From 9b2eedb85d53ca32610c32c6e50b5230ab3b16cf Mon Sep 17 00:00:00 2001
From: sean.zhou <sean.zhou@dji.com>
Date: Fri, 22 Jul 2022 20:16:03 +0800
Subject: [PATCH] V1.1.0 for dock
---
src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java | 6
src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java | 3
src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java | 136
src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java | 18
src/main/java/com/dji/sample/media/model/MediaFileDTO.java | 6
src/main/java/com/dji/sample/wayline/model/dto/FLightTaskProgress.java | 16
src/main/java/com/dji/sample/storage/service/impl/StorageServiceImpl.java | 56
src/main/java/com/dji/sample/manage/service/impl/WorkspaceServiceImpl.java | 60
src/main/java/com/dji/sample/component/mqtt/handler/StatusRouter.java | 67
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskFileDTO.java | 22
src/main/java/com/dji/sample/manage/service/IUserService.java | 14
src/main/java/com/dji/sample/component/mqtt/handler/RequestsRouter.java | 49
src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java | 8
src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java | 36
src/main/java/com/dji/sample/component/mqtt/handler/InboundMessageRouter.java | 118
src/main/java/com/dji/sample/manage/controller/LoginController.java | 5
src/main/java/com/dji/sample/component/mqtt/model/StateDataEnum.java | 26
src/main/java/com/dji/sample/component/mqtt/handler/StateRouter.java | 104
src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java | 6
src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java | 7
src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java | 212 +
src/main/java/com/dji/sample/media/model/CredentialsDTO.java | 10
src/main/java/com/dji/sample/manage/controller/DeviceController.java | 106
src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java | 43
src/main/java/com/dji/sample/wayline/model/entity/WaylineJobEntity.java | 56
src/main/java/com/dji/sample/component/mqtt/model/Chan.java | 45
src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java | 90
src/main/java/com/dji/sample/wayline/model/entity/WaylineFileEntity.java | 62
src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java | 52
src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java | 56
src/main/java/com/dji/sample/wayline/model/dto/WaylineFileUploadDTO.java | 18
src/main/java/com/dji/sample/media/model/MediaFileEntity.java | 3
src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java | 112
src/main/java/com/dji/sample/media/service/IFileService.java | 19
src/main/java/com/dji/sample/manage/model/entity/UserEntity.java | 2
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressExt.java | 16
src/main/java/com/dji/sample/wayline/service/IFlightTaskService.java | 18
src/main/java/com/dji/sample/manage/service/impl/CameraVideoServiceImpl.java | 83
src/main/java/com/dji/sample/component/mqtt/handler/StateLiveCapacityHandler.java | 39
src/main/java/com/dji/sample/component/mqtt/model/RequestsMethodEnum.java | 38
src/main/java/com/dji/sample/manage/service/IDeviceDictionaryService.java | 4
src/main/java/com/dji/sample/common/error/CommonErrorEnum.java | 10
src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java | 7
src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java | 7
src/main/java/com/dji/sample/manage/service/ILiveStreamService.java | 9
src/main/java/com/dji/sample/wayline/model/param/WaylineQueryParam.java | 30
src/main/java/com/dji/sample/manage/controller/DeviceHmsController.java | 53
src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java | 26
src/main/java/com/dji/sample/manage/controller/LiveStreamController.java | 21
src/main/java/com/dji/sample/manage/model/receiver/BindStatusReceiver.java | 30
src/main/java/com/dji/sample/component/mqtt/model/EventsReceiver.java | 21
pom.xml | 31
src/main/java/com/dji/sample/component/ApplicationBootInitial.java | 24
src/main/java/com/dji/sample/manage/controller/UserController.java | 41
src/main/java/com/dji/sample/component/websocket/service/IWebSocketManageService.java | 23
src/main/java/com/dji/sample/common/util/JwtUtil.java | 4
src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java | 73
src/main/java/com/dji/sample/manage/model/receiver/StorageReceiver.java | 16
src/main/java/com/dji/sample/manage/model/receiver/DockSdrReceiver.java | 18
src/main/java/com/dji/sample/manage/model/receiver/OsdDockReceiver.java | 67
src/main/java/com/dji/sample/manage/model/receiver/PositionStateReceiver.java | 2
src/main/java/com/dji/sample/manage/model/receiver/LiveCapacityReceiver.java | 20
src/main/java/com/dji/sample/component/mqtt/model/ErrorInfoReply.java | 23
src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java | 38
src/main/java/com/dji/sample/component/mqtt/model/ServiceReply.java | 20
src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java | 54
src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java | 10
src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java | 2
src/main/java/com/dji/sample/media/service/IMediaService.java | 16
src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java | 84
src/main/java/com/dji/sample/component/mqtt/handler/StateDeviceBasicHandler.java | 38
src/main/java/com/dji/sample/component/mqtt/model/ServicesMethodEnum.java | 29
src/main/java/com/dji/sample/manage/dao/IDeviceHmsMapper.java | 12
src/main/java/com/dji/sample/manage/model/receiver/WirelessLinkStateReceiver.java | 2
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskCreateDTO.java | 24
src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java | 155 +
src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java | 19
src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java | 28
src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java | 14
src/main/java/com/dji/sample/manage/model/receiver/OsdPayloadReceiver.java | 33
src/main/java/com/dji/sample/map/controller/WorkspaceElementController.java | 13
src/main/java/com/dji/sample/manage/service/ITSAService.java | 18
src/main/java/com/dji/sample/manage/model/receiver/OsdSubDeviceReceiver.java | 8
src/main/resources/application.yml | 80
src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java | 129
src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java | 28
src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java | 30
src/main/java/com/dji/sample/component/oss/service/IOssService.java | 18
src/main/java/com/dji/sample/component/mqtt/handler/StateDefaultHandler.java | 26
src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java | 19
src/main/java/com/dji/sample/component/oss/model/enums/OssTypeEnum.java | 28
sql/cloud_sample.sql | 157
src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java | 676 ++++-
src/main/java/com/dji/sample/CloudApiSampleApplication.java | 1
src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java | 4
src/main/java/com/dji/sample/storage/controller/StorageController.java | 21
src/main/java/com/dji/sample/wayline/model/param/CreateJobParam.java | 22
api/Cloud API Demo.postman_collection.json | 328 ++
src/main/java/com/dji/sample/wayline/model/dto/WaylineFileDTO.java | 43
src/main/java/com/dji/sample/manage/model/dto/UserListDTO.java | 34
src/main/java/com/dji/sample/wayline/dao/IWaylineJobMapper.java | 12
src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java | 2
src/main/java/com/dji/sample/manage/model/common/HmsMessage.java | 16
README.md | 6
src/main/java/com/dji/sample/manage/service/ICameraVideoService.java | 26
src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java | 22
src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java | 135 +
src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java | 58
src/main/java/com/dji/sample/component/redis/RedisConfiguration.java | 63
src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java | 58
src/main/java/com/dji/sample/component/mqtt/handler/StateFirmwareVersionHandler.java | 62
src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java | 3
src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java | 56
src/main/java/com/dji/sample/common/error/StorageErrorEnum.java | 38
src/main/java/com/dji/sample/component/GlobalScheduleService.java | 53
src/main/java/com/dji/sample/manage/model/receiver/NetworkStateReceiver.java | 18
src/main/java/com/dji/sample/component/redis/RedisConst.java | 29
src/main/java/com/dji/sample/wayline/service/IWaylineFileService.java | 21
src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java | 27
src/main/java/com/dji/sample/manage/model/receiver/FirmwareVersionReceiver.java | 29
src/main/java/com/dji/sample/media/controller/FileController.java | 35
src/main/java/com/dji/sample/manage/model/receiver/AlternateLandPointReceiver.java | 18
src/main/java/com/dji/sample/media/controller/MediaController.java | 24
src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java | 5
src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java | 4
src/main/java/com/dji/sample/manage/model/receiver/HmsArgsReceiver.java | 18
src/main/java/com/dji/sample/manage/service/impl/DockOSDServiceImpl.java | 50
src/main/java/com/dji/sample/manage/model/receiver/OrganizationGetReceiver.java | 16
src/main/java/com/dji/sample/media/model/FileExtensionDTO.java | 2
src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java | 4
src/main/java/com/dji/sample/manage/service/ICapacityCameraService.java | 17
src/main/java/com/dji/sample/manage/model/receiver/BindDeviceReceiver.java | 22
src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java | 187 +
src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java | 53
src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java | 78
src/main/java/com/dji/sample/manage/model/entity/DeviceHmsEntity.java | 76
src/main/java/com/dji/sample/manage/model/receiver/DroneChargeStateReceiver.java | 16
src/main/java/com/dji/sample/component/mqtt/model/RequestsReply.java | 44
src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java | 94
src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java | 48
src/main/java/com/dji/sample/manage/service/IWorkspaceService.java | 24
src/main/java/com/dji/sample/component/mqtt/handler/AbstractStateTopicHandler.java | 39
src/main/java/com/dji/sample/manage/service/IDeviceService.java | 71
src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java | 133 +
src/main/java/com/dji/sample/media/model/FileUploadCallback.java | 18
api/Cloud API Demo.postman_environment.json | 6
src/main/java/com/dji/sample/manage/model/receiver/DockMediaFileDetailReceiver.java | 14
src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java | 2
src/main/java/com/dji/sample/manage/model/receiver/DockSubDeviceReceiver.java | 20
src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java | 2
src/main/java/com/dji/sample/configuration/SpringBeanConfiguration.java | 49
src/main/java/com/dji/sample/manage/model/receiver/StatusSubDeviceReceiver.java | 2
src/main/java/com/dji/sample/manage/model/common/HmsJsonUtil.java | 49
src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java | 29
src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java | 4
src/main/java/com/dji/sample/manage/model/enums/PayloadModelEnum.java | 61
src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java | 6
src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java | 26
src/main/java/com/dji/sample/manage/model/dto/DeviceHmsDTO.java | 57
src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java | 56
src/main/java/com/dji/sample/manage/service/impl/DeviceDictionaryServiceImpl.java | 6
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressReceiver.java | 19
src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java | 11
src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java | 74
src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java | 33
src/main/java/com/dji/sample/manage/model/param/DeviceHmsQueryParam.java | 45
src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java | 8
src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java | 4
src/main/java/com/dji/sample/manage/model/receiver/OsdDockTransmissionReceiver.java | 18
src/main/java/com/dji/sample/wayline/dao/IWaylineFileMapper.java | 2
src/main/java/com/dji/sample/manage/service/impl/TopologyServiceImpl.java | 2
src/main/java/com/dji/sample/manage/service/IDeviceHmsService.java | 21
src/main/java/com/dji/sample/storage/service/IStorageService.java | 9
173 files changed, 6,127 insertions(+), 1,002 deletions(-)
diff --git a/README.md b/README.md
index 2071047..faf73ce 100644
--- a/README.md
+++ b/README.md
@@ -6,15 +6,15 @@
## 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
diff --git a/api/Cloud API Demo.postman_collection.json b/api/Cloud API Demo.postman_collection.json
index 6c380a8..fc0fd32 100644
--- a/api/Cloud API Demo.postman_collection.json
+++ b/api/Cloud API Demo.postman_collection.json
@@ -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 @@
"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 @@
},
{
"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 @@
"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 @@
}
},
"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 @@
"apikey": [
{
"key": "value",
- "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
+ "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTMzNzI3NDUsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTM0NTkxNDUsImlhdCI6MTY1MzM3Mjc0NSwidXNlcm5hbWUiOiJhZG1pblBDIn0.Zyb_f4umcGY2-WDaQKA1LHGOs9qYfJuPc3rQeIS-4hY",
"type": "string"
},
{
@@ -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 @@
}
},
"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 @@
"{{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 @@
"apikey": [
{
"key": "value",
- "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
+ "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTgzOTIyNzksImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTg0Nzg2NzksImlhdCI6MTY1ODM5MjI3OSwidXNlcm5hbWUiOiJhZG1pblBDIn0.ErClyQS1YzoQVBcLYxpFEiyFTb1L-eg2-vsudlL9WJU",
"type": "string"
},
{
@@ -622,7 +783,7 @@
"apikey": [
{
"key": "value",
- "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
+ "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA",
"type": "string"
},
{
@@ -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 @@
"apikey": [
{
"key": "value",
- "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Mzg5MzY2OTEsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2MzkwMjMwOTEsImlhdCI6MTYzODkzNjY5MSwidXNlcm5hbWUiOiJhZG1pblBDIn0.W_v88rbhVKivl61MnJ0Cz_0Eq6Gw0RotiHCdLj0UPSQ",
+ "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTA0MjY3MzAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTA1MTMxMzAsImlhdCI6MTY1MDQyNjczMCwidXNlcm5hbWUiOiJhZG1pblBDIn0.-FBpi0ktuZ68jV6-HQ7mwm8iC07YH-Hw2aRiREzJ8hs",
"type": "string"
},
{
diff --git a/api/Cloud API Demo.postman_environment.json b/api/Cloud API Demo.postman_environment.json
index f4faf3a..d2360f1 100644
--- a/api/Cloud API Demo.postman_environment.json
+++ b/api/Cloud API Demo.postman_environment.json
@@ -4,7 +4,7 @@
"values": [
{
"key": "ip",
- "value": "192.168.1.1",
+ "value": "localhost",
"type": "default",
"enabled": true
},
@@ -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"
}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 5cbe4c6..b45b2f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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 @@
<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>
diff --git a/sql/cloud_sample.sql b/sql/cloud_sample.sql
index 6f0e968..f644248 100644
--- a/sql/cloud_sample.sql
+++ b/sql/cloud_sample.sql
@@ -10,40 +10,8 @@
/*!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
+# manage_device
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device`;
@@ -52,25 +20,31 @@
`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;
-# manage_device_dictionary
+# manage_device_dictionary
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device_dictionary`;
@@ -106,15 +80,37 @@
(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_payload
+# manage_device_hms
+# ------------------------------------------------------------
+
+DROP TABLE IF EXISTS `manage_device_hms`;
+
+CREATE TABLE `manage_device_hms` (
+ `id` int unsigned NOT NULL AUTO_INCREMENT,
+ `hms_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
+ `tid` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+ `bid` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+ `sn` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+ `level` smallint NOT NULL,
+ `module` tinyint NOT NULL,
+ `hms_key` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
+ `message_zh` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+ `message_en` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+ `create_time` bigint NOT NULL,
+ `update_time` bigint NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `UNIQUE_hms_id` (`hms_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
+
+
+# manage_device_payload
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device_payload`;
@@ -125,7 +121,7 @@
`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,
@@ -137,7 +133,7 @@
-# manage_user
+# manage_user
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_user`;
@@ -147,7 +143,7 @@
`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,14 +158,14 @@
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;
-# manage_workspace
+# manage_workspace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_workspace`;
@@ -182,22 +178,24 @@
`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;
-# map_element_coordinate
+# map_element_coordinate
# ------------------------------------------------------------
DROP TABLE IF EXISTS `map_element_coordinate`;
@@ -213,7 +211,7 @@
-# map_group
+# map_group
# ------------------------------------------------------------
DROP TABLE IF EXISTS `map_group`;
@@ -244,7 +242,7 @@
UNLOCK TABLES;
-# map_group_element
+# map_group_element
# ------------------------------------------------------------
DROP TABLE IF EXISTS `map_group_element`;
@@ -267,7 +265,7 @@
-# media_file
+# media_file
# ------------------------------------------------------------
DROP TABLE IF EXISTS `media_file`;
@@ -277,22 +275,22 @@
`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;
-# wayline_file
+# wayline_file
# ------------------------------------------------------------
DROP TABLE IF EXISTS `wayline_file`;
@@ -304,18 +302,41 @@
`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 */;
diff --git a/src/main/java/com/dji/sample/CloudApiSampleApplication.java b/src/main/java/com/dji/sample/CloudApiSampleApplication.java
index 14cca32..a3619ab 100644
--- a/src/main/java/com/dji/sample/CloudApiSampleApplication.java
+++ b/src/main/java/com/dji/sample/CloudApiSampleApplication.java
@@ -8,6 +8,7 @@
@MapperScan("com.dji.sample.*.dao")
@SpringBootApplication
@EnableScheduling
+//@EnableConfigurationProperties(OssConfiguration.class)
public class CloudApiSampleApplication {
public static void main(String[] args) {
diff --git a/src/main/java/com/dji/sample/common/error/CommonErrorEnum.java b/src/main/java/com/dji/sample/common/error/CommonErrorEnum.java
index 1dab9d1..290cc42 100644
--- a/src/main/java/com/dji/sample/common/error/CommonErrorEnum.java
+++ b/src/main/java/com/dji/sample/common/error/CommonErrorEnum.java
@@ -7,6 +7,16 @@
*/
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"),
diff --git a/src/main/java/com/dji/sample/common/error/StorageErrorEnum.java b/src/main/java/com/dji/sample/common/error/StorageErrorEnum.java
new file mode 100644
index 0000000..16b5d2f
--- /dev/null
+++ b/src/main/java/com/dji/sample/common/error/StorageErrorEnum.java
@@ -0,0 +1,38 @@
+package com.dji.sample.common.error;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/25
+ */
+public enum StorageErrorEnum implements IErrorInfo {
+
+ GENERATE_CREDENTIALS_ERROR(217001, "Failed to generate temporary credentials."),
+
+ NO_BUCKET(217002, "The bucket does not exist."),
+
+ ILLEGAL_PATH_FORMAT(217006, "Illegal path format."),
+
+ FILE_CREATION_FAILED(217007, "File creation failed."),
+
+ DIR_CREATION_FAILED(217008, "Directory creation failed");
+
+ private String msg;
+
+ private int code;
+
+ StorageErrorEnum(int code, String msg) {
+ this.msg = msg;
+ this.code = code;
+ }
+
+ @Override
+ public String getErrorMsg() {
+ return msg;
+ }
+
+ @Override
+ public Integer getErrorCode() {
+ return code;
+ }
+}
diff --git a/src/main/java/com/dji/sample/common/util/JwtUtil.java b/src/main/java/com/dji/sample/common/util/JwtUtil.java
index 9c2cb9a..629cea1 100644
--- a/src/main/java/com/dji/sample/common/util/JwtUtil.java
+++ b/src/main/java/com/dji/sample/common/util/JwtUtil.java
@@ -54,6 +54,10 @@
JwtUtil.algorithm = Algorithm.HMAC256(secret);
}
+ private JwtUtil() {
+
+ }
+
/**
* Create a token based on custom information.
* @param claims custom information
diff --git a/src/main/java/com/dji/sample/component/ApplicationBootInitial.java b/src/main/java/com/dji/sample/component/ApplicationBootInitial.java
index 226fe1a..f35aa3c 100644
--- a/src/main/java/com/dji/sample/component/ApplicationBootInitial.java
+++ b/src/main/java/com/dji/sample/component/ApplicationBootInitial.java
@@ -1,14 +1,11 @@
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
@@ -21,20 +18,21 @@
@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)));
+
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/GlobalScheduleService.java b/src/main/java/com/dji/sample/component/GlobalScheduleService.java
index ea44a62..2813388 100644
--- a/src/main/java/com/dji/sample/component/GlobalScheduleService.java
+++ b/src/main/java/com/dji/sample/component/GlobalScheduleService.java
@@ -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,12 +11,8 @@
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
@@ -26,33 +26,34 @@
@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());
+ }
+ redisOps.del(key);
}
+ });
- 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;
- }
-
- deviceService.subDeviceOffline(sn);
- }
+ log.info("Subscriptions: {}", Arrays.toString(topicService.getSubscribedTopic()));
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java b/src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java
index df6f04f..3964aaf 100644
--- a/src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java
+++ b/src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java
@@ -11,6 +11,7 @@
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 @@
@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());
};
}
diff --git a/src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java b/src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java
index 2f06938..3d54599 100644
--- a/src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java
+++ b/src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java
@@ -74,7 +74,7 @@
@Bean(name = ChannelName.INBOUND_OSD)
public MessageChannel osdChannel() {
- return new DirectChannel();
+ return new ExecutorChannel(threadPool);
}
@Bean(name = ChannelName.DEFAULT)
@@ -87,4 +87,54 @@
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();
+ }
+
}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/AbstractStateTopicHandler.java b/src/main/java/com/dji/sample/component/mqtt/handler/AbstractStateTopicHandler.java
new file mode 100644
index 0000000..c3969f3
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/AbstractStateTopicHandler.java
@@ -0,0 +1,39 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.redis.RedisOpsUtils;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Map;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2022/2/21
+ */
+public abstract class AbstractStateTopicHandler {
+
+ protected AbstractStateTopicHandler handler;
+
+ @Autowired
+ protected ObjectMapper mapper;
+
+ @Autowired
+ protected RedisOpsUtils redisOps;
+
+ protected AbstractStateTopicHandler(AbstractStateTopicHandler handler) {
+ this.handler = handler;
+ }
+
+ /**
+ * Passing dataNode data, using different processing methods depending on the data selection.
+ * @param dataNode
+ * @param stateReceiver
+ * @param sn
+ * @return
+ * @throws JsonProcessingException
+ */
+ public abstract CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException;
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java b/src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java
new file mode 100644
index 0000000..a2baabe
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java
@@ -0,0 +1,48 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.ChannelName;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.mqtt.model.EventsMethodEnum;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.dsl.IntegrationFlow;
+import org.springframework.integration.dsl.IntegrationFlows;
+
+import java.io.IOException;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@Configuration
+public class EventsRouter {
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ @Bean
+ public IntegrationFlow eventsMethodRouterFlow() {
+ return IntegrationFlows
+ .from(ChannelName.INBOUND_EVENTS)
+ .<byte[], CommonTopicReceiver>transform(payload -> {
+ try {
+ return mapper.readValue(payload, CommonTopicReceiver.class);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return new CommonTopicReceiver();
+ })
+ .<CommonTopicReceiver, EventsMethodEnum>route(
+ receiver -> EventsMethodEnum.find(receiver.getMethod()),
+ mapping -> {
+ mapping.channelMapping(EventsMethodEnum.FILE_UPLOAD_CALLBACK, ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK);
+ mapping.channelMapping(EventsMethodEnum.FLIGHT_TASK_PROGRESS, ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS);
+ mapping.channelMapping(EventsMethodEnum.HMS, ChannelName.INBOUND_EVENTS_HMS);
+ mapping.channelMapping(EventsMethodEnum.UNKNOWN, ChannelName.DEFAULT);
+ })
+ .get();
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/InboundMessageRouter.java b/src/main/java/com/dji/sample/component/mqtt/handler/InboundMessageRouter.java
new file mode 100644
index 0000000..3047ea5
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/InboundMessageRouter.java
@@ -0,0 +1,118 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.ChannelName;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.integration.annotation.Router;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.integration.router.AbstractMessageRouter;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Pattern;
+
+import static com.dji.sample.component.mqtt.model.TopicConst.*;
+
+/**
+ *
+ * @author sean.zhou
+ * @date 2021/11/10
+ * @version 0.1
+ */
+@Component
+@Slf4j
+public class InboundMessageRouter extends AbstractMessageRouter {
+
+ @Resource(name = ChannelName.INBOUND)
+ private MessageChannel inboundChannel;
+
+ @Resource(name = ChannelName.INBOUND_STATUS)
+ private MessageChannel statusChannel;
+
+ @Resource(name = ChannelName.INBOUND_STATE)
+ private MessageChannel stateChannel;
+
+ @Resource(name = ChannelName.DEFAULT)
+ private MessageChannel defaultChannel;
+
+ @Resource(name = ChannelName.INBOUND_SERVICE_REPLY)
+ private MessageChannel serviceReplyChannel;
+
+ @Resource(name = ChannelName.INBOUND_OSD)
+ private MessageChannel osdChannel;
+
+ @Resource(name = ChannelName.INBOUND_REQUESTS)
+ private MessageChannel requestsChannel;
+
+ @Resource(name = ChannelName.INBOUND_EVENTS)
+ private MessageChannel eventsChannel;
+
+ private static final Pattern PATTERN_TOPIC_STATUS =
+ Pattern.compile("^" + BASIC_PRE + PRODUCT + REGEX_SN + STATUS_SUF + "$");
+
+ private static final Pattern PATTERN_TOPIC_STATE =
+ Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + STATE_SUF + "$");
+
+ private static final Pattern PATTERN_TOPIC_SERVICE_REPLY =
+ Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + SERVICES_SUF + _REPLY_SUF + "$");
+
+ private static final Pattern PATTERN_TOPIC_OSD =
+ Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + OSD_SUF + "$");
+
+ private static final Pattern PATTERN_TOPIC_REQUESTS =
+ Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + REQUESTS_SUF + "$");
+
+ private static final Pattern PATTERN_TOPIC_EVENTS =
+ Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + EVENTS_SUF + "$");
+
+ /**
+ * All mqtt broker messages will arrive here before distributing them to different channels.
+ * @param message message from mqtt broker
+ * @return channel
+ */
+ @Override
+ @Router(inputChannel = ChannelName.INBOUND)
+ protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
+ MessageHeaders headers = message.getHeaders();
+ String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString();
+ byte[] payload = (byte[])message.getPayload();
+
+ // osd
+ if (PATTERN_TOPIC_OSD.matcher(topic).matches()) {
+ return Collections.singleton(osdChannel);
+ }
+
+ log.debug("received topic :{} \t payload :{}", topic, new String(payload));
+
+ // status
+ if (PATTERN_TOPIC_STATUS.matcher(topic).matches()) {
+ return Collections.singleton(statusChannel);
+ }
+
+ // state
+ if (PATTERN_TOPIC_STATE.matcher(topic).matches()) {
+ return Collections.singleton(stateChannel);
+ }
+
+ // services_reply
+ if (PATTERN_TOPIC_SERVICE_REPLY.matcher(topic).matches()) {
+ return Collections.singleton(serviceReplyChannel);
+ }
+
+ // requests
+ if (PATTERN_TOPIC_REQUESTS.matcher(topic).matches()) {
+ return Collections.singleton(requestsChannel);
+ }
+
+ // events
+ if (PATTERN_TOPIC_EVENTS.matcher(topic).matches()) {
+ return Collections.singleton(eventsChannel);
+ }
+
+ return Collections.singleton(defaultChannel);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/RequestsRouter.java b/src/main/java/com/dji/sample/component/mqtt/handler/RequestsRouter.java
new file mode 100644
index 0000000..753bad2
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/RequestsRouter.java
@@ -0,0 +1,49 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.ChannelName;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.mqtt.model.RequestsMethodEnum;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.dsl.IntegrationFlow;
+import org.springframework.integration.dsl.IntegrationFlows;
+
+import java.io.IOException;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/25
+ */
+@Configuration
+public class RequestsRouter {
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ @Bean
+ public IntegrationFlow requestsMethodRouterFlow() {
+ return IntegrationFlows
+ .from(ChannelName.INBOUND_REQUESTS)
+ .<byte[], CommonTopicReceiver>transform(payload -> {
+ try {
+ return mapper.readValue(payload, CommonTopicReceiver.class);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return new CommonTopicReceiver();
+ })
+ .<CommonTopicReceiver, RequestsMethodEnum>route(
+ receiver -> RequestsMethodEnum.find(receiver.getMethod()),
+ mapping -> {
+ mapping.channelMapping(RequestsMethodEnum.STORAGE_CONFIG_GET, ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET);
+ mapping.channelMapping(RequestsMethodEnum.AIRPORT_BIND_STATUS, ChannelName.INBOUND_REQUESTS_AIRPORT_BIND_STATUS);
+ mapping.channelMapping(RequestsMethodEnum.AIRPORT_ORGANIZATION_GET, ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_GET);
+ mapping.channelMapping(RequestsMethodEnum.AIRPORT_ORGANIZATION_BIND, ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND);
+ mapping.channelMapping(RequestsMethodEnum.UNKNOWN, ChannelName.DEFAULT);
+ })
+ .get();
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/StateDefaultHandler.java b/src/main/java/com/dji/sample/component/mqtt/handler/StateDefaultHandler.java
new file mode 100644
index 0000000..a1d2624
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/StateDefaultHandler.java
@@ -0,0 +1,26 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2022/3/21
+ */
+@Service
+public class StateDefaultHandler extends AbstractStateTopicHandler {
+
+ protected StateDefaultHandler() {
+ super(null);
+ }
+
+ @Override
+ public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
+ // If no suitable handler is found for the data, it is not processed.
+ return stateReceiver;
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/StateDeviceBasicHandler.java b/src/main/java/com/dji/sample/component/mqtt/handler/StateDeviceBasicHandler.java
new file mode 100644
index 0000000..b85ebca
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/StateDeviceBasicHandler.java
@@ -0,0 +1,38 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.mqtt.model.StateDataEnum;
+import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2022/2/21
+ */
+@Service
+public class StateDeviceBasicHandler extends AbstractStateTopicHandler {
+
+ public StateDeviceBasicHandler(@Autowired @Qualifier("stateLiveCapacityHandler") AbstractStateTopicHandler handler) {
+ super(handler);
+ }
+
+ @Override
+ public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
+ // handle device basic data
+ if (dataNode.containsKey(StateDataEnum.PAYLOADS.getDesc())) {
+ DeviceBasicReceiver data = mapper.convertValue(stateReceiver.getData(), DeviceBasicReceiver.class);
+ data.setDeviceSn(sn);
+ data.getPayloads().forEach(payload -> payload.setDeviceSn(sn));
+
+ stateReceiver.setData(data);
+ return stateReceiver;
+ }
+ return handler.handleState(dataNode, stateReceiver, sn);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/StateFirmwareVersionHandler.java b/src/main/java/com/dji/sample/component/mqtt/handler/StateFirmwareVersionHandler.java
new file mode 100644
index 0000000..aceeae4
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/StateFirmwareVersionHandler.java
@@ -0,0 +1,62 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.mqtt.model.StateDataEnum;
+import com.dji.sample.manage.model.enums.DeviceDomainEnum;
+import com.dji.sample.manage.model.enums.PayloadModelEnum;
+import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2022/2/21
+ */
+@Service
+public class StateFirmwareVersionHandler extends AbstractStateTopicHandler {
+
+ protected StateFirmwareVersionHandler(@Autowired @Qualifier("stateDefaultHandler") AbstractStateTopicHandler handler) {
+ super(handler);
+ }
+
+ @Override
+ public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
+ // Parse the firmware version of the device.
+ if (dataNode.containsKey(StateDataEnum.FIRMWARE_VERSION.getDesc())) {
+ FirmwareVersionReceiver firmware = mapper.convertValue(dataNode, FirmwareVersionReceiver.class);
+ firmware.setSn(sn);
+ firmware.setDomain(DeviceDomainEnum.SUB_DEVICE);
+ stateReceiver.setData(firmware);
+ return stateReceiver;
+ }
+
+ // Parse the firmware version of the payload.
+ List<String> payloads = PayloadModelEnum.getAllModel();
+ long count = dataNode.keySet()
+ .stream()
+ .map(key -> {
+ int end = key.indexOf("-");
+ return end == -1 ? key : key.substring(0, end);
+ })
+ .filter(payloads::contains)
+ .count();
+ if (count > 0) {
+ FirmwareVersionReceiver firmware = FirmwareVersionReceiver.builder()
+ .firmwareVersion(((Map<String, String>)(dataNode.values().iterator().next()))
+ .get(StateDataEnum.FIRMWARE_VERSION.getDesc()))
+ .sn(sn)
+ .domain(DeviceDomainEnum.PAYLOAD)
+ .build();
+ stateReceiver.setData(firmware);
+ return stateReceiver;
+ }
+
+ return handler.handleState(dataNode, stateReceiver, sn);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/StateLiveCapacityHandler.java b/src/main/java/com/dji/sample/component/mqtt/handler/StateLiveCapacityHandler.java
new file mode 100644
index 0000000..dc593ab
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/StateLiveCapacityHandler.java
@@ -0,0 +1,39 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.mqtt.model.StateDataEnum;
+import com.dji.sample.manage.model.receiver.LiveCapacityReceiver;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2022/2/21
+ */
+@Service
+@Slf4j
+public class StateLiveCapacityHandler extends AbstractStateTopicHandler {
+
+ protected StateLiveCapacityHandler(@Autowired @Qualifier("stateFirmwareVersionHandler") AbstractStateTopicHandler handler) {
+ super(handler);
+ }
+
+ @Override
+ public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
+ // Determine if it is live capacity data based on name.
+ if (dataNode.containsKey(StateDataEnum.LIVE_CAPACITY.getDesc())) {
+ stateReceiver.setData(mapper.convertValue(
+ dataNode.get(StateDataEnum.LIVE_CAPACITY.getDesc()),
+ LiveCapacityReceiver.class));
+ log.info("Analyze live stream capabilities.");
+ return stateReceiver;
+ }
+ return handler.handleState(dataNode, stateReceiver, sn);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/StateRouter.java b/src/main/java/com/dji/sample/component/mqtt/handler/StateRouter.java
new file mode 100644
index 0000000..4f0e1e5
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/StateRouter.java
@@ -0,0 +1,104 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.ChannelName;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
+import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
+import com.dji.sample.manage.model.receiver.LiveCapacityReceiver;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.annotation.MessageEndpoint;
+import org.springframework.integration.annotation.Router;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.annotation.Splitter;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.integration.router.MessageRouter;
+import org.springframework.integration.router.PayloadTypeRouter;
+import org.springframework.messaging.Message;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import static com.dji.sample.component.mqtt.model.TopicConst.*;
+
+/**
+ *
+ * @author sean.zhou
+ * @date 2021/11/17
+ * @version 0.1
+ */
+@MessageEndpoint
+@Slf4j
+@Configuration
+public class StateRouter {
+
+ @Resource(name = "stateDeviceBasicHandler")
+ private AbstractStateTopicHandler handler;
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ /**
+ * Handles the routing of state topic messages. Depending on the data, it is assigned to different channels for handling.
+ * @param message
+ * @return
+ * @throws IOException
+ */
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE, outputChannel = ChannelName.INBOUND_STATE_SPLITTER)
+ public CommonTopicReceiver<?> resolveStateData(Message<?> message) throws IOException {
+ byte[] payload = (byte[])message.getPayload();
+ String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
+
+ CommonTopicReceiver stateReceiver = mapper.readValue(payload, CommonTopicReceiver.class);
+ // Get the sn of the topic source.
+ String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(),
+ topic.indexOf(STATE_SUF));
+
+ try {
+ Map<String, Object> data = (Map<String, Object>) (stateReceiver.getData());
+
+ return handler.handleState(data, stateReceiver, from);
+
+ } catch (UnrecognizedPropertyException e) {
+ log.info("The {} data is not processed.", e.getPropertyName());
+ }
+ return stateReceiver;
+ }
+
+ /**
+ * Split the state message data to different channels for handling according to their different types.
+ * @param receiver state message
+ * @return
+ */
+ @Splitter(inputChannel = ChannelName.INBOUND_STATE_SPLITTER, outputChannel = ChannelName.INBOUND_STATE_ROUTER)
+ public Collection<Object> splitState(CommonTopicReceiver receiver) {
+ ArrayList<Object> type = new ArrayList<>();
+ type.add(receiver.getData());
+ return type;
+ }
+
+ @Bean
+ @Router(inputChannel = ChannelName.INBOUND_STATE_ROUTER)
+ public MessageRouter resolveStateRouter() {
+ PayloadTypeRouter router = new PayloadTypeRouter();
+ // Channel mapping for basic data.
+ router.setChannelMapping(DeviceBasicReceiver.class.getName(),
+ ChannelName.INBOUND_STATE_BASIC);
+ // Channel mapping for live streaming capabilities.
+ router.setChannelMapping(LiveCapacityReceiver.class.getName(),
+ ChannelName.INBOUND_STATE_CAPACITY);
+ router.setChannelMapping(FirmwareVersionReceiver.class.getName(),
+ ChannelName.INBOUND_STATE_FIRMWARE_VERSION);
+ router.setChannelMapping(Map.class.getName(),
+ ChannelName.DEFAULT);
+ return router;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/handler/StatusRouter.java b/src/main/java/com/dji/sample/component/mqtt/handler/StatusRouter.java
new file mode 100644
index 0000000..0b34137
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/handler/StatusRouter.java
@@ -0,0 +1,67 @@
+package com.dji.sample.component.mqtt.handler;
+
+import com.dji.sample.component.mqtt.model.ChannelName;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.manage.model.receiver.StatusGatewayReceiver;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.integration.annotation.MessageEndpoint;
+import org.springframework.integration.annotation.Router;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.Message;
+import org.springframework.util.CollectionUtils;
+
+import static com.dji.sample.component.mqtt.model.TopicConst.*;
+
+/**
+ *
+ * @author sean.zhou
+ * @date 2021/11/12
+ * @version 0.1
+ */
+@MessageEndpoint
+public class StatusRouter {
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ /**
+ * Converts the status data sent by the gateway device into an object.
+ * @param message
+ * @return
+ */
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_STATUS, outputChannel = ChannelName.INBOUND_STATUS_ROUTER)
+ public CommonTopicReceiver<StatusGatewayReceiver> resolveStatus(Message<?> message) {
+ CommonTopicReceiver<StatusGatewayReceiver> statusReceiver = new CommonTopicReceiver<>();
+ try {
+ statusReceiver = mapper.readValue(
+ (byte[])message.getPayload(),
+ new TypeReference<CommonTopicReceiver<StatusGatewayReceiver>>() {});
+
+ String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
+
+ // set gateway's sn
+ statusReceiver.getData().setSn(
+ topic.substring((BASIC_PRE + PRODUCT).length(),
+ topic.indexOf(STATUS_SUF)));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return statusReceiver;
+ }
+
+ /**
+ * Handles the routing of status topic messages. Depending on the data, it is assigned to different channels for handling.
+ * @param receiver
+ * @return
+ */
+ @Router(inputChannel = ChannelName.INBOUND_STATUS_ROUTER)
+ public String resolveStatusRouter(CommonTopicReceiver<StatusGatewayReceiver> receiver) {
+ // Determine whether the drone is online or offline according to whether the data of the sub-device is empty.
+ return CollectionUtils.isEmpty(receiver.getData().getSubDevices()) ?
+ ChannelName.INBOUND_STATUS_OFFLINE : ChannelName.INBOUND_STATUS_ONLINE;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/Chan.java b/src/main/java/com/dji/sample/component/mqtt/model/Chan.java
new file mode 100644
index 0000000..8fa6c64
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/Chan.java
@@ -0,0 +1,45 @@
+package com.dji.sample.component.mqtt.model;
+
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * The demo is only for functional closure, which is not recommended.
+ * @author sean.zhou
+ * @date 2021/11/22
+ * @version 0.1
+ */
+public class Chan<T> {
+
+ private static final long THREAD_WAIT_TIME = 1000_000 * 2000;
+
+ private volatile T data;
+
+ private volatile Thread t;
+
+ private Chan () {
+
+ }
+
+ public static Chan getInstance() {
+ return ChanSingleton.INSTANCE;
+ }
+
+ public T get(Object blocker) {
+ this.t = Thread.currentThread();
+ LockSupport.parkNanos(blocker, THREAD_WAIT_TIME);
+ this.t = null;
+ return data;
+ }
+
+ public void put(T data) {
+ this.data = data;
+ if (t == null) {
+ return;
+ }
+ LockSupport.unpark(t);
+ }
+
+ private static class ChanSingleton {
+ private static final Chan<?> INSTANCE = new Chan<>();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java b/src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java
index c8f5f01..08cec5a 100644
--- a/src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java
+++ b/src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java
@@ -43,4 +43,23 @@
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";
}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java b/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java
index 5a6fe45..8770bfc 100644
--- a/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java
+++ b/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java
@@ -26,4 +26,10 @@
private Long timestamp;
private T data;
+
+ private String gateway;
+
+ private Integer needReply;
+
+ private String from;
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java b/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java
index effd5c1..e8055c0 100644
--- a/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java
+++ b/src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java
@@ -30,4 +30,6 @@
private String method;
private T data;
+
+ private Long timestamp;
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/ErrorInfoReply.java b/src/main/java/com/dji/sample/component/mqtt/model/ErrorInfoReply.java
new file mode 100644
index 0000000..160a86e
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/ErrorInfoReply.java
@@ -0,0 +1,23 @@
+package com.dji.sample.component.mqtt.model;
+
+import com.dji.sample.common.model.ResponseResult;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/14
+ */
+@Data
+@AllArgsConstructor
+public class ErrorInfoReply {
+
+ private String sn;
+
+ private Integer errCode;
+
+ public static ErrorInfoReply success(String sn) {
+ return new ErrorInfoReply(sn, ResponseResult.CODE_SUCCESS);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java b/src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java
new file mode 100644
index 0000000..2a71ac2
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java
@@ -0,0 +1,36 @@
+package com.dji.sample.component.mqtt.model;
+
+import java.util.Arrays;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+public enum EventsMethodEnum {
+
+ FLIGHT_TASK_PROGRESS("flighttask_progress"),
+
+ FILE_UPLOAD_CALLBACK("file_upload_callback"),
+
+ HMS("hms"),
+
+ UNKNOWN("Unknown");
+
+ private String method;
+
+ EventsMethodEnum(String method) {
+ this.method = method;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public static EventsMethodEnum find(String method) {
+ return Arrays.stream(EventsMethodEnum.values())
+ .filter(methodEnum -> methodEnum.method.equals(method))
+ .findAny()
+ .orElse(UNKNOWN);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/EventsReceiver.java b/src/main/java/com/dji/sample/component/mqtt/model/EventsReceiver.java
new file mode 100644
index 0000000..bff226d
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/EventsReceiver.java
@@ -0,0 +1,21 @@
+package com.dji.sample.component.mqtt.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class EventsReceiver<T> {
+
+ private Integer result;
+
+ private T output;
+
+ private String bid;
+
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java b/src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java
new file mode 100644
index 0000000..97433ff
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java
@@ -0,0 +1,29 @@
+package com.dji.sample.component.mqtt.model;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/14
+ */
+public final class MapKeyConst {
+
+ private MapKeyConst(){
+
+ }
+
+ public static final String ORGANIZATION_NAME = "organization_name";
+
+ public static final String DEVICES = "devices";
+
+ public static final String SN = "sn";
+
+ public static final String BIND_DEVICES = "bind_devices";
+
+ public static final String ERR_INFOS = "err_infos";
+
+ public static final String TINY_FINGERPRINTS = "tiny_fingerprints";
+
+ public static final String BIND_STATUS = "bind_status";
+
+ public static final String LIST = "list";
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/RequestsMethodEnum.java b/src/main/java/com/dji/sample/component/mqtt/model/RequestsMethodEnum.java
new file mode 100644
index 0000000..ddfa599
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/RequestsMethodEnum.java
@@ -0,0 +1,38 @@
+package com.dji.sample.component.mqtt.model;
+
+import java.util.Arrays;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/25
+ */
+public enum RequestsMethodEnum {
+
+ STORAGE_CONFIG_GET("storage_config_get"),
+
+ AIRPORT_BIND_STATUS("airport_bind_status"),
+
+ AIRPORT_ORGANIZATION_BIND("airport_organization_bind"),
+
+ AIRPORT_ORGANIZATION_GET("airport_organization_get"),
+
+ UNKNOWN("Unknown");
+
+ private String method;
+
+ RequestsMethodEnum(String method) {
+ this.method = method;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public static RequestsMethodEnum find(String method) {
+ return Arrays.stream(RequestsMethodEnum.values())
+ .filter(methodEnum -> methodEnum.method.equals(method))
+ .findAny()
+ .orElse(UNKNOWN);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/RequestsReply.java b/src/main/java/com/dji/sample/component/mqtt/model/RequestsReply.java
new file mode 100644
index 0000000..e788466
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/RequestsReply.java
@@ -0,0 +1,44 @@
+package com.dji.sample.component.mqtt.model;
+
+import com.dji.sample.common.error.IErrorInfo;
+import com.dji.sample.common.model.ResponseResult;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/13
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class RequestsReply<T> {
+
+ private Integer result;
+
+ private T output;
+
+
+ public static RequestsReply error(IErrorInfo errorInfo) {
+ return RequestsReply.builder()
+ .result(errorInfo.getErrorCode())
+ .output(errorInfo.getErrorMsg())
+ .build();
+ }
+
+ public static <T> RequestsReply success(T data) {
+ return RequestsReply.builder()
+ .result(ResponseResult.CODE_SUCCESS)
+ .output(data)
+ .build();
+ }
+ public static RequestsReply success() {
+ return RequestsReply.builder()
+ .result(ResponseResult.CODE_SUCCESS)
+ .build();
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/ServiceReply.java b/src/main/java/com/dji/sample/component/mqtt/model/ServiceReply.java
new file mode 100644
index 0000000..d0b1562
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/ServiceReply.java
@@ -0,0 +1,20 @@
+package com.dji.sample.component.mqtt.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+/**
+ * @author sean.zhou
+ * @version 0.1
+ * @date 2021/11/22
+ */
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ServiceReply<T> {
+
+ private Integer result;
+
+ private T info;
+
+ private T output;
+}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/ServicesMethodEnum.java b/src/main/java/com/dji/sample/component/mqtt/model/ServicesMethodEnum.java
new file mode 100644
index 0000000..4f56b15
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/ServicesMethodEnum.java
@@ -0,0 +1,29 @@
+package com.dji.sample.component.mqtt.model;
+
+/**
+ * @author sean.zhou
+ * @date 2021/11/22
+ * @version 0.1
+ */
+public enum ServicesMethodEnum {
+
+ LIVE_START_PUSH("live_start_push"),
+
+ LIVE_STOP_PUSH("live_stop_push"),
+
+ LIVE_SET_QUALITY("live_set_quality"),
+
+ FLIGHTTASK_CREATE("flighttask_create"),
+
+ UNKNOWN("unknown");
+
+ private String method;
+
+ ServicesMethodEnum(String method) {
+ this.method = method;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/StateDataEnum.java b/src/main/java/com/dji/sample/component/mqtt/model/StateDataEnum.java
new file mode 100644
index 0000000..82bed19
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/mqtt/model/StateDataEnum.java
@@ -0,0 +1,26 @@
+package com.dji.sample.component.mqtt.model;
+
+/**
+ *
+ * @author sean.zhou
+ * @date 2021/11/18
+ * @version 0.1
+ */
+public enum StateDataEnum {
+
+ FIRMWARE_VERSION("firmware_version"),
+
+ LIVE_CAPACITY("live_capacity"),
+
+ PAYLOADS("payloads");
+
+ private String desc;
+
+ StateDataEnum(String desc) {
+ this.desc = desc;
+ }
+
+ public String getDesc() {
+ return this.desc;
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java b/src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java
index 667c969..dc9df7c 100644
--- a/src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java
+++ b/src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java
@@ -24,6 +24,10 @@
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]+";
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java b/src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java
index 7930d41..152d6a8 100644
--- a/src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java
+++ b/src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java
@@ -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 @@
*/
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);
}
diff --git a/src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java b/src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java
index 2510ead..ae24b37 100644
--- a/src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java
+++ b/src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java
@@ -1,14 +1,19 @@
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
@@ -22,11 +27,11 @@
@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 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();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java b/src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java
index 88170ed..ffd6bb1 100644
--- a/src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java
+++ b/src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java
@@ -5,7 +5,7 @@
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 @@
@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 @@
@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());
}
}
diff --git a/src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java b/src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java
new file mode 100644
index 0000000..491ee44
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java
@@ -0,0 +1,94 @@
+package com.dji.sample.component.oss.model;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author sean
+ * @version 0.2
+ * @date 2021/12/9
+ */
+@ConfigurationProperties(prefix = "oss")
+@Component
+@Data
+public class OssConfiguration {
+
+ /**
+ * @see com.dji.sample.component.oss.model.enums.OssTypeEnum
+ */
+ private String provider;
+
+ /**
+ * Whether to use the object storage service.
+ */
+ private boolean enable;
+
+ /**
+ * The protocol needs to be included at the beginning of the address.
+ */
+ private String endpoint;
+
+ private String accessKey;
+
+ private String secretKey;
+
+ private String region;
+
+ private Long expire;
+
+ private String roleSessionName;
+
+ private String roleArn;
+
+ private String bucket;
+
+ private String objectDirPrefix;
+
+ public void setProvider(String provider) {
+ this.provider = provider;
+ }
+
+ public void setEnable(boolean enable) {
+ this.enable = enable;
+ }
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ public void setAccessKey(String accessKey) {
+ this.accessKey = accessKey;
+ }
+
+ public void setSecretKey(String secretKey) {
+ this.secretKey = secretKey;
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public void setExpire(Long expire) {
+ this.expire = expire;
+ }
+
+ public void setRoleSessionName(String roleSessionName) {
+ this.roleSessionName = roleSessionName;
+ }
+
+ public void setRoleArn(String roleArn) {
+ this.roleArn = roleArn;
+ }
+
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+
+ public void setObjectDirPrefix(String objectDirPrefix) {
+ this.objectDirPrefix = objectDirPrefix;
+ }
+}
+
+
+
diff --git a/src/main/java/com/dji/sample/component/oss/model/enums/OssTypeEnum.java b/src/main/java/com/dji/sample/component/oss/model/enums/OssTypeEnum.java
new file mode 100644
index 0000000..58e608c
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/oss/model/enums/OssTypeEnum.java
@@ -0,0 +1,28 @@
+package com.dji.sample.component.oss.model.enums;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/30
+ */
+public enum OssTypeEnum {
+
+ ALIYUN("ali"),
+
+ AWS("aws"),
+
+ /*
+ * MinIO is temporarily unavailable.
+ */
+ MINIO("minio");
+
+ private String type;
+
+ OssTypeEnum(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/oss/service/IOssService.java b/src/main/java/com/dji/sample/component/oss/service/IOssService.java
index beb9db6..53746ef 100644
--- a/src/main/java/com/dji/sample/component/oss/service/IOssService.java
+++ b/src/main/java/com/dji/sample/component/oss/service/IOssService.java
@@ -11,6 +11,8 @@
*/
public interface IOssService {
+ String getOssType();
+
/**
* Get temporary credentials.
* @return
@@ -24,4 +26,20 @@
* @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);
}
diff --git a/src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java b/src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java
index 5ffae6c..4767aec 100644
--- a/src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java
+++ b/src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java
@@ -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.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 @@
@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 @@
if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) {
return null;
}
- try {
- // First check if the object can be fetched.
- ossClient.getObject(bucket, objectKey);
+ 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) {
- e.printStackTrace();
- }
- return null;
+ return ossClient.generatePresignedUrl(bucket, objectKey,
+ new Date(System.currentTimeMillis() + configuration.getExpire() * 1000));
}
+ @Override
+ public Boolean deleteObject(String bucket, String objectKey) {
+ OSS ossClient = this.createClient();
+ ossClient.deleteObject(bucket, objectKey);
+ ossClient.shutdown();
+ return true;
+ }
+
+ @Override
+ public byte[] getObject(String bucket, String objectKey) {
+ OSS ossClient = this.createClient();
+ OSSObject object = ossClient.getObject(bucket, objectKey);
+ InputStream stream = object.getObjectContent();
+
+ try {
+ return stream.readAllBytes();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ stream.close();
+ ossClient.shutdown();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return new byte[0];
+ }
+
+ private OSS createClient() {
+ return new OSSClientBuilder()
+ .build(configuration.getEndpoint(), configuration.getAccessKey(), configuration.getSecretKey());
+ }
}
diff --git a/src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java b/src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java
new file mode 100644
index 0000000..6d0b8af
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java
@@ -0,0 +1,135 @@
+package com.dji.sample.component.oss.service.impl;
+
+import com.amazonaws.HttpMethod;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration;
+import com.amazonaws.services.s3.model.CORSRule;
+import com.amazonaws.services.s3.model.S3Object;
+import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
+import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
+import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
+import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
+import com.amazonaws.services.securitytoken.model.Credentials;
+import com.dji.sample.component.AuthInterceptor;
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.model.enums.OssTypeEnum;
+import com.dji.sample.component.oss.service.IOssService;
+import com.dji.sample.media.model.CredentialsDTO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/27
+ */
+@Service
+public class AmazonS3ServiceImpl implements IOssService {
+
+ @Autowired
+ private OssConfiguration configuration;
+
+ @Override
+ public String getOssType() {
+ return OssTypeEnum.AWS.getType();
+ }
+
+ @Override
+ public CredentialsDTO getCredentials() {
+ AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
+ .withCredentials(new AWSStaticCredentialsProvider(
+ new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey())))
+ .withRegion(configuration.getRegion()).build();
+
+ AssumeRoleRequest request = new AssumeRoleRequest()
+ .withRoleArn(configuration.getRoleArn())
+ .withRoleSessionName(configuration.getRoleSessionName())
+ .withDurationSeconds(Math.toIntExact(configuration.getExpire()));
+ AssumeRoleResult result = stsClient.assumeRole(request);
+ Credentials credentials = result.getCredentials();
+ stsClient.shutdown();
+ return new CredentialsDTO(credentials);
+ }
+
+ @Override
+ public URL getObjectUrl(String bucket, String objectKey) {
+ AmazonS3 client = this.createClient();
+ URL url = client.generatePresignedUrl(bucket, objectKey,
+ new Date(System.currentTimeMillis() + configuration.getExpire() * 1000), HttpMethod.GET);
+ client.shutdown();
+ return url;
+ }
+
+ @Override
+ public Boolean deleteObject(String bucket, String objectKey) {
+ AmazonS3 client = this.createClient();
+ client.deleteObject(bucket, objectKey);
+ client.shutdown();
+ return true;
+ }
+
+ public byte[] getObject(String bucket, String objectKey) {
+ AmazonS3 client = this.createClient();
+ S3Object object = client.getObject(bucket, objectKey);
+ InputStream stream = object.getObjectContent().getDelegateStream();
+ try {
+ return stream.readAllBytes();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ stream.close();
+ client.shutdown();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return new byte[0];
+ }
+
+ private AmazonS3 createClient() {
+ return AmazonS3ClientBuilder.standard()
+ .withCredentials(
+ new AWSStaticCredentialsProvider(
+ new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey())))
+ .withRegion(configuration.getRegion())
+ .build();
+ }
+
+ /**
+ * Configuring cross-origin resource sharing
+ */
+ @PostConstruct
+ private void configCORS() {
+ if (!configuration.isEnable() || !OssTypeEnum.AWS.getType().equals(configuration.getProvider())) {
+ return;
+ }
+ List<CORSRule.AllowedMethods> allowedMethods = new ArrayList<>();
+ allowedMethods.add(CORSRule.AllowedMethods.GET);
+ allowedMethods.add(CORSRule.AllowedMethods.POST);
+ allowedMethods.add(CORSRule.AllowedMethods.DELETE);
+
+ CORSRule rule = new CORSRule()
+ .withId("CORSAccessRule")
+ .withAllowedOrigins(List.of("*"))
+ .withAllowedHeaders(List.of(AuthInterceptor.PARAM_TOKEN))
+ .withAllowedMethods(allowedMethods);
+
+ AmazonS3 client = this.createClient();
+
+ client.setBucketCrossOriginConfiguration(this.configuration.getBucket(),
+ new BucketCrossOriginConfiguration().withRules(rule));
+ client.shutdown();
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java b/src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java
index 76d4e5d..633c35f 100644
--- a/src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java
+++ b/src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java
@@ -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 @@
@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 URL getObjectUrl(String bucket, String objectKey) {
try {
return new URL(
- client.getPresignedObjectUrl(
- GetPresignedObjectUrlArgs.builder()
- .method(Method.GET)
- .bucket(bucket)
- .object(objectKey)
- .expiry(MinIOConfiguration.expire)
- .build()));
+ this.createClient()
+ .getPresignedObjectUrl(
+ GetPresignedObjectUrlArgs.builder()
+ .method(Method.GET)
+ .bucket(bucket)
+ .object(objectKey)
+ .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();
+ }
}
diff --git a/src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java b/src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java
new file mode 100644
index 0000000..f7f9223
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java
@@ -0,0 +1,33 @@
+package com.dji.sample.component.oss.service.impl;
+
+import com.dji.sample.component.oss.model.OssConfiguration;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/20
+ */
+@Component
+@Aspect
+public class OssAspectHandler {
+
+ @Autowired
+ private OssServiceContext ossServiceContext;
+
+ @Autowired
+ private OssConfiguration configuration;
+
+ @Before("execution(public * com.dji.sample.component.oss.service.impl.OssServiceContext.*(..))")
+ public void before() {
+ if (!this.configuration.isEnable()) {
+ throw new IllegalArgumentException("Please enable OssConfiguration.");
+ }
+ if (this.ossServiceContext.getOssService() == null) {
+ throw new IllegalArgumentException("Please check the OssConfiguration configuration.");
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java b/src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java
new file mode 100644
index 0000000..9ac8059
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java
@@ -0,0 +1,58 @@
+package com.dji.sample.component.oss.service.impl;
+
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.model.enums.OssTypeEnum;
+import com.dji.sample.component.oss.service.IOssService;
+import com.dji.sample.media.model.CredentialsDTO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/30
+ */
+@Service
+public class OssServiceContext {
+
+ private IOssService ossService;
+
+ private OssConfiguration configuration;
+
+ @Autowired
+ public OssServiceContext(List<IOssService> ossServices, OssConfiguration configuration) {
+ this.configuration = configuration;
+ if (!configuration.isEnable()) {
+ return;
+ }
+ this.ossService = ossServices.stream()
+ .filter(ossService -> ossService.getOssType().equals(configuration.getProvider()))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("Oss provider is illegal. Optional: " +
+ Arrays.toString(Arrays.stream(OssTypeEnum.values()).map(OssTypeEnum::getType).toArray())));
+ }
+
+ IOssService getOssService() {
+ return this.ossService;
+ }
+
+ public CredentialsDTO getCredentials() {
+ return this.ossService.getCredentials();
+ }
+
+ public URL getObjectUrl(String bucket, String objectKey) {
+ return this.ossService.getObjectUrl(bucket, objectKey);
+ }
+
+ public Boolean deleteObject(String bucket, String objectKey) {
+ return this.ossService.deleteObject(bucket, objectKey);
+ }
+
+ public byte[] getObject(String bucket, String objectKey) {
+ return this.ossService.getObject(bucket, objectKey);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/redis/RedisConfiguration.java b/src/main/java/com/dji/sample/component/redis/RedisConfiguration.java
new file mode 100644
index 0000000..f73261e
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/redis/RedisConfiguration.java
@@ -0,0 +1,63 @@
+package com.dji.sample.component.redis;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/19
+ */
+@Configuration
+@EnableRedisRepositories
+public class RedisConfiguration {
+
+ @Bean
+ public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
+ RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+ redisTemplate.setConnectionFactory(factory);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ JavaTimeModule timeModule = new JavaTimeModule();
+ timeModule.addDeserializer(LocalDateTime.class,
+ new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+ timeModule.addSerializer(LocalDateTime.class,
+ new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+ objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
+ objectMapper.registerModules(timeModule);
+ objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
+ ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+
+ objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+
+ StringRedisSerializer serializer = new StringRedisSerializer();
+ redisTemplate.setKeySerializer(serializer);
+ redisTemplate.setHashKeySerializer(serializer);
+
+ GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
+ redisTemplate.setValueSerializer(jsonRedisSerializer);
+ redisTemplate.setHashValueSerializer(jsonRedisSerializer);
+ redisTemplate.afterPropertiesSet();
+ return redisTemplate;
+
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/redis/RedisConst.java b/src/main/java/com/dji/sample/component/redis/RedisConst.java
new file mode 100644
index 0000000..4d8acf1
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/redis/RedisConst.java
@@ -0,0 +1,29 @@
+package com.dji.sample.component.redis;
+
+import com.dji.sample.manage.model.enums.DeviceDomainEnum;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/21
+ */
+public final class RedisConst {
+
+ private RedisConst() {
+
+ }
+
+ public static final Integer DEVICE_ALIVE_SECOND = 60;
+
+ public static final Integer WEBSOCKET_ALIVE_SECOND = 60 * 60 * 24;
+
+ public static final String ONLINE_PREFIX = "online:";
+
+ public static final String DEVICE_ONLINE_PREFIX = ONLINE_PREFIX + DeviceDomainEnum.SUB_DEVICE + ":";
+
+ public static final String WEBSOCKET_PREFIX = "webSocket:";
+
+ public static final String WEBSOCKET_ALL = "webSocket:all";
+
+ public static final String HMS_PREFIX = "hms:";
+}
diff --git a/src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java b/src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
new file mode 100644
index 0000000..f5b1066
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
@@ -0,0 +1,187 @@
+package com.dji.sample.component.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/19
+ */
+@Component
+public class RedisOpsUtils {
+
+ @Autowired
+ private RedisTemplate<String, Object> redisTemplate;
+
+ /**
+ * HSET
+ * @param key
+ * @param field
+ * @param value
+ */
+ public void hashSet(String key, String field, Object value) {
+ redisTemplate.opsForHash().put(key, field, value);
+ }
+
+ /**
+ * HGET
+ * @param key
+ * @param field
+ * @return
+ */
+ public Object hashGet(String key, String field) {
+ return redisTemplate.opsForHash().get(key, field);
+ }
+
+ /**
+ * HKEYS
+ * @param key
+ * @return
+ */
+ public Set<Object> hashKeys(String key) {
+ return redisTemplate.opsForHash().keys(key);
+ }
+
+ /**
+ * HEXISTS
+ * @param key
+ * @param field
+ * @return
+ */
+ public boolean hashCheck(String key, String field) {
+ return redisTemplate.opsForHash().hasKey(key, field);
+ }
+
+ /**
+ * HDEL
+ * @param key
+ * @param fields
+ * @return
+ */
+ public boolean hashDel(String key, Object[] fields) {
+ return redisTemplate.opsForHash().delete(key, fields) > 0;
+ }
+
+ /**
+ * EXPIRE
+ * @param key
+ * @param timeout
+ * @return
+ */
+ public boolean expireKey(String key, long timeout) {
+ return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
+ }
+
+ /**
+ * SET
+ * @param key
+ * @param value
+ */
+ public void set(String key, Object value) {
+ redisTemplate.opsForValue().set(key, value);
+ }
+
+ /**
+ * GET
+ * @param key
+ * @return
+ */
+ public Object get(String key) {
+ return redisTemplate.opsForValue().get(key);
+ }
+
+ /**
+ * SETEX
+ * @param key
+ * @param value
+ * @param expire
+ */
+ public void setWithExpire(String key, Object value, long expire) {
+ redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
+ }
+
+ /**
+ * TTL
+ * @param key
+ * @return
+ */
+ public long getExpire(String key) {
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+ }
+
+ /**
+ * EXISTS
+ * @param key
+ * @return
+ */
+ public boolean checkExist(String key) {
+ return redisTemplate.hasKey(key);
+ }
+
+ /**
+ * DEL
+ * @param key
+ * @return
+ */
+ public boolean del(String key) {
+ return this.checkExist(key) && redisTemplate.delete(key);
+ }
+
+ /**
+ * KEYS
+ * @param pattern
+ * @return
+ */
+ public Set<String> getAllKeys(String pattern) {
+ return redisTemplate.keys(pattern);
+ }
+
+ /**
+ * RPUSH
+ * @param key
+ * @param value
+ */
+ public void listRPush(String key, Object... value) {
+ if (value.length == 0) {
+ return;
+ }
+ for (Object val : value) {
+ redisTemplate.opsForList().rightPush(key, val);
+ }
+ }
+
+ /**
+ * LRANGE
+ * @param key
+ * @param start
+ * @param end
+ * @return
+ */
+ public List<Object> listGet(String key, long start, long end) {
+ return redisTemplate.opsForList().range(key, start, end);
+ }
+
+ /**
+ * LRANGE
+ * @param key
+ * @return
+ */
+ public List<Object> listGetAll(String key) {
+ return redisTemplate.opsForList().range(key, 0, -1);
+ }
+
+ /**
+ * LLen
+ * @param key
+ * @return
+ */
+ public Long listLen(String key) {
+ return redisTemplate.opsForList().size(key);
+ }
+}
diff --git a/src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java b/src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java
index 68f070e..05fbd2d 100644
--- a/src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java
+++ b/src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java
@@ -35,7 +35,7 @@
if (!StringUtils.hasText(token)) {
return false;
}
-
+ log.debug("token:" + token);
Optional<CustomClaim> customClaim = JwtUtil.parseToken(token);
if (customClaim.isEmpty()) {
return false;
diff --git a/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java b/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java
index 4fdd774..f6ad8fb 100644
--- a/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java
+++ b/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java
@@ -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 @@
@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);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java b/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java
index d4c7e7a..11ee861 100644
--- a/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java
+++ b/src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java
@@ -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 @@
@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 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());
}
}
diff --git a/src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java b/src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java
index 6ac35c2..50f8978 100644
--- a/src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java
+++ b/src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java
@@ -17,13 +17,19 @@
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;
diff --git a/src/main/java/com/dji/sample/component/websocket/service/IWebSocketManageService.java b/src/main/java/com/dji/sample/component/websocket/service/IWebSocketManageService.java
new file mode 100644
index 0000000..f09a6e2
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/websocket/service/IWebSocketManageService.java
@@ -0,0 +1,23 @@
+package com.dji.sample.component.websocket.service;
+
+import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
+
+import java.util.Collection;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/25
+ */
+public interface IWebSocketManageService {
+
+ void put(String key, ConcurrentWebSocketSession val);
+
+ void remove(String key, String sessionId);
+
+ Collection<ConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId);
+
+ Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType);
+
+ Long getConnectedCount();
+}
diff --git a/src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java b/src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java
index 8ee6131..0546728 100644
--- a/src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java
+++ b/src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java
@@ -5,6 +5,7 @@
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 @@
@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 @@
return;
}
- ObjectMapper mapper = new ObjectMapper();
session.sendMessage(new TextMessage(mapper.writeValueAsBytes(message)));
} catch (IOException e) {
@@ -50,7 +53,6 @@
try {
- ObjectMapper mapper = new ObjectMapper();
TextMessage data = new TextMessage(mapper.writeValueAsBytes(message));
for (ConcurrentWebSocketSession session : sessions) {
@@ -60,7 +62,6 @@
return;
}
session.sendMessage(data);
-
}
} catch (IOException e) {
diff --git a/src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java b/src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java
new file mode 100644
index 0000000..e2734c0
--- /dev/null
+++ b/src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java
@@ -0,0 +1,90 @@
+package com.dji.sample.component.websocket.service.impl;
+
+import com.dji.sample.component.redis.RedisConst;
+import com.dji.sample.component.redis.RedisOpsUtils;
+import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
+import com.dji.sample.component.websocket.service.IWebSocketManageService;
+import com.dji.sample.manage.model.enums.UserTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/25
+ */
+@Slf4j
+@Service
+public class WebSocketManageServiceImpl implements IWebSocketManageService {
+
+ private static final ConcurrentHashMap<String, ConcurrentWebSocketSession> SESSIONS = new ConcurrentHashMap<>(16);
+
+ @Autowired
+ private RedisOpsUtils redisOps;
+
+ @Override
+ public void put(String key, ConcurrentWebSocketSession val) {
+ String[] name = key.split("/");
+ if (name.length != 3) {
+ log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]");
+ return;
+ }
+ String sessionId = val.getId();
+ String workspaceKey = RedisConst.WEBSOCKET_PREFIX + name[0];
+ String userTypeKey = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc();
+ redisOps.hashSet(workspaceKey, sessionId, name[2]);
+ redisOps.hashSet(userTypeKey, sessionId, name[2]);
+ SESSIONS.put(sessionId, val);
+ redisOps.expireKey(workspaceKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
+ redisOps.expireKey(userTypeKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
+ }
+
+ @Override
+ public void remove(String key, String sessionId) {
+ String[] name = key.split("/");
+ if (name.length != 3) {
+ log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]");
+ return;
+ }
+ redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId});
+ redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])), new String[] {sessionId});
+ SESSIONS.remove(sessionId);
+ }
+
+ @Override
+ public Collection<ConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId) {
+ if (!StringUtils.hasText(workspaceId)) {
+ return Collections.emptySet();
+ }
+ String key = RedisConst.WEBSOCKET_PREFIX + workspaceId;
+
+ return redisOps.hashKeys(key)
+ .stream()
+ .map(SESSIONS::get)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType) {
+ String key = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(userType).getDesc();
+ return redisOps.hashKeys(key)
+ .stream()
+ .map(SESSIONS::get)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Long getConnectedCount() {
+ return SESSIONS.mappingCount();
+ }
+}
diff --git a/src/main/java/com/dji/sample/configuration/SpringBeanConfiguration.java b/src/main/java/com/dji/sample/configuration/SpringBeanConfiguration.java
new file mode 100644
index 0000000..f1a481e
--- /dev/null
+++ b/src/main/java/com/dji/sample/configuration/SpringBeanConfiguration.java
@@ -0,0 +1,49 @@
+package com.dji.sample.configuration;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Configuration
+public class SpringBeanConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(ObjectMapper.class)
+ public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
+ ObjectMapper objectMapper = builder.createXmlMapper(false).build();
+ objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ JavaTimeModule timeModule = new JavaTimeModule();
+ timeModule.addDeserializer(LocalDateTime.class,
+ new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+ timeModule.addSerializer(LocalDateTime.class,
+ new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+
+ objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
+ objectMapper.registerModules(timeModule);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+ objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
+ objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
+ @Override
+ public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ gen.writeString("");
+ }
+ });
+ return objectMapper;
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/controller/DeviceController.java b/src/main/java/com/dji/sample/manage/controller/DeviceController.java
index 08a245d..ad2579a 100644
--- a/src/main/java/com/dji/sample/manage/controller/DeviceController.java
+++ b/src/main/java/com/dji/sample/manage/controller/DeviceController.java
@@ -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.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 @@
.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 @@
.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 @@
deviceService.handleOSD(topic, payload);
}
- /**
- * Handles the payloads data of the drone.
- * @param deviceSn drone's sn
- */
- @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);
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_FIRMWARE_VERSION)
+ public void updateFirmwareVersion(FirmwareVersionReceiver receiver) {
+ deviceService.updateFirmwareVersion(receiver);
+ }
- 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);
+ @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());
+ }
+
+ /**
+ * Get the binding devices list in one workspace.
+ * @param workspaceId
+ * @param page
+ * @param pageSize
+ * @return
+ */
+ @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();
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/controller/DeviceHmsController.java b/src/main/java/com/dji/sample/manage/controller/DeviceHmsController.java
new file mode 100644
index 0000000..f058399
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/controller/DeviceHmsController.java
@@ -0,0 +1,53 @@
+package com.dji.sample.manage.controller;
+
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.common.model.ResponseResult;
+import com.dji.sample.manage.model.dto.DeviceHmsDTO;
+import com.dji.sample.manage.model.param.DeviceHmsQueryParam;
+import com.dji.sample.manage.service.IDeviceHmsService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/7
+ */
+
+@RestController
+@Slf4j
+@RequestMapping("${url.manage.prefix}${url.manage.version}/devices")
+public class DeviceHmsController {
+
+ @Autowired
+ private IDeviceHmsService deviceHmsService;
+
+ @GetMapping("/{workspace_id}/devices/hms")
+ public ResponseResult<PaginationData<DeviceHmsDTO>> getBoundDevicesWithDomain(DeviceHmsQueryParam param,
+ @PathVariable("workspace_id") String workspaceId) {
+ PaginationData<DeviceHmsDTO> devices = deviceHmsService.getDeviceHmsByParam(param);
+
+ return ResponseResult.success(devices);
+ }
+
+ @PutMapping("/{workspace_id}/devices/hms/{device_sn}")
+ public ResponseResult updateReadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) {
+ deviceHmsService.updateUnreadHms(deviceSn);
+ return ResponseResult.success();
+ }
+
+ @GetMapping("/{workspace_id}/devices/hms/{device_sn}")
+ public ResponseResult<List<DeviceHmsDTO>> getUnreadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) {
+ PaginationData<DeviceHmsDTO> paginationData = deviceHmsService.getDeviceHmsByParam(
+ DeviceHmsQueryParam.builder()
+ .deviceSn(new HashSet<>(Set.of(deviceSn)))
+ .updateTime(0L)
+ .build());
+ return ResponseResult.success(paginationData.getList());
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java b/src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java
index 0c0ba2c..4a768a2 100644
--- a/src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java
+++ b/src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java
@@ -2,7 +2,6 @@
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;
@@ -24,25 +23,6 @@
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.
*
* Note: Only the data of the drone payload is handled here. You can handle other data from the drone
@@ -50,9 +30,8 @@
* @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 @@
log.debug("The result of saving the payloads is {}.", isSave);
- return deviceBasic.getDeviceSn();
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/controller/LiveStreamController.java b/src/main/java/com/dji/sample/manage/controller/LiveStreamController.java
index ef89f34..7f6e90c 100644
--- a/src/main/java/com/dji/sample/manage/controller/LiveStreamController.java
+++ b/src/main/java/com/dji/sample/manage/controller/LiveStreamController.java
@@ -2,13 +2,13 @@
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 @@
@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 @@
@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.
diff --git a/src/main/java/com/dji/sample/manage/controller/LoginController.java b/src/main/java/com/dji/sample/manage/controller/LoginController.java
index b0cacb4..23c84d9 100644
--- a/src/main/java/com/dji/sample/manage/controller/LoginController.java
+++ b/src/main/java/com/dji/sample/manage/controller/LoginController.java
@@ -27,9 +27,10 @@
@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 @@
return ResponseResult.error(CommonErrorEnum.NO_TOKEN.getErrorMsg());
}
- return ResponseResult.success(user);
+ return ResponseResult.success(user.get());
}
}
diff --git a/src/main/java/com/dji/sample/manage/controller/UserController.java b/src/main/java/com/dji/sample/manage/controller/UserController.java
index 06cfb4d..91990e7 100644
--- a/src/main/java/com/dji/sample/manage/controller/UserController.java
+++ b/src/main/java/com/dji/sample/manage/controller/UserController.java
@@ -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 @@
@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();
+ }
}
diff --git a/src/main/java/com/dji/sample/manage/dao/IDeviceHmsMapper.java b/src/main/java/com/dji/sample/manage/dao/IDeviceHmsMapper.java
new file mode 100644
index 0000000..c7eb8bb
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/dao/IDeviceHmsMapper.java
@@ -0,0 +1,12 @@
+package com.dji.sample.manage.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dji.sample.manage.model.entity.DeviceHmsEntity;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/6
+ */
+public interface IDeviceHmsMapper extends BaseMapper<DeviceHmsEntity> {
+}
diff --git a/src/main/java/com/dji/sample/manage/model/common/HmsJsonUtil.java b/src/main/java/com/dji/sample/manage/model/common/HmsJsonUtil.java
new file mode 100644
index 0000000..030bf5f
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/common/HmsJsonUtil.java
@@ -0,0 +1,49 @@
+package com.dji.sample.manage.model.common;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/7
+ */
+@Slf4j
+@Component
+public class HmsJsonUtil {
+
+ private static ObjectMapper mapper;
+
+ @Autowired
+ public void setMapper(ObjectMapper mapper) {
+ HmsJsonUtil.mapper = mapper;
+ }
+
+ private static JsonNode nodes;
+
+ private HmsJsonUtil(){
+
+ }
+
+ @PostConstruct
+ private void loadJsonFile() {
+ try (InputStream inputStream = new ClassPathResource("hms.json").getInputStream()){
+ nodes = mapper.readTree(inputStream);
+ } catch (IOException e) {
+ log.error("hms.json failed to load.");
+ e.printStackTrace();
+ }
+ }
+
+ public static HmsMessage get(String key) {
+ return mapper.convertValue(nodes.get(key), HmsMessage.class);
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/model/common/HmsMessage.java b/src/main/java/com/dji/sample/manage/model/common/HmsMessage.java
new file mode 100644
index 0000000..328b45e
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/common/HmsMessage.java
@@ -0,0 +1,16 @@
+package com.dji.sample.manage.model.common;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/7
+ */
+@Data
+public class HmsMessage {
+
+ private String zh;
+
+ private String en;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java b/src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java
index dbc6481..d44fddd 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java
@@ -18,13 +18,11 @@
@NoArgsConstructor
public class CapacityCameraDTO {
- private Integer id;
+ private String id;
private String deviceSn;
private String name;
-
- private String description;
private String index;
diff --git a/src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java b/src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java
index 1d9dc3a..9366472 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java
@@ -16,7 +16,7 @@
@NoArgsConstructor
public class CapacityVideoDTO {
- private Integer id;
+ private String id;
private String index;
diff --git a/src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java b/src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java
index 2571dff..89d19d6 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java
@@ -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 @@
@AllArgsConstructor
@NoArgsConstructor
@Builder
-@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class DeviceDTO {
private String deviceSn;
@@ -44,4 +42,22 @@
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;
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/model/dto/DeviceHmsDTO.java b/src/main/java/com/dji/sample/manage/model/dto/DeviceHmsDTO.java
new file mode 100644
index 0000000..7dc1c1a
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/dto/DeviceHmsDTO.java
@@ -0,0 +1,57 @@
+package com.dji.sample.manage.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/8
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class DeviceHmsDTO implements Cloneable {
+
+ private String hmsId;
+
+ private String tid;
+
+ private String bid;
+
+ private String sn;
+
+ private Integer level;
+
+ private Integer module;
+
+ private String key;
+
+ private String messageZh;
+
+ private String messageEn;
+
+ private LocalDateTime createTime;
+
+ private LocalDateTime updateTime;
+
+ @Override
+ public DeviceHmsDTO clone() {
+ try {
+ return (DeviceHmsDTO) super.clone();
+ } catch (CloneNotSupportedException e) {
+ return DeviceHmsDTO.builder()
+ .sn(this.sn)
+ .bid(this.bid)
+ .tid(this.tid)
+ .createTime(this.createTime)
+ .updateTime(this.updateTime)
+ .build();
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java b/src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java
index 8f7f9d5..26fe624 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java
@@ -14,9 +14,9 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
-public class TelemetryDTO {
+public class TelemetryDTO<T> {
- private TelemetryDeviceDTO host;
+ private T host;
private String sn;
}
diff --git a/src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java b/src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java
index c36e88d..ced5277 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java
@@ -22,8 +22,7 @@
private DeviceModelDTO deviceModel;
- @Builder.Default
- private Boolean onlineStatus = true;
+ private Boolean onlineStatus;
private String deviceCallsign;
@@ -32,4 +31,12 @@
private String userCallsign;
private IconUrlDTO iconUrls;
+
+ private String model;
+
+ private Boolean boundStatus;
+
+ private String gatewaySn;
+
+ private String domain;
}
diff --git a/src/main/java/com/dji/sample/manage/model/dto/UserListDTO.java b/src/main/java/com/dji/sample/manage/model/dto/UserListDTO.java
new file mode 100644
index 0000000..7bfb3a6
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/dto/UserListDTO.java
@@ -0,0 +1,34 @@
+package com.dji.sample.manage.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/18
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserListDTO {
+
+ private String userId;
+
+ private String username;
+
+ private String workspaceName;
+
+ private String userType;
+
+ private String mqttUsername;
+
+ private String mqttPassword;
+
+ private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java b/src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java
index b82ca44..7c0d8f4 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java
@@ -11,4 +11,7 @@
@NonNull
private String password;
+
+ @NonNull
+ private Integer flag;
}
diff --git a/src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java b/src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java
index 0ce7d15..3714974 100644
--- a/src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java
+++ b/src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java
@@ -19,8 +19,6 @@
@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 @@
private String workspaceDesc;
private String platformName;
+
+ private String bindCode;
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java b/src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java
index f019a01..29326da 100644
--- a/src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java
+++ b/src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java
@@ -66,4 +66,23 @@
@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;
+
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/model/entity/DeviceHmsEntity.java b/src/main/java/com/dji/sample/manage/model/entity/DeviceHmsEntity.java
new file mode 100644
index 0000000..bf14f5a
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/entity/DeviceHmsEntity.java
@@ -0,0 +1,76 @@
+package com.dji.sample.manage.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/6
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "manage_device_hms")
+public class DeviceHmsEntity implements Serializable, Cloneable {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ @TableField("hms_id")
+ private String hmsId;
+
+ @TableField("tid")
+ private String tid;
+
+ @TableField("bid")
+ private String bid;
+
+ @TableField("sn")
+ private String sn;
+
+ @TableField("level")
+ private Integer level;
+
+ @TableField("module")
+ private Integer module;
+
+ @TableField("hms_key")
+ private String hmsKey;
+
+ @TableField("message_zh")
+ private String messageZh;
+
+ @TableField("message_en")
+ private String messageEn;
+
+ @TableField("create_time")
+ private Long createTime;
+
+ @TableField("update_time")
+ private Long updateTime;
+
+ @Override
+ public DeviceHmsEntity clone() {
+ try {
+ return (DeviceHmsEntity) super.clone();
+ } catch (CloneNotSupportedException e) {
+ return DeviceHmsEntity.builder()
+ .bid(this.getBid())
+ .tid(this.getTid())
+ .createTime(this.getCreateTime())
+ .updateTime(this.getUpdateTime())
+ .sn(this.getSn())
+ .build();
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java b/src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java
index 184fb0f..a54ff0d 100644
--- a/src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java
+++ b/src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java
@@ -35,8 +35,8 @@
@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;
diff --git a/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java b/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
index 67edecf..6c095b9 100644
--- a/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
+++ b/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
@@ -22,7 +22,7 @@
private String password;
@TableField(value = "workspace_id")
- private Integer workspaceId;
+ private String workspaceId;
@TableField(value = "user_type")
private Integer userType;
diff --git a/src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java b/src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java
index 8a84ff0..90a5348 100644
--- a/src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java
+++ b/src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java
@@ -30,4 +30,6 @@
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Long updateTime;
+ @TableField(value = "bind_code")
+ private String bindCode;
}
diff --git a/src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java b/src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java
index cd8fd39..76b9c4d 100644
--- a/src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java
+++ b/src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java
@@ -14,6 +14,8 @@
PAYLOAD(1, "payload"),
+ DOCK (3, "dock"),
+
UNKNOWN(-1, "unknown");
private int val;
@@ -29,6 +31,10 @@
return val;
}
+ public String getDesc() {
+ return desc;
+ }
+
public static String getDesc(int val) {
if (SUB_DEVICE.val == val) {
return SUB_DEVICE.desc;
@@ -40,6 +46,10 @@
if (PAYLOAD.val == val) {
return PAYLOAD.desc;
+ }
+
+ if (DOCK.val == val) {
+ return DOCK.desc;
}
return UNKNOWN.desc;
}
@@ -56,6 +66,10 @@
if (PAYLOAD.desc.equals(desc)) {
return PAYLOAD.val;
}
+
+ if (DOCK.desc.equals(desc)) {
+ return DOCK.val;
+ }
return UNKNOWN.val;
}
diff --git a/src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java b/src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java
new file mode 100644
index 0000000..331a985
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java
@@ -0,0 +1,155 @@
+package com.dji.sample.manage.model.enums;
+
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/7
+ */
+@Getter
+public enum HmsEnum {
+
+ IN_THE_SKY("_in_the_sky", 1);
+
+ private int val;
+
+ private String text;
+
+ HmsEnum(String text, int val) {
+ this.text = text;
+ this.val = val;
+ }
+
+ @Getter
+ public enum MessageLanguage {
+
+ EN("en"),
+
+ ZH("zh");
+
+ String language;
+
+ MessageLanguage(String language) {
+ this.language = language;
+ }
+ }
+
+ @Getter
+ public enum DomainType {
+ DRONE_NEST("drone_nest"),
+
+ DRONE("drone");
+
+ private String domain;
+
+ DomainType(String domain) {
+ this.domain = domain;
+ }
+
+ }
+
+ @Getter
+ public enum HmsFaqIdEnum {
+
+ FPV_TIP("fpv_tip_");
+
+ private String text;
+
+ HmsFaqIdEnum(String text) {
+ this.text = text;
+ }
+
+ }
+
+ @Getter
+ public enum HmsBatteryIndexEnum {
+ LEFT(0, "left", "左"),
+
+ RIGHT(1, "right", "右"),
+
+ UNKNOWN(-1, "unknown", "未知");
+
+ private int val;
+
+ private String en;
+
+ private String zh;
+
+ HmsBatteryIndexEnum(int val, String en, String zh) {
+ this.val = val;
+ this.en = en;
+ this.zh = zh;
+ }
+
+ public static HmsBatteryIndexEnum find(int val) {
+ return Arrays.stream(HmsBatteryIndexEnum.values())
+ .filter(battery -> battery.val == val)
+ .findAny()
+ .orElse(UNKNOWN);
+ }
+ }
+
+ @Getter
+ public enum HmsDockCoverIndexEnum {
+ LEFT(0, "left", "左"),
+
+ RIGHT(1, "right", "右"),
+
+ UNKNOWN(-1, "unknown", "未知");
+
+ private int val;
+
+ private String en;
+
+ private String zh;
+
+ HmsDockCoverIndexEnum(int val, String en, String zh) {
+ this.val = val;
+ this.en = en;
+ this.zh = zh;
+ }
+
+ public static HmsDockCoverIndexEnum find(int val) {
+ return Arrays.stream(HmsDockCoverIndexEnum.values())
+ .filter(dockCover -> dockCover.val == val)
+ .findAny()
+ .orElse(UNKNOWN);
+ }
+ }
+
+ @Getter
+ public enum HmsChargingRodIndexEnum {
+
+ FRONT(0, "front", "前"),
+
+ BACK(1, "back", "后"),
+
+ LEFT(2, "left", "左"),
+
+ RIGHT(3, "right", "右"),
+
+ UNKNOWN(-1, "unknown", "未知");
+
+ private int val;
+
+ private String en;
+
+ private String zh;
+
+ HmsChargingRodIndexEnum(int val, String en, String zh) {
+ this.val = val;
+ this.en = en;
+ this.zh = zh;
+ }
+
+ public static HmsChargingRodIndexEnum find(int val) {
+ return Arrays.stream(HmsChargingRodIndexEnum.values())
+ .filter(rod -> rod.val == val)
+ .findAny()
+ .orElse(UNKNOWN);
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/model/enums/PayloadModelEnum.java b/src/main/java/com/dji/sample/manage/model/enums/PayloadModelEnum.java
new file mode 100644
index 0000000..5633b03
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/enums/PayloadModelEnum.java
@@ -0,0 +1,61 @@
+package com.dji.sample.manage.model.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/29
+ */
+public enum PayloadModelEnum {
+
+ Z30("Z30", "20-0"),
+
+ XT2("XT2", "26-0"),
+
+ XTS("XTS", "41-0"),
+
+ H20("H20", "42-0"),
+
+ H20T("H20T", "43-0"),
+
+ P1("P1", "50-65535"),
+
+ M30("M30", "52-0"),
+
+ M30T("M30T", "53-0"),
+
+ H20N("H20N", "61-0"),
+
+ DOCK("DOCK", "165-0"),
+
+ L1("L1", "90742-0");
+
+ private String model;
+
+ private String index;
+
+ PayloadModelEnum(String model, String index) {
+ this.model = model;
+ this.index = index;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public String getIndex() {
+ return index;
+ }
+
+ public static List<String> getAllModel() {
+ return Arrays.stream(PayloadModelEnum.values()).map(PayloadModelEnum::getModel).collect(Collectors.toList());
+ }
+
+ public static List<String> getAllIndex() {
+ return Arrays.stream(PayloadModelEnum.values()).map(PayloadModelEnum::getIndex).collect(Collectors.toList());
+ }
+
+}
diff --git a/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java b/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java
index 311669e..a90e526 100644
--- a/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java
+++ b/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java
@@ -7,18 +7,36 @@
*/
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;
}
}
diff --git a/src/main/java/com/dji/sample/manage/model/param/DeviceHmsQueryParam.java b/src/main/java/com/dji/sample/manage/model/param/DeviceHmsQueryParam.java
new file mode 100644
index 0000000..cfce9fe
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/param/DeviceHmsQueryParam.java
@@ -0,0 +1,45 @@
+package com.dji.sample.manage.model.param;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/8
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class DeviceHmsQueryParam implements Serializable {
+
+ @JsonProperty("device_sn")
+ private Set<String> deviceSn;
+
+ @JsonProperty("begin_time")
+ private Long beginTime;
+
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ private String language;
+
+ private String message;
+
+ private Long page;
+
+ @JsonProperty("page_size")
+ private Long pageSize;
+
+ private Integer level;
+
+ @JsonProperty("update_time")
+ private Long updateTime;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java b/src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java
index 9233121..b9fc67e 100644
--- a/src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java
+++ b/src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java
@@ -3,6 +3,8 @@
import lombok.Builder;
import lombok.Data;
+import java.util.List;
+
/**
* The object of the device query field.
*
@@ -22,10 +24,12 @@
private Integer subType;
- private Integer domain;
+ private List<Integer> domains;
private String childSn;
+ private Boolean boundStatus;
+
private boolean orderBy;
private boolean isAsc;
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/AlternateLandPointReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/AlternateLandPointReceiver.java
new file mode 100644
index 0000000..bd69415
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/AlternateLandPointReceiver.java
@@ -0,0 +1,18 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Data
+public class AlternateLandPointReceiver {
+
+ private Double latitude;
+
+ private Double longitude;
+
+ private Double safeLandHeight;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/BindDeviceReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/BindDeviceReceiver.java
new file mode 100644
index 0000000..7f13246
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/BindDeviceReceiver.java
@@ -0,0 +1,22 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/13
+ */
+@Data
+public class BindDeviceReceiver {
+
+ private String deviceBindingCode;
+
+ private String organizationId;
+
+ private String deviceCallsign;
+
+ private String sn;
+
+ private String deviceModelKey;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/BindStatusReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/BindStatusReceiver.java
new file mode 100644
index 0000000..61c8477
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/BindStatusReceiver.java
@@ -0,0 +1,30 @@
+package com.dji.sample.manage.model.receiver;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/14
+ */
+@Builder
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude
+public class BindStatusReceiver {
+
+ private String sn;
+
+ private Boolean isDeviceBindOrganization;
+
+ private String organizationId;
+
+ private String organizationName;
+
+ private String deviceCallsign;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java
index 1ae46d8..fa22b73 100644
--- a/src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java
@@ -21,17 +21,11 @@
private String deviceSn;
- private Integer flightMode;
-
- private Integer flightStatus;
-
private Double homeLatitude;
private Double homeLongitude;
private Integer lowBatteryWarningThreshold;
-
- private Integer positionMode;
private Integer seriousLowBatteryWarningThreshold;
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java
new file mode 100644
index 0000000..f2557a5
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java
@@ -0,0 +1,28 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/6
+ */
+@Data
+public class DeviceHmsReceiver {
+
+ private String code;
+
+ private String deviceType;
+
+ private String domainType;
+
+ private Integer imminent;
+
+ private Integer inTheSky;
+
+ private Integer level;
+
+ private Integer module;
+
+ private HmsArgsReceiver args;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java
index 2b3f998..830c9d6 100644
--- a/src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java
@@ -23,7 +23,4 @@
private String sn;
- private Integer version;
-
- private Integer workMode;
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DockMediaFileDetailReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DockMediaFileDetailReceiver.java
new file mode 100644
index 0000000..bd7745a
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DockMediaFileDetailReceiver.java
@@ -0,0 +1,14 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/17
+ */
+@Data
+public class DockMediaFileDetailReceiver {
+
+ private Integer remainUpload;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DockSdrReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DockSdrReceiver.java
new file mode 100644
index 0000000..4067717
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DockSdrReceiver.java
@@ -0,0 +1,18 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/17
+ */
+@Data
+public class DockSdrReceiver {
+
+ private Integer downQuality;
+
+ private Double frequencyBand;
+
+ private Integer upQuality;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DockSubDeviceReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DockSubDeviceReceiver.java
new file mode 100644
index 0000000..4708ea7
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DockSubDeviceReceiver.java
@@ -0,0 +1,20 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Data
+public class DockSubDeviceReceiver {
+
+ private String deviceSn;
+
+ private Integer deviceOnlineStatus;
+
+ private Integer devicePaired;
+
+ private String deviceModelKey;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/DroneChargeStateReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/DroneChargeStateReceiver.java
new file mode 100644
index 0000000..6fe4f49
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/DroneChargeStateReceiver.java
@@ -0,0 +1,16 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Data
+public class DroneChargeStateReceiver {
+
+ private Integer state;
+
+ private Integer capacityPercent;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/FirmwareVersionReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/FirmwareVersionReceiver.java
new file mode 100644
index 0000000..a3c2634
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/FirmwareVersionReceiver.java
@@ -0,0 +1,29 @@
+package com.dji.sample.manage.model.receiver;
+
+import com.dji.sample.manage.model.enums.DeviceDomainEnum;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/4/28
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FirmwareVersionReceiver {
+
+ private String firmwareVersion;
+
+ private Integer compatibleStatus;
+
+ private Integer firmwareUpgradeStatus;
+
+ private String sn;
+
+ private DeviceDomainEnum domain;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/HmsArgsReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/HmsArgsReceiver.java
new file mode 100644
index 0000000..2d35a1e
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/HmsArgsReceiver.java
@@ -0,0 +1,18 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/6
+ */
+@Data
+public class HmsArgsReceiver {
+
+ private Long componentIndex;
+
+ private Integer sensorIndex;
+
+ private Integer alarmId;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/LiveCapacityReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/LiveCapacityReceiver.java
new file mode 100644
index 0000000..af471b7
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/LiveCapacityReceiver.java
@@ -0,0 +1,20 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/24
+ */
+@Data
+public class LiveCapacityReceiver {
+
+ private Integer availableVideoNumber;
+
+ private Integer coexistVideoNumberMax;
+
+ private List<CapacityDeviceReceiver> deviceList;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/NetworkStateReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/NetworkStateReceiver.java
new file mode 100644
index 0000000..84698cc
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/NetworkStateReceiver.java
@@ -0,0 +1,18 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Data
+public class NetworkStateReceiver {
+
+ private Integer type;
+
+ private Integer quality;
+
+ private float rate;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/OrganizationGetReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/OrganizationGetReceiver.java
new file mode 100644
index 0000000..3b92484
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/OrganizationGetReceiver.java
@@ -0,0 +1,16 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/13
+ */
+@Data
+public class OrganizationGetReceiver {
+
+ private String deviceBindingCode;
+
+ private String organizationId;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/OsdDockReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/OsdDockReceiver.java
new file mode 100644
index 0000000..ebd8b34
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/OsdDockReceiver.java
@@ -0,0 +1,67 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Data
+public class OsdDockReceiver {
+
+ private NetworkStateReceiver networkState;
+
+ private Integer droneInDock;
+
+ private DroneChargeStateReceiver droneChargeState;
+
+ private Integer rainfall;
+
+ private Float windSpeed;
+
+ private Float environmentTemperature;
+
+ private Integer environmentHumidity;
+
+ private Float temperature;
+
+ private Integer humidity;
+
+ private Double latitude;
+
+ private Double longitude;
+
+ private Double height;
+
+ private AlternateLandPointReceiver alternateLandPoint;
+
+ private Integer jobNumber;
+
+ private Integer accTime;
+
+ private Long firstPowerOn;
+
+ private PositionStateReceiver positionState;
+
+ private StorageReceiver storage;
+
+ private Integer electricSupplyVoltage;
+
+ private Integer workingVoltage;
+
+ private Integer workingCurrent;
+
+ private Integer backupBatteryVoltage;
+
+ private Integer modeCode;
+
+ private Integer coverState;
+
+ private Integer supplementLightState;
+
+ private Integer putterState;
+
+ private DockSubDeviceReceiver subDevice;
+
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/OsdDockTransmissionReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/OsdDockTransmissionReceiver.java
new file mode 100644
index 0000000..cdd9abf
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/OsdDockTransmissionReceiver.java
@@ -0,0 +1,18 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/17
+ */
+@Data
+public class OsdDockTransmissionReceiver {
+
+ private Integer flighttaskStepCode;
+
+ private DockMediaFileDetailReceiver mediaFileDetail;
+
+ private DockSdrReceiver sdr;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/OsdPayloadReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/OsdPayloadReceiver.java
new file mode 100644
index 0000000..e4125c6
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/OsdPayloadReceiver.java
@@ -0,0 +1,33 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/6
+ */
+@Data
+public class OsdPayloadReceiver {
+
+ private String payloadIndex;
+
+ private Double gimbalPitch;
+
+ private Double gimbalRoll;
+
+ private Double gimbalYaw;
+
+ private Double measureTargetAltitude;
+
+ private Double measureTargetDistance;
+
+ private Double measureTargetLatitude;
+
+ private Double measureTargetLongitude;
+
+ private Integer measureTargetErrorState;
+
+ private Integer version;
+
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/OsdSubDeviceReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/OsdSubDeviceReceiver.java
index 24d101e..2cb54df 100644
--- a/src/main/java/com/dji/sample/manage/model/receiver/OsdSubDeviceReceiver.java
+++ b/src/main/java/com/dji/sample/manage/model/receiver/OsdSubDeviceReceiver.java
@@ -5,6 +5,8 @@
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;
+import java.util.List;
+
/**
* @author sean.zhou
* @version 0.1
@@ -49,7 +51,11 @@
private Double windDirection;
- private Double windSpeed;
+ private Float windSpeed;
private PositionStateReceiver positionState;
+
+ private List<OsdPayloadReceiver> payloads;
+
+ private StorageReceiver storage;
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/PositionStateReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/PositionStateReceiver.java
index 5c6787f..ad7baec 100644
--- a/src/main/java/com/dji/sample/manage/model/receiver/PositionStateReceiver.java
+++ b/src/main/java/com/dji/sample/manage/model/receiver/PositionStateReceiver.java
@@ -13,6 +13,8 @@
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class PositionStateReceiver {
+ private Integer isCalibration;
+
private Integer gpsNumber;
private Integer isFixed;
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/StatusSubDeviceReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/StatusSubDeviceReceiver.java
index 4f0d47a..428f16c 100644
--- a/src/main/java/com/dji/sample/manage/model/receiver/StatusSubDeviceReceiver.java
+++ b/src/main/java/com/dji/sample/manage/model/receiver/StatusSubDeviceReceiver.java
@@ -16,6 +16,8 @@
private String sn;
+ private Integer domain;
+
private Integer type;
@JsonProperty(value = "sub_type")
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/StorageReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/StorageReceiver.java
new file mode 100644
index 0000000..6cb4b75
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/model/receiver/StorageReceiver.java
@@ -0,0 +1,16 @@
+package com.dji.sample.manage.model.receiver;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Data
+public class StorageReceiver {
+
+ private Long total;
+
+ private Long used;
+}
diff --git a/src/main/java/com/dji/sample/manage/model/receiver/WirelessLinkStateReceiver.java b/src/main/java/com/dji/sample/manage/model/receiver/WirelessLinkStateReceiver.java
index 5dc8bd5..1efbe3e 100644
--- a/src/main/java/com/dji/sample/manage/model/receiver/WirelessLinkStateReceiver.java
+++ b/src/main/java/com/dji/sample/manage/model/receiver/WirelessLinkStateReceiver.java
@@ -15,7 +15,7 @@
private Integer downloadQuality;
- private Integer frequencyBand;
+ private Double frequencyBand;
private Integer upwardQuality;
diff --git a/src/main/java/com/dji/sample/manage/service/ICameraVideoService.java b/src/main/java/com/dji/sample/manage/service/ICameraVideoService.java
index 808d6dd..df2f1ec 100644
--- a/src/main/java/com/dji/sample/manage/service/ICameraVideoService.java
+++ b/src/main/java/com/dji/sample/manage/service/ICameraVideoService.java
@@ -3,8 +3,6 @@
import com.dji.sample.manage.model.dto.CapacityVideoDTO;
import com.dji.sample.manage.model.receiver.CapacityVideoReceiver;
-import java.util.List;
-
/**
* @author sean.zhou
* @date 2021/11/19
@@ -13,25 +11,9 @@
public interface ICameraVideoService {
/**
- * Queries all lens data contained in the camera based on camera id.
- * @param cameraId
- * @return
+ * Convert the received lens capability object into lens data transfer object.
+ * @param receiver
+ * @return data transfer object
*/
- List<CapacityVideoDTO> getCameraVideosByCameraId(Integer cameraId);
-
- /**
- * Deletes all the data of this lens, according to the lens id.
- * @param ids A collection of lens ids.
- * @return true
- */
- Boolean deleteCameraVideosById(List<Integer> ids);
-
- /**
- * Save the live capability of all lenses of this camera.
- * @param capacityVideoReceivers live capability of lens
- * @param cameraId
- * @return
- */
- Boolean saveCameraVideoDTOList(List<CapacityVideoReceiver> capacityVideoReceivers, Integer cameraId);
-
+ CapacityVideoDTO receiver2Dto(CapacityVideoReceiver receiver);
}
diff --git a/src/main/java/com/dji/sample/manage/service/ICapacityCameraService.java b/src/main/java/com/dji/sample/manage/service/ICapacityCameraService.java
index 02ab494..df4d3ee 100644
--- a/src/main/java/com/dji/sample/manage/service/ICapacityCameraService.java
+++ b/src/main/java/com/dji/sample/manage/service/ICapacityCameraService.java
@@ -20,14 +20,6 @@
List<CapacityCameraDTO> getCapacityCameraByDeviceSn(String deviceSn);
/**
- * Query whether this camera data has been saved based on the device sn and camera location.
- * @param deviceSn
- * @param cameraIndex
- * @return
- */
- Boolean checkExist(String deviceSn, String cameraIndex);
-
- /**
* Delete all live capability data for this device based on the device sn.
* @param deviceSn
* @return
@@ -38,8 +30,13 @@
* Save the live capability data of the device.
* @param capacityCameraReceivers
* @param deviceSn
+ */
+ void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn);
+
+ /**
+ * Convert the received camera capability object into camera data transfer object.
+ * @param receiver
* @return
*/
- Boolean saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn);
-
+ CapacityCameraDTO receiver2Dto(CapacityCameraReceiver receiver);
}
diff --git a/src/main/java/com/dji/sample/manage/service/IDeviceDictionaryService.java b/src/main/java/com/dji/sample/manage/service/IDeviceDictionaryService.java
index 65324ac..201f82c 100644
--- a/src/main/java/com/dji/sample/manage/service/IDeviceDictionaryService.java
+++ b/src/main/java/com/dji/sample/manage/service/IDeviceDictionaryService.java
@@ -13,12 +13,10 @@
/**
* Query the type data of the device based on domain, device type and sub type.
- * @param domain
* @param deviceType
* @param subType
* @return
*/
- Optional<DeviceDictionaryDTO> getOneDictionaryInfoByDomainTypeSubType(
- Integer domain, Integer deviceType, Integer subType);
+ Optional<DeviceDictionaryDTO> getOneDictionaryInfoByTypeSubType(Integer deviceType, Integer subType);
}
diff --git a/src/main/java/com/dji/sample/manage/service/IDeviceHmsService.java b/src/main/java/com/dji/sample/manage/service/IDeviceHmsService.java
new file mode 100644
index 0000000..c3085ac
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/service/IDeviceHmsService.java
@@ -0,0 +1,21 @@
+package com.dji.sample.manage.service;
+
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.manage.model.dto.DeviceHmsDTO;
+import com.dji.sample.manage.model.param.DeviceHmsQueryParam;
+import org.springframework.messaging.MessageHeaders;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/6
+ */
+public interface IDeviceHmsService {
+
+ void handleHms(CommonTopicReceiver receiver, MessageHeaders headers);
+
+ PaginationData<DeviceHmsDTO> getDeviceHmsByParam(DeviceHmsQueryParam param);
+
+ void updateUnreadHms(String deviceSn);
+}
diff --git a/src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java b/src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java
index 2eb5c0e..93397c7 100644
--- a/src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java
+++ b/src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java
@@ -2,6 +2,7 @@
import com.dji.sample.manage.model.dto.DevicePayloadDTO;
import com.dji.sample.manage.model.receiver.DevicePayloadReceiver;
+import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
import java.util.List;
@@ -45,4 +46,10 @@
* @param deviceSns
*/
void deletePayloadsByDeviceSn(List<String> deviceSns);
+
+ /**
+ * Update the firmware version information of the payload.
+ * @param receiver
+ */
+ void updateFirmwareVersion(FirmwareVersionReceiver receiver);
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/service/IDeviceService.java b/src/main/java/com/dji/sample/manage/service/IDeviceService.java
index 444d49d..911edb7 100644
--- a/src/main/java/com/dji/sample/manage/service/IDeviceService.java
+++ b/src/main/java/com/dji/sample/manage/service/IDeviceService.java
@@ -1,11 +1,15 @@
package com.dji.sample.manage.service;
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.TopologyDeviceDTO;
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 org.springframework.messaging.MessageHeaders;
import java.util.Collection;
import java.util.List;
@@ -90,7 +94,7 @@
* @param sessions The collection of connection objects on the pilot side.
* @param sn
*/
- void pushDeviceOnlineTopo(Collection<ConcurrentWebSocketSession> sessions, String sn);
+ void pushDeviceOnlineTopo(Collection<ConcurrentWebSocketSession> sessions, String sn, String gatewaySn);
/**
* Query the information of the device according to the sn of the device.
@@ -111,9 +115,9 @@
* it also broadcasts a push of device online, offline and topology update to PILOT via websocket,
* and PILOT will get the device topology list again after receiving the push.
* @param workspaceId
- * @param gatewaySn
+ * @param sn
*/
- void pushDeviceOfflineTopo(String workspaceId, String gatewaySn);
+ void pushDeviceOfflineTopo(String workspaceId, String sn);
/**
* When the server receives the request of any device online, offline and topology update in the same workspace,
@@ -123,7 +127,7 @@
* @param deviceSn
* @param gatewaySn
*/
- void pushDeviceOnlineTopo(String workspaceId, String deviceSn, String gatewaySn);
+ void pushDeviceOnlineTopo(String workspaceId, String gatewaySn, String deviceSn);
/**
* Handle messages from the osd topic.
@@ -132,4 +136,63 @@
*/
void handleOSD(String topic, byte[] payload);
+ /**
+ * Update the device information.
+ * @param deviceDTO
+ * @return
+ */
+ Boolean updateDevice(DeviceDTO deviceDTO);
+
+ /**
+ * Bind devices to organizations and people.
+ * @param device
+ */
+ Boolean bindDevice(DeviceDTO device);
+
+ /**
+ * Handle dock binding status requests.
+ * Note: If your business does not need to bind the dock to the organization,
+ * you can directly reply to the successful message without implementing business logic.
+ * @param receiver
+ * @param headers
+ */
+ void bindStatus(CommonTopicReceiver receiver, MessageHeaders headers);
+
+ /**
+ * Handle dock binding requests.
+ * Note: If your business does not need to bind the dock to the organization,
+ * you can directly reply to the successful message without implementing business logic.
+ * @param receiver
+ * @param headers
+ */
+ void bindDevice(CommonTopicReceiver receiver, MessageHeaders headers);
+
+ /**
+ * Get the binding devices list in one workspace.
+ * @param workspaceId
+ * @param page
+ * @param pageSize
+ * @param domain
+ * @return
+ */
+ PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page, Long pageSize, String domain);
+
+ /**
+ * Unbind device base on device's sn.
+ * @param deviceSn
+ */
+ void unbindDevice(String deviceSn);
+
+ /**
+ * Get device information based on device's sn.
+ * @param sn device's sn
+ * @return device
+ */
+ Optional<DeviceDTO> getDeviceBySn(String sn);
+
+ /**
+ * Update the firmware version information of the device or payload.
+ * @param receiver
+ */
+ void updateFirmwareVersion(FirmwareVersionReceiver receiver);
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/service/ILiveStreamService.java b/src/main/java/com/dji/sample/manage/service/ILiveStreamService.java
index 09cba9e..2d1ac98 100644
--- a/src/main/java/com/dji/sample/manage/service/ILiveStreamService.java
+++ b/src/main/java/com/dji/sample/manage/service/ILiveStreamService.java
@@ -3,7 +3,7 @@
import com.dji.sample.common.model.ResponseResult;
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.LiveCapacityReceiver;
import java.util.List;
@@ -22,11 +22,10 @@
List<CapacityDeviceDTO> getLiveCapacity(String workspaceId);
/**
- * Save live capability data from drone.
- * @param capacityDeviceReceiver
- * @return
+ * Save live capability data.
+ * @param liveCapacityReceiver
*/
- Boolean saveLiveCapacity(CapacityDeviceReceiver capacityDeviceReceiver);
+ void saveLiveCapacity(LiveCapacityReceiver liveCapacityReceiver);
/**
* Initiate a live streaming by publishing mqtt message.
diff --git a/src/main/java/com/dji/sample/manage/service/ITSAService.java b/src/main/java/com/dji/sample/manage/service/ITSAService.java
index a444f92..e11a903 100644
--- a/src/main/java/com/dji/sample/manage/service/ITSAService.java
+++ b/src/main/java/com/dji/sample/manage/service/ITSAService.java
@@ -1,5 +1,13 @@
package com.dji.sample.manage.service;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
+import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
+import com.dji.sample.manage.model.dto.DeviceDTO;
+import com.dji.sample.manage.model.dto.TelemetryDTO;
+
+import java.util.Collection;
+
/**
* @author sean
* @version 0.3
@@ -14,4 +22,14 @@
* @param sn
*/
void pushTelemetryData(String workspaceId, Object osdData, String sn);
+
+ /**
+ * Handle device's osd data.
+ * @param receiver
+ * @param webSessions
+ * @param wsMessage
+ */
+ void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
+ Collection<ConcurrentWebSocketSession> webSessions, CustomWebSocketMessage<TelemetryDTO> wsMessage);
+
}
diff --git a/src/main/java/com/dji/sample/manage/service/IUserService.java b/src/main/java/com/dji/sample/manage/service/IUserService.java
index 2ceff96..133c4c7 100644
--- a/src/main/java/com/dji/sample/manage/service/IUserService.java
+++ b/src/main/java/com/dji/sample/manage/service/IUserService.java
@@ -1,7 +1,9 @@
package com.dji.sample.manage.service;
+import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.manage.model.dto.UserDTO;
+import com.dji.sample.manage.model.dto.UserListDTO;
import java.util.Optional;
@@ -19,9 +21,10 @@
* Verify the username and password to log in.
* @param username
* @param password
+ * @param flag
* @return
*/
- ResponseResult userLogin(String username, String password);
+ ResponseResult userLogin(String username, String password, Integer flag);
/**
* Create a user object containing a new token.
@@ -29,4 +32,13 @@
* @return
*/
Optional<UserDTO> refreshToken(String token);
+
+ /**
+ * Query information about all users in a workspace.
+ * @param workspaceId uuid
+ * @return
+ */
+ PaginationData<UserListDTO> getUsersByWorkspaceId(long page, long pageSize, String workspaceId);
+
+ Boolean updateUser(String workspaceId, String userId, UserListDTO user);
}
diff --git a/src/main/java/com/dji/sample/manage/service/IWorkspaceService.java b/src/main/java/com/dji/sample/manage/service/IWorkspaceService.java
index 5defa10..2d80777 100644
--- a/src/main/java/com/dji/sample/manage/service/IWorkspaceService.java
+++ b/src/main/java/com/dji/sample/manage/service/IWorkspaceService.java
@@ -1,18 +1,13 @@
package com.dji.sample.manage.service;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.manage.model.dto.WorkspaceDTO;
+import org.springframework.messaging.MessageHeaders;
import java.util.Optional;
public interface IWorkspaceService {
-
- /**
- * Query the workspace information based on the primary key id of the database.
- * @param id primary key id
- * @return
- */
- Optional<WorkspaceDTO> getWorkspaceById(int id);
/**
* Query the information of a workspace based on its workspace id.
@@ -20,4 +15,19 @@
* @return
*/
Optional<WorkspaceDTO> getWorkspaceByWorkspaceId(String workspaceId);
+
+ /**
+ * Query the workspace of a workspace based on bind code.
+ * @param bindCode
+ * @return
+ */
+ Optional<WorkspaceDTO> getWorkspaceNameByBindCode(String bindCode);
+
+ /**
+ * Handle the request for obtaining the organization information corresponding to the device binding.
+ * Note: If your business does not need to bind the dock to the organization,
+ * you can directly reply to the successful message without implementing business logic.
+ * @param receiver
+ */
+ void replyOrganizationGet(CommonTopicReceiver receiver, MessageHeaders headers);
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java b/src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java
index 35597fa..56b8217 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java
@@ -1,16 +1,17 @@
package com.dji.sample.manage.service.impl;
-import com.dji.sample.component.mqtt.model.TopicStateReceiver;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
-import com.dji.sample.component.websocket.model.WebSocketManager;
import com.dji.sample.component.websocket.service.ISendMessageService;
+import com.dji.sample.component.websocket.service.IWebSocketManageService;
+import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.TelemetryDTO;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.service.ITSAService;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collection;
@@ -24,6 +25,15 @@
protected AbstractTSAService tsaService;
+ @Autowired
+ protected ObjectMapper mapper;
+
+ @Autowired
+ protected RedisOpsUtils redisOps;
+
+ @Autowired
+ private IWebSocketManageService webSocketManageService;
+
public AbstractTSAService(AbstractTSAService tsaService) {
this.tsaService = tsaService;
}
@@ -34,9 +44,8 @@
@Override
public void pushTelemetryData(String workspaceId, Object osdData, String sn) {
// All connected accounts on the pilot side of this workspace.
- Collection<ConcurrentWebSocketSession> pilotSessions = WebSocketManager
- .getValueWithWorkspaceAndUserType(
- workspaceId, UserTypeEnum.PILOT.getVal());
+ Collection<ConcurrentWebSocketSession> pilotSessions = webSocketManageService
+ .getValueWithWorkspaceAndUserType(workspaceId, UserTypeEnum.PILOT.getVal());
TelemetryDTO telemetry = TelemetryDTO.builder()
.sn(sn)
@@ -53,7 +62,6 @@
public abstract void pushTelemetryData(Collection<ConcurrentWebSocketSession> sessions,
CustomWebSocketMessage<TelemetryDTO> message, Object Object);
- protected abstract void handleOSD(TopicStateReceiver receiver, String sn, String workspaceId, JsonNode hostNode,
- Collection<ConcurrentWebSocketSession> webSessions, CustomWebSocketMessage wsMessage)
- throws JsonProcessingException;
+ public abstract void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
+ Collection<ConcurrentWebSocketSession> webSessions, CustomWebSocketMessage<TelemetryDTO> wsMessage);
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/CameraVideoServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/CameraVideoServiceImpl.java
index a2196e4..ec769b3 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/CameraVideoServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/CameraVideoServiceImpl.java
@@ -1,17 +1,11 @@
package com.dji.sample.manage.service.impl;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.dji.sample.manage.dao.ICameraVideoMapper;
import com.dji.sample.manage.model.dto.CapacityVideoDTO;
-import com.dji.sample.manage.model.entity.CameraVideoEntity;
import com.dji.sample.manage.model.receiver.CapacityVideoReceiver;
import com.dji.sample.manage.service.ICameraVideoService;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import java.util.List;
-import java.util.stream.Collectors;
+import java.util.UUID;
/**
* @author sean.zhou
@@ -19,80 +13,17 @@
* @date 2021/11/19
*/
@Service
-@Transactional
+//@Transactional
public class CameraVideoServiceImpl implements ICameraVideoService {
- @Autowired
- private ICameraVideoMapper mapper;
-
@Override
- public List<CapacityVideoDTO> getCameraVideosByCameraId(Integer cameraId) {
- return mapper.selectList(
- new LambdaQueryWrapper<CameraVideoEntity>()
- .eq(CameraVideoEntity::getCameraId, cameraId))
- .stream()
- .map(this::entityConvertToDto)
- .collect(Collectors.toList());
- }
-
- @Override
- public Boolean deleteCameraVideosById(List<Integer> ids) {
- if (ids.isEmpty()) {
- return true;
- }
- return mapper.deleteBatchIds(ids) > 0;
- }
-
- @Override
- public Boolean saveCameraVideoDTOList(List<CapacityVideoReceiver> capacityVideoReceivers, Integer cameraId) {
- for (CapacityVideoReceiver videoDTO : capacityVideoReceivers) {
- CameraVideoEntity videoEntity = videoDTOConvertToEntity(videoDTO);
- videoEntity.setCameraId(cameraId);
- int saveId = this.saveOneCameraVideoEntity(videoEntity);
- if (saveId <= 0) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Save the live capability of the lens of this camera.
- * @param entity lens data
- * @return
- */
- private Integer saveOneCameraVideoEntity(CameraVideoEntity entity) {
- return mapper.insert(entity) > 0 ? entity.getId() : 0;
- }
-
- /**
- * Convert the received lens capability object into a database entity object.
- * @param dto received lens object
- * @return entity
- */
- private CameraVideoEntity videoDTOConvertToEntity(CapacityVideoReceiver dto) {
- CameraVideoEntity.CameraVideoEntityBuilder builder = CameraVideoEntity.builder();
- if (dto != null) {
- builder
- .videoIndex(dto.getVideoIndex())
- .videoType(dto.getVideoType());
- }
- return builder.build();
- }
-
- /**
- * Convert database entity objects into lens data transfer object.
- * @param entity
- * @return data transfer object
- */
- private CapacityVideoDTO entityConvertToDto(CameraVideoEntity entity) {
+ public CapacityVideoDTO receiver2Dto(CapacityVideoReceiver receiver) {
CapacityVideoDTO.CapacityVideoDTOBuilder builder = CapacityVideoDTO.builder();
- if (entity != null) {
- builder
- .id(entity.getId())
- .index(entity.getVideoIndex())
- .type(entity.getVideoType());
+ if (receiver != null) {
+ builder.id(UUID.randomUUID().toString())
+ .index(receiver.getVideoIndex())
+ .type(receiver.getVideoType());
}
return builder.build();
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java
index 7ac4fc4..a524648 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java
@@ -1,23 +1,20 @@
package com.dji.sample.manage.service.impl;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.dji.sample.manage.dao.ICapacityCameraMapper;
+import com.dji.sample.component.mqtt.model.StateDataEnum;
+import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.CapacityCameraDTO;
-import com.dji.sample.manage.model.dto.CapacityVideoDTO;
import com.dji.sample.manage.model.dto.DeviceDictionaryDTO;
-import com.dji.sample.manage.model.entity.CapacityCameraEntity;
-import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.model.receiver.CapacityCameraReceiver;
import com.dji.sample.manage.service.ICameraVideoService;
import com.dji.sample.manage.service.ICapacityCameraService;
import com.dji.sample.manage.service.IDeviceDictionaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.UUID;
import java.util.stream.Collectors;
/**
@@ -26,11 +23,8 @@
* @version 0.1
*/
@Service
-@Transactional
+//@Transactional
public class CapacityCameraServiceImpl implements ICapacityCameraService {
-
- @Autowired
- private ICapacityCameraMapper mapper;
@Autowired
private ICameraVideoService cameraVideoService;
@@ -38,95 +32,29 @@
@Autowired
private IDeviceDictionaryService dictionaryService;
+ @Autowired
+ private RedisOpsUtils redisOps;
+
@Override
public List<CapacityCameraDTO> getCapacityCameraByDeviceSn(String deviceSn) {
- List<CapacityCameraDTO> capacityCamerasList = mapper.selectList(
- new LambdaQueryWrapper<CapacityCameraEntity>()
- .eq(CapacityCameraEntity::getDeviceSn, deviceSn))
- .stream()
- .map(this::entityConvertToDto)
- .collect(Collectors.toList());
- capacityCamerasList.forEach(capacityCamera -> {
- // Set the lens data for this camera.
- capacityCamera.setVideosList(
- cameraVideoService.getCameraVideosByCameraId(capacityCamera.getId()));
- });
-
- return capacityCamerasList;
- }
-
- @Override
- public Boolean checkExist(String deviceSn, String cameraIndex) {
- return mapper.selectOne(
- new LambdaQueryWrapper<CapacityCameraEntity>()
- .eq(CapacityCameraEntity::getDeviceSn, deviceSn)
- .eq(CapacityCameraEntity::getCameraIndex, cameraIndex)
- .last(" limit 1")) != null;
+ return (List<CapacityCameraDTO>) redisOps.hashGet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn);
}
@Override
public Boolean deleteCapacityCameraByDeviceSn(String deviceSn) {
-
- List<CapacityCameraDTO> capacityCamerasList = this.getCapacityCameraByDeviceSn(deviceSn);
- // Return directly if no data exists in the database.
- if (capacityCamerasList.isEmpty()) {
- return true;
- }
-
- List<Integer> cameraIds = capacityCamerasList
- .stream()
- .map(CapacityCameraDTO::getId)
- .collect(Collectors.toList());
-
- List<Integer> videoIds = capacityCamerasList
- .stream()
- .flatMap(camera -> camera.getVideosList().stream())
- .map(CapacityVideoDTO::getId)
- .collect(Collectors.toList());
-
- return mapper.deleteBatchIds(cameraIds) > 0 && cameraVideoService.deleteCameraVideosById(videoIds);
+ return redisOps.hashDel(StateDataEnum.LIVE_CAPACITY.getDesc(), new String[]{deviceSn});
}
@Override
- public Boolean saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn) {
- for (CapacityCameraReceiver cameraDTO : capacityCameraReceivers) {
- CapacityCameraEntity cameraEntity = receiverConvertToEntity(cameraDTO);
- cameraEntity.setDeviceSn(deviceSn);
- int cameraId = this.saveOneCapacityCameraEntity(cameraEntity);
- if (cameraId <= 0) {
- continue;
- }
- boolean saveVideo = cameraVideoService.saveCameraVideoDTOList(
- cameraDTO.getVideosList(), cameraId);
-
- if (!saveVideo) {
- return false;
- }
- }
- return true;
+ public void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn) {
+ List<CapacityCameraDTO> capacity = capacityCameraReceivers.stream()
+ .map(this::receiver2Dto).collect(Collectors.toList());
+ redisOps.hashSet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn, capacity);
}
- /**
- * Save the camera live capability data of the device.
- * @param cameraEntity
- * @return
- */
- private Integer saveOneCapacityCameraEntity(CapacityCameraEntity cameraEntity) {
- boolean exist = checkExist(
- cameraEntity.getDeviceSn(), cameraEntity.getCameraIndex());
- if (exist) {
- return -1;
- }
- return mapper.insert(cameraEntity) > 0 ? cameraEntity.getId() : 0;
- }
-
- /**
- * Convert the received camera capability object into a database entity object.
- * @param receiver
- * @return
- */
- private CapacityCameraEntity receiverConvertToEntity(CapacityCameraReceiver receiver) {
- CapacityCameraEntity.CapacityCameraEntityBuilder builder = CapacityCameraEntity.builder();
+ @Override
+ public CapacityCameraDTO receiver2Dto(CapacityCameraReceiver receiver) {
+ CapacityCameraDTO.CapacityCameraDTOBuilder builder = CapacityCameraDTO.builder();
if (receiver == null) {
return builder.build();
}
@@ -138,35 +66,17 @@
// type-subType-index
if (indexArr.length == 3) {
Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService
- .getOneDictionaryInfoByDomainTypeSubType(
- DeviceDomainEnum.PAYLOAD.getVal(), indexArr[0], indexArr[1]);
+ .getOneDictionaryInfoByTypeSubType(indexArr[0], indexArr[1]);
dictionaryOpt.ifPresent(dictionary ->
builder.name(dictionary.getDeviceName()));
}
return builder
- .availableVideoNumber(receiver.getAvailableVideoNumber())
- .coexistVideoNumberMax(receiver.getCoexistVideoNumberMax())
- .cameraIndex(receiver.getCameraIndex())
+ .id(UUID.randomUUID().toString())
+ .videosList(receiver.getVideosList()
+ .stream()
+ .map(cameraVideoService::receiver2Dto)
+ .collect(Collectors.toList()))
+ .index(receiver.getCameraIndex())
.build();
- }
-
- /**
- * Convert database entity objects into camera data transfer object.
- * @param entity
- * @return
- */
- private CapacityCameraDTO entityConvertToDto(CapacityCameraEntity entity) {
- CapacityCameraDTO.CapacityCameraDTOBuilder builder = CapacityCameraDTO.builder();
-
- if (entity != null) {
- builder
- .id(entity.getId())
- .name(entity.getName())
- .description(entity.getDescription())
- .deviceSn(entity.getDeviceSn())
- .index(entity.getCameraIndex())
- .build();
- }
- return builder.build();
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceDictionaryServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceDictionaryServiceImpl.java
index 60da3d5..f0dbad0 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DeviceDictionaryServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceDictionaryServiceImpl.java
@@ -25,16 +25,14 @@
private IDeviceDictionaryMapper mapper;
@Override
- public Optional<DeviceDictionaryDTO> getOneDictionaryInfoByDomainTypeSubType(
- Integer domain, Integer deviceType, Integer subType) {
- if (domain == null || deviceType == null || subType == null) {
+ public Optional<DeviceDictionaryDTO> getOneDictionaryInfoByTypeSubType(Integer deviceType, Integer subType) {
+ if (deviceType == null || subType == null) {
return Optional.empty();
}
return Optional.ofNullable(
entityConvertToDTO(
mapper.selectOne(
new LambdaQueryWrapper<DeviceDictionaryEntity>()
- .eq(DeviceDictionaryEntity::getDomain, domain)
.eq(DeviceDictionaryEntity::getDeviceType, deviceType)
.eq(DeviceDictionaryEntity::getSubType, subType))));
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java
new file mode 100644
index 0000000..61c13ee
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java
@@ -0,0 +1,133 @@
+package com.dji.sample.manage.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.dji.sample.common.model.Pagination;
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.component.mqtt.model.ChannelName;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.mqtt.model.MapKeyConst;
+import com.dji.sample.component.mqtt.model.TopicConst;
+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.model.BizCodeEnum;
+import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
+import com.dji.sample.component.websocket.service.impl.SendMessageServiceImpl;
+import com.dji.sample.component.websocket.service.impl.WebSocketManageServiceImpl;
+import com.dji.sample.manage.dao.IDeviceHmsMapper;
+import com.dji.sample.manage.model.common.HmsJsonUtil;
+import com.dji.sample.manage.model.common.HmsMessage;
+import com.dji.sample.manage.model.dto.DeviceDTO;
+import com.dji.sample.manage.model.dto.DeviceHmsDTO;
+import com.dji.sample.manage.model.dto.TelemetryDTO;
+import com.dji.sample.manage.model.entity.DeviceHmsEntity;
+import com.dji.sample.manage.model.enums.HmsEnum;
+import com.dji.sample.manage.model.enums.UserTypeEnum;
+import com.dji.sample.manage.model.param.DeviceHmsQueryParam;
+import com.dji.sample.manage.model.receiver.DeviceHmsReceiver;
+import com.dji.sample.manage.model.receiver.HmsArgsReceiver;
+import com.dji.sample.manage.service.IDeviceHmsService;
+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.ServiceActivator;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/7/6
+ */
+@Service
+@Transactional
+public class DeviceHmsServiceImpl implements IDeviceHmsService {
+
+ @Autowired
+ private IDeviceHmsMapper mapper;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Autowired
+ private RedisOpsUtils redisOps;
+
+ @Autowired
+ private SendMessageServiceImpl sendMessageService;
+
+ @Autowired
+ private WebSocketManageServiceImpl webSocketManageService;
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_HMS)
+ public void handleHms(CommonTopicReceiver receiver, MessageHeaders headers) {
+ }
+
+ @Override
+ public PaginationData<DeviceHmsDTO> getDeviceHmsByParam(DeviceHmsQueryParam param) {
+ LambdaQueryWrapper<DeviceHmsEntity> queryWrapper = new LambdaQueryWrapper<DeviceHmsEntity>()
+ .and(wrapper -> param.getDeviceSn().forEach(sn -> wrapper.eq(DeviceHmsEntity::getSn, sn).or()))
+ .between(param.getBeginTime() != null && param.getEndTime() != null,
+ DeviceHmsEntity::getCreateTime, param.getBeginTime(), param.getEndTime())
+ .eq(param.getUpdateTime() != null, DeviceHmsEntity::getUpdateTime, param.getUpdateTime())
+ .eq(param.getLevel() != null, DeviceHmsEntity::getLevel, param.getLevel())
+ .like(StringUtils.hasText(param.getMessage()) &&
+ HmsEnum.MessageLanguage.ZH.getLanguage().equals(param.getLanguage()),
+ DeviceHmsEntity::getMessageZh, param.getMessage())
+ .like(StringUtils.hasText(param.getMessage()) &&
+ HmsEnum.MessageLanguage.EN.getLanguage().equals(param.getLanguage()),
+ DeviceHmsEntity::getMessageEn, param.getMessage())
+ .orderByDesc(DeviceHmsEntity::getCreateTime);
+ if (param.getPage() == null || param.getPageSize() == null) {
+ param.setPage(1L);
+ param.setPageSize(Long.valueOf(mapper.selectCount(queryWrapper)));
+ }
+
+ Page<DeviceHmsEntity> pagination = mapper.selectPage(new Page<>(param.getPage(), param.getPageSize()), queryWrapper);
+
+ List<DeviceHmsDTO> deviceHmsList = pagination.getRecords().stream().map(this::entity2Dto).collect(Collectors.toList());
+
+ return new PaginationData<DeviceHmsDTO>(deviceHmsList, new Pagination(pagination));
+ }
+
+ @Override
+ public void updateUnreadHms(String deviceSn) {
+ mapper.update(DeviceHmsEntity.builder().updateTime(System.currentTimeMillis()).build(),
+ new LambdaUpdateWrapper<DeviceHmsEntity>()
+ .eq(DeviceHmsEntity::getSn, deviceSn)
+ .eq(DeviceHmsEntity::getUpdateTime, 0L));
+ redisOps.del(RedisConst.HMS_PREFIX + deviceSn);
+ }
+
+ private DeviceHmsDTO entity2Dto(DeviceHmsEntity entity) {
+ if (entity == null) {
+ return null;
+ }
+ return DeviceHmsDTO.builder()
+ .bid(entity.getBid())
+ .tid(entity.getTid())
+ .createTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
+ .updateTime(entity.getUpdateTime().intValue() == 0 ?
+ null : LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getUpdateTime()), ZoneId.systemDefault()))
+ .sn(entity.getSn())
+ .hmsId(entity.getHmsId())
+ .key(entity.getHmsKey())
+ .level(entity.getLevel())
+ .module(entity.getModule())
+ .messageEn(entity.getMessageEn())
+ .messageZh(entity.getMessageZh())
+ .build();
+ }
+
+}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java
index 606343c..9fc690d 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java
@@ -1,22 +1,25 @@
package com.dji.sample.manage.service.impl;
-import com.dji.sample.component.mqtt.model.TopicStateReceiver;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
-import com.dji.sample.manage.model.DeviceStatusManager;
+import com.dji.sample.manage.model.dto.DeviceDTO;
+import com.dji.sample.manage.model.dto.DevicePayloadDTO;
import com.dji.sample.manage.model.dto.TelemetryDTO;
import com.dji.sample.manage.model.dto.TelemetryDeviceDTO;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
+import com.dji.sample.manage.model.receiver.OsdPayloadReceiver;
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-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.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
-import java.time.LocalDateTime;
import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
* @author sean
@@ -24,10 +27,11 @@
* @date 2022/2/21
*/
@Service
+@Slf4j
public class DeviceOSDServiceImpl extends AbstractTSAService {
- protected DeviceOSDServiceImpl() {
- super(null);
+ protected DeviceOSDServiceImpl(@Autowired @Qualifier("dockOSDServiceImpl") AbstractTSAService tsaService) {
+ super(tsaService);
}
@Override
@@ -50,20 +54,32 @@
}
}
@Override
- protected void handleOSD(TopicStateReceiver receiver, String sn, String workspaceId, JsonNode hostNode,
- Collection<ConcurrentWebSocketSession> webSessions, CustomWebSocketMessage wsMessage) throws JsonProcessingException {
- // Real-time update of device status in memory
- DeviceStatusManager.STATUS_MANAGER.put(
- DeviceDomainEnum.SUB_DEVICE.getVal() + "/" + sn, LocalDateTime.now());
- wsMessage.setBizCode(BizCodeEnum.DEVICE_OSD.getCode());
+ public void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
+ Collection<ConcurrentWebSocketSession> webSessions,
+ CustomWebSocketMessage<TelemetryDTO> wsMessage) {
+ if (DeviceDomainEnum.SUB_DEVICE.getDesc().equals(device.getDomain())) {
+ wsMessage.setBizCode(BizCodeEnum.DEVICE_OSD.getCode());
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- OsdSubDeviceReceiver data = mapper.treeToValue(hostNode, OsdSubDeviceReceiver.class);
+ OsdSubDeviceReceiver data = mapper.convertValue(receiver.getData(), OsdSubDeviceReceiver.class);
+ List<DevicePayloadDTO> payloadsList = device.getPayloadsList();
+ try {
+ Map<String, Object> receiverData = (Map<String, Object>) receiver.getData();
+ data.setPayloads(payloadsList.stream()
+ .map(payload -> mapper.convertValue(
+ receiverData.getOrDefault(payload.getPayloadName(), Map.of()),
+ OsdPayloadReceiver.class))
+ .collect(Collectors.toList()));
- wsMessage.setData(data);
+ } catch (NullPointerException e) {
+ log.warn("Please remount the payload, or restart the drone. Otherwise the data of the payload will not be received.");
+ }
- sendMessageService.sendBatch(webSessions, wsMessage);
- this.pushTelemetryData(workspaceId, data, sn);
+
+ wsMessage.getData().setHost(data);
+
+ sendMessageService.sendBatch(webSessions, wsMessage);
+ this.pushTelemetryData(device.getWorkspaceId(), data, device.getDeviceSn());
+ }
+ tsaService.handleOSD(receiver, device, webSessions, wsMessage);
}
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java
index a88504f..7f05b54 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java
@@ -1,12 +1,16 @@
package com.dji.sample.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.dji.sample.component.redis.RedisConst;
+import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.dao.IDevicePayloadMapper;
+import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.DeviceDictionaryDTO;
import com.dji.sample.manage.model.dto.DevicePayloadDTO;
import com.dji.sample.manage.model.entity.DevicePayloadEntity;
-import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.model.receiver.DevicePayloadReceiver;
+import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
import com.dji.sample.manage.service.ICapacityCameraService;
import com.dji.sample.manage.service.IDeviceDictionaryService;
import com.dji.sample.manage.service.IDevicePayloadService;
@@ -14,6 +18,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@@ -37,6 +42,9 @@
@Autowired
private ICapacityCameraService capacityCameraService;
+ @Autowired
+ private RedisOpsUtils redisOps;
+
@Override
public Integer checkPayloadExist(String payloadSn) {
DevicePayloadEntity devicePayload = mapper.selectOne(
@@ -57,12 +65,28 @@
@Override
public Boolean savePayloadDTOs(List<DevicePayloadReceiver> payloadReceiverList) {
+ if (payloadReceiverList.isEmpty()) {
+ return true;
+ }
+
+ String deviceSn = payloadReceiverList.get(0).getDeviceSn();
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
+ DeviceDTO device = (DeviceDTO) redisOps.get(key);
+ List<DevicePayloadDTO> payloads = new ArrayList<>();
+
for (DevicePayloadReceiver payloadReceiver : payloadReceiverList) {
int payloadId = this.saveOnePayloadDTO(payloadReceiver);
if (payloadId <= 0) {
return false;
}
+ payloads.add(this.receiver2Dto(payloadReceiver));
}
+
+ if (payloads.isEmpty()) {
+ payloads = this.getDevicePayloadEntitiesByDeviceSn(deviceSn);
+ }
+ device.setPayloadsList(payloads);
+ redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(), device, RedisConst.DEVICE_ALIVE_SECOND);
return true;
}
@@ -89,6 +113,15 @@
.eq(DevicePayloadEntity::getDeviceSn, deviceSn));
capacityCameraService.deleteCapacityCameraByDeviceSn(deviceSn);
});
+ }
+
+ @Override
+ public void updateFirmwareVersion(FirmwareVersionReceiver receiver) {
+ mapper.update(DevicePayloadEntity.builder()
+ .firmwareVersion(receiver.getFirmwareVersion())
+ .build()
+ , new LambdaUpdateWrapper<DevicePayloadEntity>()
+ .eq(DevicePayloadEntity::getDeviceSn, receiver.getSn()));
}
/**
@@ -129,8 +162,7 @@
if (arr.length == 3) {
Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService
- .getOneDictionaryInfoByDomainTypeSubType(DeviceDomainEnum.PAYLOAD.getVal(),
- arr[0], arr[1]);
+ .getOneDictionaryInfoByTypeSubType(arr[0], arr[1]);
dictionaryOpt.ifPresent(dictionary ->
builder.payloadName(dictionary.getDeviceName())
.payloadDesc(dictionary.getDeviceDesc()));
@@ -147,10 +179,17 @@
return builder
.payloadSn(dto.getSn())
- .version(dto.getVersion())
- .deviceSn(dto.getSn()
- .substring(0,
- dto.getSn().indexOf("-")))
+ .deviceSn(dto.getDeviceSn())
+ .build();
+ }
+
+ private DevicePayloadDTO receiver2Dto(DevicePayloadReceiver receiver) {
+ DevicePayloadDTO.DevicePayloadDTOBuilder builder = DevicePayloadDTO.builder();
+ if (receiver == null) {
+ return builder.build();
+ }
+ return builder.payloadSn(receiver.getSn())
+ .payloadName(receiver.getPayloadIndex())
.build();
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
index 80e34df..dbfbf77 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
@@ -1,15 +1,21 @@
package com.dji.sample.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.dji.sample.component.mqtt.model.CommonTopicResponse;
-import com.dji.sample.component.mqtt.model.TopicStateReceiver;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.dji.sample.common.error.CommonErrorEnum;
+import com.dji.sample.common.model.Pagination;
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.component.mqtt.model.*;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
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.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
-import com.dji.sample.component.websocket.model.WebSocketManager;
import com.dji.sample.component.websocket.service.ISendMessageService;
+import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.manage.dao.IDeviceMapper;
import com.dji.sample.manage.model.dto.*;
import com.dji.sample.manage.model.entity.DeviceEntity;
@@ -17,28 +23,26 @@
import com.dji.sample.manage.model.enums.IconUrlEnum;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.param.DeviceQueryParam;
-import com.dji.sample.manage.model.receiver.StatusGatewayReceiver;
-import com.dji.sample.manage.model.receiver.StatusSubDeviceReceiver;
-import com.dji.sample.manage.service.IDeviceDictionaryService;
-import com.dji.sample.manage.service.IDevicePayloadService;
-import com.dji.sample.manage.service.IDeviceService;
-import com.dji.sample.manage.service.IWorkspaceService;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonNode;
+import com.dji.sample.manage.model.receiver.*;
+import com.dji.sample.manage.service.*;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@@ -77,23 +81,61 @@
private ISendMessageService sendMessageService;
@Autowired
+ private ObjectMapper objectMapper;
+
+ @Autowired
+ private RedisOpsUtils redisOps;
+
+ @Autowired
+ private IWebSocketManageService webSocketManageService;
+
+ @Autowired
@Qualifier("gatewayOSDServiceImpl")
- private AbstractTSAService tsaService;
+ private ITSAService tsaService;
@Override
public Boolean deviceOffline(String gatewaySn) {
- List<DeviceDTO> gatewaysList = this.getDevicesByParams(
- DeviceQueryParam.builder()
- .deviceSn(gatewaySn)
- .build());
+ this.subscribeTopicOnline(gatewaySn);
- // If no information about this gateway device exists in the database, the drone is considered to be offline.
- if (gatewaysList.isEmpty()) {
- log.debug("The drone is already offline.");
+ // Only the remote controller is logged in and the aircraft is not connected.
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + gatewaySn;
+
+ boolean exist = redisOps.checkExist(key);
+ if (!exist) {
+ Optional<DeviceDTO> gatewayOpt = this.getDeviceBySn(gatewaySn);
+ if (gatewayOpt.isPresent()) {
+ DeviceDTO value = gatewayOpt.get();
+ value.setChildDeviceSn(value.getDeviceSn());
+ value.setBoundTime(null);
+ value.setLoginTime(null);
+ redisOps.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
+ this.pushDeviceOnlineTopo(value.getWorkspaceId(), gatewaySn, gatewaySn);
+ return true;
+ }
+ DeviceDTO gateway = DeviceDTO.builder()
+ .deviceSn(gatewaySn)
+ .childDeviceSn(gatewaySn)
+ .domain(DeviceDomainEnum.GATEWAY.getDesc())
+ .build();
+ gatewayOpt.map(DeviceDTO::getWorkspaceId).ifPresent(gateway::setWorkspaceId);
+ redisOps.setWithExpire(key, gateway, RedisConst.DEVICE_ALIVE_SECOND);
+ this.pushDeviceOnlineTopo(gateway.getWorkspaceId(), gatewaySn, gatewaySn);
return true;
}
- // Handle the drone connected to the gateway device offline.
- return this.subDeviceOffline(gatewaysList.get(0).getChildDeviceSn());
+
+ long expire = redisOps.getExpire(key);
+ // If the key about the device in redis has expired, the remote control is considered to be offline.
+ if (expire <= 0) {
+ log.debug("The remote control is already offline.");
+ return true;
+ }
+
+ String deviceSn = ((DeviceDTO)(redisOps.get(key))).getChildDeviceSn();
+ if (deviceSn.equals(gatewaySn)) {
+ return true;
+ }
+
+ return subDeviceOffline(deviceSn);
}
@Override
@@ -101,82 +143,117 @@
// Cancel drone-related subscriptions.
this.unsubscribeTopicOffline(deviceSn);
- List<DeviceDTO> devicesList = this.getDevicesByParams(
- DeviceQueryParam.builder()
- .deviceSn(deviceSn)
- .build());
-
- // If no information about this drone exists in the database, the drone is considered to be offline.
- if (devicesList.isEmpty()) {
- log.debug("{} is already offline.", deviceSn);
+ payloadService.deletePayloadsByDeviceSn(new ArrayList<>(List.of(deviceSn)));
+ // If no information about this gateway device exists in the database, the drone is considered to be offline.
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
+ if (!redisOps.checkExist(key) || redisOps.getExpire(key) <= 0) {
+ log.debug("The drone is already offline.");
return true;
}
+ DeviceDTO device = (DeviceDTO) redisOps.get(key);
+ // Publish the latest device topology information in the current workspace.
+ this.pushDeviceOfflineTopo(device.getWorkspaceId(), deviceSn);
- List<String> ids = devicesList.stream()
- .map(DeviceDTO::getDeviceSn)
- .collect(Collectors.toList());
-
- // Delete all data related to the drone.
- boolean isDel = this.delDeviceByDeviceSns(ids);
- payloadService.deletePayloadsByDeviceSn(ids);
-
- log.debug("{} offline status: {}.", deviceSn, isDel);
- return isDel;
+ redisOps.del(key);
+ log.debug("{} offline.", deviceSn);
+ return true;
}
@Override
public Boolean deviceOnline(StatusGatewayReceiver deviceGateway) {
String deviceSn = deviceGateway.getSubDevices().get(0).getSn();
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
+ // change log: Use redis instead of
+ long time = redisOps.getExpire(key);
+ long now = System.currentTimeMillis();
- List<DeviceDTO> devicesList = this.getDevicesByParams(
- DeviceQueryParam.builder()
- .deviceSn(deviceSn)
- .build());
- // If the information about this drone exists in the database, the drone is considered to be online.
- if (!devicesList.isEmpty()) {
+ if (time > 0) {
+ redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn(), RedisConst.DEVICE_ALIVE_SECOND);
+ redisOps.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND);
+ DeviceDTO device = DeviceDTO.builder().loginTime(LocalDateTime.now()).deviceSn(deviceSn).build();
+ DeviceDTO gateway = DeviceDTO.builder()
+ .loginTime(LocalDateTime.now())
+ .deviceSn(deviceGateway.getSn())
+ .childDeviceSn(deviceSn).build();
+ this.updateDevice(gateway);
+ this.updateDevice(device);
+ String workspaceId = ((DeviceDTO)(redisOps.get(key))).getWorkspaceId();
+ if (StringUtils.hasText(workspaceId)) {
+ this.subscribeTopicOnline(deviceSn);
+ this.subscribeTopicOnline(deviceGateway.getSn());
+ }
log.warn("{} is already online.", deviceSn);
- // Subscribe to topic related to drone and gateway devices.
- this.subscribeTopicOnline(deviceGateway.getSn());
- this.subscribeTopicOnline(deviceSn);
return true;
}
- // Delete the gateway device information that was previously bound to the drone.
- this.delDeviceByDeviceSns(
- this.getDevicesByParams(
- DeviceQueryParam.builder()
- .childSn(deviceSn)
- .build())
- .stream()
- .map(DeviceDTO::getDeviceSn)
- .collect(Collectors.toList()));
+ List<DeviceDTO> gatewaysList = this.getDevicesByParams(
+ DeviceQueryParam.builder()
+ .childSn(deviceSn)
+ .build());
+ gatewaysList.stream().filter(
+ gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn()))
+ .findAny()
+ .ifPresent(gateway -> {
+ gateway.setChildDeviceSn("");
+ this.updateDevice(gateway);
+ });
+
DeviceEntity gateway = deviceGatewayConvertToDeviceEntity(deviceGateway);
- gateway.setWorkspaceId(WorkspaceDTO.DEFAULT_WORKSPACE_ID);
+ gateway.setChildSn(deviceSn);
// Set the icon of the gateway device displayed in the pilot's map, required in the TSA module.
gateway.setUrlNormal(IconUrlEnum.NORMAL_PERSON.getUrl());
// Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module.
gateway.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl());
+ gateway.setLoginTime(now);
DeviceEntity subDevice = subDeviceConvertToDeviceEntity(deviceGateway.getSubDevices().get(0));
- subDevice.setWorkspaceId(WorkspaceDTO.DEFAULT_WORKSPACE_ID);
- // Set the icon of the drone device displayed in the pilot's map, required in the TSA module.
- subDevice.setUrlSelect(IconUrlEnum.SELECT_EQUIPMENT.getUrl());
// Set the icon of the drone device displayed in the pilot's map when it is selected, required in the TSA module.
subDevice.setUrlNormal(IconUrlEnum.NORMAL_EQUIPMENT.getUrl());
+ // Set the icon of the drone device displayed in the pilot's map, required in the TSA module.
+ subDevice.setUrlSelect(IconUrlEnum.SELECT_EQUIPMENT.getUrl());
+ subDevice.setLoginTime(now);
- gateway.setChildSn(subDevice.getDeviceSn());
-
- boolean isSave = this.saveDevice(gateway) > 0 && this.saveDevice(subDevice) > 0;
-
- log.debug(subDevice.getDeviceSn() + " online status: {}", isSave);
- if (isSave) {
- // Subscribe to topic related to drone and gateway devices.
- this.subscribeTopicOnline(subDevice.getDeviceSn());
- this.subscribeTopicOnline(gateway.getDeviceSn());
-
+ // dock go online
+ if (deviceGateway.getDomain() != null && DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain()) {
+ Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(deviceGateway.getSn());
+ if (deviceOpt.isEmpty()) {
+ log.info("The dock is not bound and cannot go online.");
+ return false;
+ }
+ gateway.setNickname(null);
+ subDevice.setNickname(null);
}
- return isSave;
+
+ Optional<DeviceEntity> gatewayOpt = this.saveDevice(gateway);
+ String workspaceId = this.saveDevice(subDevice).orElse(subDevice).getWorkspaceId();
+
+ redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceSn,
+ DeviceDTO.builder()
+ .deviceSn(deviceSn)
+ .domain(DeviceDomainEnum.SUB_DEVICE.getDesc())
+ .workspaceId(workspaceId)
+ .build(),
+ RedisConst.DEVICE_ALIVE_SECOND);
+ redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn(),
+ DeviceDTO.builder()
+ .deviceSn(gateway.getDeviceSn())
+ .workspaceId(gatewayOpt.orElse(gateway).getWorkspaceId())
+ .childDeviceSn(deviceSn)
+ .domain(deviceGateway.getDomain() != null ?
+ DeviceDomainEnum.getDesc(deviceGateway.getDomain()) :
+ DeviceDomainEnum.GATEWAY.getDesc())
+ .build(),
+ RedisConst.DEVICE_ALIVE_SECOND);
+ log.debug("{} online.", subDevice.getDeviceSn());
+
+ if (StringUtils.hasText(workspaceId)) {
+ this.pushDeviceOnlineTopo(workspaceId, deviceGateway.getSn(), deviceSn);
+ }
+ // Subscribe to topic related to drone devices.
+ this.subscribeTopicOnline(deviceSn);
+ this.subscribeTopicOnline(deviceGateway.getSn());
+ return true;
}
@Override
@@ -191,6 +268,8 @@
topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + OSD_SUF);
topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + STATE_SUF);
topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + SERVICES_SUF + _REPLY_SUF);
+ topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + REQUESTS_SUF);
+ topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + EVENTS_SUF);
}
@Override
@@ -198,6 +277,8 @@
topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + OSD_SUF);
topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + STATE_SUF);
topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + SERVICES_SUF + _REPLY_SUF);
+ topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + REQUESTS_SUF);
+ topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + EVENTS_SUF);
}
@Override
@@ -232,17 +313,21 @@
return mapper.selectList(
new LambdaQueryWrapper<DeviceEntity>()
.eq(StringUtils.hasText(param.getDeviceSn()),
- DeviceEntity::getDeviceSn, param.getDeviceSn())
+ DeviceEntity::getDeviceSn, param.getDeviceSn())
.eq(param.getDeviceType() != null,
DeviceEntity::getDeviceType, param.getDeviceType())
.eq(param.getSubType() != null,
DeviceEntity::getSubType, param.getSubType())
.eq(StringUtils.hasText(param.getChildSn()),
DeviceEntity::getChildSn, param.getChildSn())
- .eq(param.getDomain() != null,
- DeviceEntity::getDomain, param.getDomain())
+ .and(!CollectionUtils.isEmpty(param.getDomains()), wrapper -> {
+ for (Integer domain : param.getDomains()) {
+ wrapper.eq(DeviceEntity::getDomain, domain).or();
+ }
+ })
.eq(StringUtils.hasText(param.getWorkspaceId()),
DeviceEntity::getWorkspaceId, param.getWorkspaceId())
+ .eq(param.getBoundStatus() != null, DeviceEntity::getBoundStatus, param.getBoundStatus())
.orderBy(param.isOrderBy(),
param.isAsc(), DeviceEntity::getId))
.stream()
@@ -255,13 +340,13 @@
List<DeviceDTO> devicesList = this.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
- .domain(DeviceDomainEnum.SUB_DEVICE.getVal())
+ .domains(List.of(DeviceDomainEnum.SUB_DEVICE.getVal()))
.build());
devicesList.forEach(device -> {
this.spliceDeviceTopo(device);
device.setWorkspaceId(workspaceId);
-
+ device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
});
return devicesList;
}
@@ -301,7 +386,7 @@
}
@Override
- public void pushDeviceOnlineTopo(Collection<ConcurrentWebSocketSession> sessions, String sn) {
+ public void pushDeviceOnlineTopo(Collection<ConcurrentWebSocketSession> sessions, String sn, String gatewaySn) {
CustomWebSocketMessage<TopologyDeviceDTO> pilotMessage =
CustomWebSocketMessage.<TopologyDeviceDTO>builder()
@@ -312,6 +397,9 @@
this.getDeviceTopoForPilot(sn)
.ifPresent(pilotMessage::setData);
+ boolean exist = redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn);
+ pilotMessage.getData().setOnlineStatus(exist);
+ pilotMessage.getData().setGatewaySn(gatewaySn.equals(sn) ? "" : gatewaySn);
sendMessageService.sendBatch(sessions, pilotMessage);
}
@@ -321,91 +409,82 @@
TopologyDeviceDTO.TopologyDeviceDTOBuilder builder = TopologyDeviceDTO.builder();
if (device != null) {
- String domain = String.valueOf(DeviceDomainEnum.getVal(device.getDomain()));
+ int domain = DeviceDomainEnum.getVal(device.getDomain());
String subType = String.valueOf(device.getSubType());
String type = String.valueOf(device.getType());
builder.sn(device.getDeviceSn())
- .deviceCallsign(device.getDeviceName())
+ .deviceCallsign(device.getNickname())
.deviceModel(DeviceModelDTO.builder()
- .domain(domain)
+ .domain(String.valueOf(domain))
.subType(subType)
.type(type)
.key(domain + "-" + type + "-" + subType)
.build())
.iconUrls(device.getIconUrl())
+ .onlineStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
+ .boundStatus(device.getBoundStatus())
+ .model(device.getDeviceName())
+ .userId(device.getUserId())
+ .domain(DeviceDomainEnum.getDesc(domain))
.build();
}
return builder.build();
}
@Override
- public void pushDeviceOnlineTopo(String workspaceId, String deviceSn, String gatewaySn) {
+ public void pushDeviceOnlineTopo(String workspaceId, String gatewaySn, String deviceSn) {
- // All connected accounts on the pilot side of this workspace.
- Collection<ConcurrentWebSocketSession> pilotSessions = WebSocketManager
- .getValueWithWorkspaceAndUserType(
- workspaceId, UserTypeEnum.PILOT.getVal());
+ // All connected accounts in this workspace.
+ Collection<ConcurrentWebSocketSession> allSessions = webSocketManageService.getValueWithWorkspace(workspaceId);
- this.pushDeviceOnlineTopo(pilotSessions, deviceSn);
- this.pushDeviceOnlineTopo(pilotSessions, gatewaySn);
- this.pushDeviceUpdateTopo(pilotSessions, deviceSn);
- this.pushDeviceUpdateTopo(pilotSessions, gatewaySn);
+ if (!gatewaySn.equals(deviceSn)) {
+ this.pushDeviceOnlineTopo(allSessions, deviceSn, gatewaySn);
+ this.pushDeviceUpdateTopo(allSessions, deviceSn);
+ }
+ this.pushDeviceOnlineTopo(allSessions, gatewaySn, gatewaySn);
+ this.pushDeviceUpdateTopo(allSessions, gatewaySn);
}
@Override
- public void pushDeviceOfflineTopo(String workspaceId, String gatewaySn) {
- // All connected accounts on the pilot side of this workspace.
- Collection<ConcurrentWebSocketSession> pilotSessions = WebSocketManager
- .getValueWithWorkspaceAndUserType(
- workspaceId, UserTypeEnum.PILOT.getVal());
+ public void pushDeviceOfflineTopo(String workspaceId, String sn) {
+ // All connected accounts of this workspace.
+ Collection<ConcurrentWebSocketSession> allSessions = webSocketManageService
+ .getValueWithWorkspace(workspaceId);
-
- List<DeviceDTO> gatewaysList = this.getDevicesByParams(
- DeviceQueryParam.builder()
- .deviceSn(gatewaySn)
- .build());
-
- if (!gatewaysList.isEmpty()) {
- String deviceSn = gatewaysList.get(0).getChildDeviceSn();
- this.pushDeviceOfflineTopo(pilotSessions, deviceSn);
- this.pushDeviceUpdateTopo(pilotSessions, deviceSn);
- }
-
- this.pushDeviceOfflineTopo(pilotSessions, gatewaySn);
- this.pushDeviceUpdateTopo(pilotSessions, gatewaySn);
+ this.pushDeviceOfflineTopo(allSessions, sn);
+ this.pushDeviceUpdateTopo(allSessions, sn);
}
@Override
public void handleOSD(String topic, byte[] payload) {
- TopicStateReceiver receiver;
+ CommonTopicReceiver receiver;
try {
String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(),
topic.indexOf(OSD_SUF));
- List<DeviceDTO> deviceList = this.getDevicesByParams(
- DeviceQueryParam.builder().deviceSn(from).build());
- if (deviceList.isEmpty()) {
+ // Real-time update of device status in memory
+ redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND);
+
+ DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + from);
+
+ if (device == null || !StringUtils.hasText(device.getWorkspaceId())) {
return;
}
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ receiver = objectMapper.readValue(payload, CommonTopicReceiver.class);
- receiver = mapper.readValue(payload, TopicStateReceiver.class);
+ CustomWebSocketMessage<TelemetryDTO> wsMessage = CustomWebSocketMessage.<TelemetryDTO>builder()
+ .timestamp(System.currentTimeMillis())
+ .data(TelemetryDTO.builder().sn(from).build())
+ .build();
- CustomWebSocketMessage wsMessage = CustomWebSocketMessage.builder()
- .timestamp(System.currentTimeMillis()).build();
-
- JsonNode hostNode = mapper.readTree(payload).findPath("data");
-
- String workspaceId = deviceList.get(0).getWorkspaceId();
- Collection<ConcurrentWebSocketSession> webSessions = WebSocketManager
+ Collection<ConcurrentWebSocketSession> webSessions = webSocketManageService
.getValueWithWorkspaceAndUserType(
- workspaceId, UserTypeEnum.WEB.getVal());
+ device.getWorkspaceId(), UserTypeEnum.WEB.getVal());
- tsaService.handleOSD(receiver, from, workspaceId, hostNode, webSessions, wsMessage);
+ tsaService.handleOSD(receiver, device, webSessions, wsMessage);
} catch (IOException e) {
e.printStackTrace();
@@ -451,7 +530,7 @@
* @param entity
* @return
*/
- private Integer saveDevice(DeviceEntity entity) {
+ private Optional<DeviceEntity> saveDevice(DeviceEntity entity) {
DeviceEntity deviceEntity = mapper.selectOne(
new LambdaQueryWrapper<DeviceEntity>()
.eq(DeviceEntity::getDeviceSn, entity.getDeviceSn()));
@@ -459,9 +538,9 @@
if (deviceEntity != null) {
entity.setId(deviceEntity.getId());
mapper.updateById(entity);
- return deviceEntity.getId();
+ return Optional.of(deviceEntity);
}
- return mapper.insert(entity) > 0 ? entity.getId() : 0;
+ return mapper.insert(entity) > 0 ? Optional.of(entity) : Optional.empty();
}
/**
@@ -477,19 +556,20 @@
// Query the model information of this gateway device.
Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService
- .getOneDictionaryInfoByDomainTypeSubType(gateway.getDomain(),
- gateway.getType(), gateway.getSubType());
+ .getOneDictionaryInfoByTypeSubType(gateway.getType(), gateway.getSubType());
dictionaryOpt.ifPresent(entity ->
builder.deviceName(entity.getDeviceName())
+ .nickname(entity.getDeviceName())
.deviceDesc(entity.getDeviceDesc()));
return builder
.deviceSn(gateway.getSn())
- .domain(gateway.getDomain())
.subType(gateway.getSubType())
.deviceType(gateway.getType())
.version(gateway.getVersion())
+ .domain(gateway.getDomain() != null ?
+ gateway.getDomain() : DeviceDomainEnum.GATEWAY.getVal())
.build();
}
@@ -506,48 +586,330 @@
// Query the model information of this drone device.
Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService
- .getOneDictionaryInfoByDomainTypeSubType(DeviceDomainEnum.SUB_DEVICE.getVal(),
- device.getType(), device.getSubType());
+ .getOneDictionaryInfoByTypeSubType(device.getType(), device.getSubType());
dictionaryOpt.ifPresent(dictionary ->
builder.deviceName(dictionary.getDeviceName())
+ .nickname(dictionary.getDeviceName())
.deviceDesc(dictionary.getDeviceDesc()));
return builder
.deviceSn(device.getSn())
.deviceType(device.getType())
.subType(device.getSubType())
- .domain(DeviceDomainEnum.SUB_DEVICE.getVal())
.version(device.getVersion())
.deviceIndex(device.getIndex())
+ .domain(device.getDomain() != null ?
+ device.getDomain() : DeviceDomainEnum.SUB_DEVICE.getVal())
.build();
}
/**
- * Convert database entity objects into device data transfer object.
+ * Convert database entity object into device data transfer object.
* @param entity
* @return
*/
private DeviceDTO deviceEntityConvertToDTO(DeviceEntity entity) {
- DeviceDTO.DeviceDTOBuilder builder = DeviceDTO.builder();
-
- if (entity != null) {
- builder.deviceSn(entity.getDeviceSn())
- .childDeviceSn(entity.getChildSn())
- .deviceName(entity.getDeviceName())
- .deviceDesc(entity.getDeviceDesc())
- .deviceIndex(entity.getDeviceIndex())
- .workspaceId(entity.getWorkspaceId())
- .type(entity.getDeviceType())
- .subType(entity.getSubType())
- .domain(DeviceDomainEnum.getDesc(entity.getDomain()))
- .iconUrl(IconUrlDTO.builder()
- .normalUrl(entity.getUrlNormal())
- .selectUrl(entity.getUrlSelect())
- .build())
- .build();
+ if (entity == null) {
+ return null;
}
- return builder.build();
+ return DeviceDTO.builder()
+ .deviceSn(entity.getDeviceSn())
+ .childDeviceSn(entity.getChildSn())
+ .deviceName(entity.getDeviceName())
+ .deviceDesc(entity.getDeviceDesc())
+ .deviceIndex(entity.getDeviceIndex())
+ .workspaceId(entity.getWorkspaceId())
+ .type(entity.getDeviceType())
+ .subType(entity.getSubType())
+ .domain(DeviceDomainEnum.getDesc(entity.getDomain()))
+ .iconUrl(IconUrlDTO.builder()
+ .normalUrl(entity.getUrlNormal())
+ .selectUrl(entity.getUrlSelect())
+ .build())
+ .boundStatus(entity.getBoundStatus())
+ .loginTime(entity.getLoginTime() != null ?
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getLoginTime()), ZoneId.systemDefault())
+ : null)
+ .boundTime(entity.getBoundTime() != null ?
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBoundTime()), ZoneId.systemDefault())
+ : null)
+ .nickname(entity.getNickname())
+ .firmwareVersion(entity.getFirmwareVersion())
+ .workspaceName(entity.getWorkspaceId() != null ?
+ workspaceService.getWorkspaceByWorkspaceId(entity.getWorkspaceId())
+ .map(WorkspaceDTO::getWorkspaceName).orElse("") : "")
+ .build();
}
+ @Override
+ public Boolean updateDevice(DeviceDTO deviceDTO) {
+ int update = mapper.update(this.deviceDTO2Entity(deviceDTO),
+ new LambdaUpdateWrapper<DeviceEntity>().eq(DeviceEntity::getDeviceSn, deviceDTO.getDeviceSn()));
+ return update > 0;
+ }
+
+ @Override
+ public Boolean bindDevice(DeviceDTO device) {
+ device.setBoundStatus(true);
+ device.setBoundTime(LocalDateTime.now());
+
+ boolean isUpd = this.saveDevice(this.deviceDTO2Entity(device)).isPresent();
+ if (DeviceDomainEnum.DOCK.getDesc().equals(device.getDomain())) {
+ return isUpd;
+ }
+ if (!isUpd) {
+ return false;
+ }
+
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn();
+ DeviceDTO redisDevice = (DeviceDTO)redisOps.get(key);
+ redisDevice.setWorkspaceId(device.getWorkspaceId());
+ redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
+
+ if (DeviceDomainEnum.GATEWAY.getDesc().equals(redisDevice.getDomain())) {
+ this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()),
+ device.getDeviceSn(), device.getDeviceSn());
+ }
+ if (DeviceDomainEnum.SUB_DEVICE.getDesc().equals(redisDevice.getDomain())) {
+ DeviceDTO subDevice = this.getDevicesByParams(DeviceQueryParam.builder()
+ .childSn(device.getChildDeviceSn())
+ .build()).get(0);
+ this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()),
+ device.getDeviceSn(), subDevice.getDeviceSn());
+ }
+ this.subscribeTopicOnline(device.getDeviceSn());
+
+ return true;
+ }
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_AIRPORT_BIND_STATUS, outputChannel = ChannelName.OUTBOUND)
+ public void bindStatus(CommonTopicReceiver receiver, MessageHeaders headers) {
+ List<Map<String, String>> data = ((Map<String, List<Map<String, String>>>) receiver.getData()).get(MapKeyConst.DEVICES);
+ String dockSn = data.get(0).get(MapKeyConst.SN);
+ String droneSn = data.size() > 1 ? data.get(1).get(MapKeyConst.SN) : "null";
+
+ Optional<DeviceDTO> dockOpt = this.getDeviceBySn(dockSn);
+ Optional<DeviceDTO> droneOpt = this.getDeviceBySn(droneSn);
+
+ List<BindStatusReceiver> bindStatusResult = new ArrayList<>();
+ bindStatusResult.add(dockOpt.isPresent() ? this.dto2BindStatus(dockOpt.get()) :
+ BindStatusReceiver.builder().sn(dockSn).isDeviceBindOrganization(false).build());
+ if (data.size() > 1) {
+ bindStatusResult.add(droneOpt.isPresent() ? this.dto2BindStatus(droneOpt.get()) :
+ BindStatusReceiver.builder().sn(droneSn).isDeviceBindOrganization(false).build());
+ }
+
+ messageSender.publish(headers.get(MqttHeaders.RECEIVED_TOPIC) + _REPLY_SUF,
+ CommonTopicResponse.builder()
+ .tid(receiver.getTid())
+ .bid(receiver.getBid())
+ .timestamp(System.currentTimeMillis())
+ .method(RequestsMethodEnum.AIRPORT_BIND_STATUS.getMethod())
+ .data(RequestsReply.success(Map.of(MapKeyConst.BIND_STATUS, bindStatusResult)))
+ .build());
+
+ }
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND)
+ public void bindDevice(CommonTopicReceiver receiver, MessageHeaders headers) {
+ Map<String, List<BindDeviceReceiver>> data = objectMapper.convertValue(receiver.getData(),
+ new TypeReference<Map<String, List<BindDeviceReceiver>>>() {});
+ List<BindDeviceReceiver> devices = data.get(MapKeyConst.BIND_DEVICES);
+ BindDeviceReceiver dock = null;
+ BindDeviceReceiver drone = null;
+ for (BindDeviceReceiver device : devices) {
+ int val = Integer.parseInt(device.getDeviceModelKey().split("-")[0]);
+ if (val == DeviceDomainEnum.DOCK.getVal()) {
+ dock = device;
+ }
+ if (val == DeviceDomainEnum.SUB_DEVICE.getVal()) {
+ drone = device;
+ }
+ }
+
+ assert dock != null;
+
+ Optional<DeviceEntity> dockEntityOpt = this.bindDevice2Entity(dock);
+ Optional<DeviceEntity> droneEntityOpt = this.bindDevice2Entity(drone);
+
+ List<ErrorInfoReply> bindResult = new ArrayList<>();
+
+ droneEntityOpt.ifPresent(droneEntity -> {
+ dockEntityOpt.get().setChildSn(droneEntity.getDeviceSn());
+ Optional<DeviceEntity> deviceEntityOpt = this.saveDevice(droneEntity);
+ bindResult.add(
+ deviceEntityOpt.isPresent() ?
+ ErrorInfoReply.success(droneEntity.getDeviceSn()) :
+ new ErrorInfoReply(droneEntity.getDeviceSn(),
+ CommonErrorEnum.DEVICE_BINDING_FAILED.getErrorCode())
+ );
+ });
+ Optional<DeviceEntity> dockOpt = this.saveDevice(dockEntityOpt.get());
+
+ bindResult.add(dockOpt.isPresent() ?
+ ErrorInfoReply.success(dock.getSn()) :
+ new ErrorInfoReply(dock.getSn(),
+ CommonErrorEnum.DEVICE_BINDING_FAILED.getErrorCode()));
+
+ String topic = headers.get(MqttHeaders.RECEIVED_TOPIC) + _REPLY_SUF;
+ messageSender.publish(topic,
+ CommonTopicResponse.builder()
+ .tid(receiver.getTid())
+ .bid(receiver.getBid())
+ .method(RequestsMethodEnum.AIRPORT_ORGANIZATION_BIND.getMethod())
+ .timestamp(System.currentTimeMillis())
+ .data(RequestsReply.success(Map.of(MapKeyConst.ERR_INFOS, bindResult)))
+ .build());
+
+ }
+
+ @Override
+ public PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page,
+ Long pageSize, String domain) {
+
+ Page<DeviceEntity> pagination = mapper.selectPage(new Page<>(page, pageSize),
+ new LambdaQueryWrapper<DeviceEntity>()
+ .eq(DeviceEntity::getDomain, DeviceDomainEnum.getVal(domain))
+ .eq(DeviceEntity::getWorkspaceId, workspaceId)
+ .eq(DeviceEntity::getBoundStatus, true));
+ List<DeviceDTO> devicesList = pagination.getRecords().stream().map(this::deviceEntityConvertToDTO)
+ .peek(device -> {
+ device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
+ if (StringUtils.hasText(device.getChildDeviceSn())) {
+ Optional<DeviceDTO> childOpt = this.getDeviceBySn(device.getChildDeviceSn());
+ childOpt.ifPresent(child -> {
+ child.setStatus(
+ redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn()));
+ child.setWorkspaceName(device.getWorkspaceName());
+ device.setChildren(child);
+ });
+ }
+ })
+ .collect(Collectors.toList());
+ return new PaginationData<DeviceDTO>(devicesList, new Pagination(pagination));
+ }
+
+ @Override
+ public void unbindDevice(String deviceSn) {
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
+ DeviceDTO redisDevice = (DeviceDTO) redisOps.get(key);
+ redisDevice.setWorkspaceId("");
+ redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
+
+ DeviceDTO device = DeviceDTO.builder()
+ .deviceSn(deviceSn)
+ .workspaceId("")
+ .userId("")
+ .boundStatus(false)
+ .build();
+ this.updateDevice(device);
+ }
+
+ @Override
+ public Optional<DeviceDTO> getDeviceBySn(String sn) {
+ List<DeviceDTO> devicesList = this.getDevicesByParams(DeviceQueryParam.builder().deviceSn(sn).build());
+ if (devicesList.isEmpty()) {
+ return Optional.empty();
+ }
+ DeviceDTO device = devicesList.get(0);
+ device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn));
+ return Optional.of(device);
+ }
+
+ @Override
+ public void updateFirmwareVersion(FirmwareVersionReceiver receiver) {
+ if (receiver.getDomain() == DeviceDomainEnum.SUB_DEVICE) {
+ this.updateDevice(DeviceDTO.builder()
+ .deviceSn(receiver.getSn())
+ .firmwareVersion(receiver.getFirmwareVersion())
+ .build());
+ return;
+ }
+ payloadService.updateFirmwareVersion(receiver);
+ }
+
+ /**
+ * Convert device data transfer object into database entity object.
+ * @param dto
+ * @return
+ */
+ private DeviceEntity deviceDTO2Entity(DeviceDTO dto) {
+ DeviceEntity.DeviceEntityBuilder builder = DeviceEntity.builder();
+ if (dto == null) {
+ return builder.build();
+ }
+
+ return builder.deviceSn(dto.getDeviceSn())
+ .userId(dto.getUserId())
+ .nickname(dto.getNickname())
+ .workspaceId(dto.getWorkspaceId())
+ .boundStatus(dto.getBoundStatus())
+ .loginTime(dto.getLoginTime() != null ?
+ dto.getLoginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
+ .boundTime(dto.getBoundTime() != null ?
+ dto.getBoundTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
+ .childSn(dto.getChildDeviceSn())
+ .domain(StringUtils.hasText(dto.getDomain()) ? DeviceDomainEnum.getVal(dto.getDomain()) : null)
+ .firmwareVersion(dto.getFirmwareVersion())
+ .build();
+ }
+
+ /**
+ * Convert device binding data object into database entity object.
+ * @param receiver
+ * @return
+ */
+ private Optional<DeviceEntity> bindDevice2Entity(BindDeviceReceiver receiver) {
+ if (receiver == null) {
+ return Optional.empty();
+ }
+ int[] droneKey = Arrays.stream(receiver.getDeviceModelKey().split("-")).mapToInt(Integer::parseInt).toArray();
+ Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService.getOneDictionaryInfoByTypeSubType(droneKey[1], droneKey[2]);
+ DeviceEntity.DeviceEntityBuilder builder = DeviceEntity.builder();
+
+ dictionaryOpt.ifPresent(entity ->
+ builder.deviceName(entity.getDeviceName())
+ .nickname(entity.getDeviceName())
+ .deviceDesc(entity.getDeviceDesc()));
+
+ Optional<WorkspaceDTO> workspace = workspaceService.getWorkspaceNameByBindCode(receiver.getDeviceBindingCode());
+
+ DeviceEntity entity = builder
+ .workspaceId(workspace.isPresent() ? workspace.get().getWorkspaceId() : receiver.getOrganizationId())
+ .domain(droneKey[0])
+ .deviceType(droneKey[1])
+ .subType(droneKey[2])
+ .deviceSn(receiver.getSn())
+ .boundStatus(true)
+ .loginTime(System.currentTimeMillis())
+ .boundTime(System.currentTimeMillis())
+ .urlSelect(IconUrlEnum.SELECT_EQUIPMENT.getUrl())
+ .urlNormal(IconUrlEnum.NORMAL_EQUIPMENT.getUrl())
+ .build();
+ if (StringUtils.hasText(receiver.getDeviceCallsign())) {
+ entity.setNickname(receiver.getDeviceCallsign());
+ }
+ return Optional.of(entity);
+ }
+
+ /**
+ * Convert device data transfer object into device binding status data object.
+ * @param device
+ * @return
+ */
+ private BindStatusReceiver dto2BindStatus(DeviceDTO device) {
+ if (device == null) {
+ return null;
+ }
+ return BindStatusReceiver.builder()
+ .sn(device.getDeviceSn())
+ .deviceCallsign(device.getNickname())
+ .isDeviceBindOrganization(device.getBoundStatus())
+ .organizationId(device.getWorkspaceId())
+ .organizationName(device.getWorkspaceName())
+ .build();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DockOSDServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DockOSDServiceImpl.java
new file mode 100644
index 0000000..4c34cd5
--- /dev/null
+++ b/src/main/java/com/dji/sample/manage/service/impl/DockOSDServiceImpl.java
@@ -0,0 +1,50 @@
+package com.dji.sample.manage.service.impl;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
+import com.dji.sample.component.websocket.model.BizCodeEnum;
+import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
+import com.dji.sample.manage.model.dto.DeviceDTO;
+import com.dji.sample.manage.model.dto.TelemetryDTO;
+import com.dji.sample.manage.model.enums.DeviceDomainEnum;
+import com.dji.sample.manage.model.receiver.OsdDockReceiver;
+import com.dji.sample.manage.model.receiver.OsdDockTransmissionReceiver;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+
+/**
+ * @author sean
+ * @version 1.0
+ * @date 2022/5/11
+ */
+@Service
+public class DockOSDServiceImpl extends AbstractTSAService {
+
+ public DockOSDServiceImpl() {
+ super(null);
+ }
+
+ @Override
+ public void pushTelemetryData(Collection<ConcurrentWebSocketSession> sessions,
+ CustomWebSocketMessage<TelemetryDTO> message, Object Object) {
+
+ }
+
+ @Override
+ public void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
+ Collection<ConcurrentWebSocketSession> webSessions,
+ CustomWebSocketMessage<TelemetryDTO> wsMessage) {
+
+ if (DeviceDomainEnum.DOCK.getDesc().equals(device.getDomain())) {
+ wsMessage.setBizCode(BizCodeEnum.DOCK_OSD.getCode());
+ OsdDockReceiver data = mapper.convertValue(receiver.getData(), OsdDockReceiver.class);
+ wsMessage.getData().setHost(data);
+ if (data.getSubDevice() == null) {
+ OsdDockTransmissionReceiver transmission = mapper.convertValue(receiver.getData(), OsdDockTransmissionReceiver.class);
+ wsMessage.getData().setHost(transmission);
+ }
+ sendMessageService.sendBatch(webSessions, wsMessage);
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java
index a69b9fe..397c80e 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java
@@ -1,23 +1,18 @@
package com.dji.sample.manage.service.impl;
-import com.dji.sample.component.mqtt.model.TopicStateReceiver;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
-import com.dji.sample.manage.model.DeviceStatusManager;
+import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.TelemetryDTO;
import com.dji.sample.manage.model.dto.TelemetryDeviceDTO;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.model.receiver.OsdGatewayReceiver;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
-import java.time.LocalDateTime;
import java.util.Collection;
/**
@@ -49,26 +44,21 @@
}
@Override
- protected void handleOSD(TopicStateReceiver receiver, String sn, String workspaceId, JsonNode hostNode,
- Collection<ConcurrentWebSocketSession> webSessions, CustomWebSocketMessage wsMessage) throws JsonProcessingException {
- if (sn.equals(receiver.getGateway())) {
- // Real-time update of device status in memory
- DeviceStatusManager.STATUS_MANAGER.put(DeviceDomainEnum.GATEWAY.getVal() + "/" + sn,
- LocalDateTime.now());
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ public void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
+ Collection<ConcurrentWebSocketSession> webSessions,
+ CustomWebSocketMessage<TelemetryDTO> wsMessage) {
+ if (DeviceDomainEnum.GATEWAY.getDesc().equals(device.getDomain())) {
wsMessage.setBizCode(BizCodeEnum.GATEWAY_OSD.getCode());
- OsdGatewayReceiver data = mapper.treeToValue(hostNode, OsdGatewayReceiver.class);
- wsMessage.setData(data);
+ OsdGatewayReceiver data = mapper.convertValue(receiver.getData(), OsdGatewayReceiver.class);
+ wsMessage.getData().setHost(data);
this.sendMessageService.sendBatch(webSessions, wsMessage);
- this.pushTelemetryData(workspaceId, data, sn);
+ this.pushTelemetryData(device.getWorkspaceId(), data, device.getDeviceSn());
return;
}
- tsaService.handleOSD(receiver, sn, workspaceId, hostNode, webSessions, wsMessage);
+ tsaService.handleOSD(receiver, device, webSessions, wsMessage);
}
}
diff --git a/src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java
index 371ad97..9ef86b1 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java
@@ -2,18 +2,19 @@
import com.dji.sample.common.error.LiveErrorEnum;
import com.dji.sample.common.model.ResponseResult;
-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.model.ServicesMethodEnum;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
-import com.dji.sample.manage.model.Chan;
+import com.dji.sample.component.redis.RedisConst;
+import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.*;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
-import com.dji.sample.manage.model.enums.LiveMethodEnum;
import com.dji.sample.manage.model.enums.LiveUrlTypeEnum;
import com.dji.sample.manage.model.enums.LiveVideoQualityEnum;
import com.dji.sample.manage.model.param.DeviceQueryParam;
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.ICapacityCameraService;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.manage.service.ILiveStreamService;
@@ -24,9 +25,12 @@
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
-import java.util.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import static com.dji.sample.component.mqtt.model.TopicConst.*;
@@ -51,32 +55,37 @@
@Autowired
private IMessageSenderService messageSender;
+ @Autowired
+ private RedisOpsUtils redisOps;
+
@Override
public List<CapacityDeviceDTO> getLiveCapacity(String workspaceId) {
- // Query all drone data in this workspace.
+ // Query all devices in this workspace.
List<DeviceDTO> devicesList = deviceService.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
- .domain(DeviceDomainEnum.SUB_DEVICE.getVal())
+ .domains(List.of(DeviceDomainEnum.SUB_DEVICE.getVal(), DeviceDomainEnum.DOCK.getVal()))
.build());
- List<CapacityDeviceDTO> capacityDevicesList = new ArrayList<>();
// Query the live capability of each drone.
- devicesList.forEach(device -> capacityDevicesList.add(CapacityDeviceDTO.builder()
- .name(device.getDeviceName())
- .sn(device.getDeviceSn())
- .camerasList(capacityCameraService.getCapacityCameraByDeviceSn(device.getDeviceSn()))
- .build()));
-
- return capacityDevicesList;
+ return devicesList.stream()
+ .filter(device -> redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
+ .map(device -> CapacityDeviceDTO.builder()
+ .name(device.getDeviceName())
+ .sn(device.getDeviceSn())
+ .camerasList(capacityCameraService.getCapacityCameraByDeviceSn(device.getDeviceSn()))
+ .build())
+ .collect(Collectors.toList());
}
@Override
- public Boolean saveLiveCapacity(CapacityDeviceReceiver capacityDeviceReceiver) {
- return capacityCameraService.saveCapacityCameraReceiverList(
- capacityDeviceReceiver.getCameraList(),
- capacityDeviceReceiver.getSn());
+ public void saveLiveCapacity(LiveCapacityReceiver liveCapacityReceiver) {
+ for (CapacityDeviceReceiver capacityDeviceReceiver : liveCapacityReceiver.getDeviceList()) {
+ capacityCameraService.saveCapacityCameraReceiverList(
+ capacityDeviceReceiver.getCameraList(),
+ capacityDeviceReceiver.getSn());
+ }
}
@Override
@@ -87,11 +96,11 @@
return responseResult;
}
- List<DeviceDTO> data = (List<DeviceDTO>)responseResult.getData();
+ DeviceDTO data = (DeviceDTO)responseResult.getData();
// target topic
String respTopic = THING_MODEL_PRE + PRODUCT +
- data.get(0).getDeviceSn() + SERVICES_SUF;
- Optional<ServiceReplyReceiver> receiveReplyOpt = this.publishLiveStart(respTopic, liveParam);
+ data.getDeviceSn() + SERVICES_SUF;
+ Optional<ServiceReply> receiveReplyOpt = this.publishLiveStart(respTopic, liveParam);
if (receiveReplyOpt.isEmpty()) {
return ResponseResult.error(LiveErrorEnum.NO_REPLY);
@@ -119,7 +128,7 @@
.toString());
break;
case RTSP:
- String url = receiveReplyOpt.get().getInfo();
+ String url = receiveReplyOpt.get().getInfo().toString();
this.resolveUrlUser(url, live);
break;
case UNKNOWN:
@@ -131,14 +140,14 @@
@Override
public ResponseResult liveStop(String videoId) {
- ResponseResult<List<DeviceDTO>> responseResult = this.checkBeforeLive(videoId);
+ ResponseResult<DeviceDTO> responseResult = this.checkBeforeLive(videoId);
if (responseResult.getCode() != 0) {
return responseResult;
}
- String respTopic = THING_MODEL_PRE + PRODUCT + responseResult.getData().get(0).getDeviceSn() + SERVICES_SUF;
+ String respTopic = THING_MODEL_PRE + PRODUCT + responseResult.getData().getDeviceSn() + SERVICES_SUF;
- Optional<ServiceReplyReceiver> receiveReplyOpt = this.publishLiveStop(respTopic, videoId);
+ Optional<ServiceReply> receiveReplyOpt = this.publishLiveStop(respTopic, videoId);
if (receiveReplyOpt.isEmpty()) {
return ResponseResult.error(LiveErrorEnum.NO_REPLY);
}
@@ -156,15 +165,15 @@
return ResponseResult.error(LiveErrorEnum.ERROR_PARAMETERS);
}
- ResponseResult<List<DeviceDTO>> responseResult = this.checkBeforeLive(liveParam.getVideoId());
+ ResponseResult<DeviceDTO> responseResult = this.checkBeforeLive(liveParam.getVideoId());
if (responseResult.getCode() != 0) {
return responseResult;
}
- String respTopic = THING_MODEL_PRE + PRODUCT + responseResult.getData().get(0).getDeviceSn() + SERVICES_SUF;
+ String respTopic = THING_MODEL_PRE + PRODUCT + responseResult.getData().getDeviceSn() + SERVICES_SUF;
- Optional<ServiceReplyReceiver> receiveReplyOpt = this.publishLiveSetQuality(respTopic, liveParam);
+ Optional<ServiceReply> receiveReplyOpt = this.publishLiveSetQuality(respTopic, liveParam);
if (receiveReplyOpt.isEmpty()) {
return ResponseResult.error(LiveErrorEnum.NO_REPLY);
}
@@ -180,22 +189,31 @@
* @param videoId
* @return
*/
- private ResponseResult checkBeforeLive(String videoId) {
+ private ResponseResult<DeviceDTO> checkBeforeLive(String videoId) {
String[] videoIdArr = videoId.split("/");
// drone sn / enumeration value of the location where the payload is mounted / payload lens
if (videoIdArr.length != 3) {
return ResponseResult.error(LiveErrorEnum.ERROR_PARAMETERS);
}
+ Optional<DeviceDTO> deviceOpt = deviceService.getDeviceBySn(videoIdArr[0]);
+ // Check if the gateway device connected to this drone exists
+ if (deviceOpt.isEmpty()) {
+ return ResponseResult.error(LiveErrorEnum.NO_AIRCRAFT);
+ }
+
+ if (deviceOpt.get().getDomain().equals(DeviceDomainEnum.DOCK.getDesc())) {
+ return ResponseResult.success(deviceOpt.get());
+ }
List<DeviceDTO> gatewayList = deviceService.getDevicesByParams(
DeviceQueryParam.builder()
.childSn(videoIdArr[0])
.build());
- // Check if the gateway device connected to this drone exists
if (gatewayList.isEmpty()) {
return ResponseResult.error(LiveErrorEnum.NO_FLIGHT_CONTROL);
}
- return ResponseResult.success(gatewayList);
+
+ return ResponseResult.success(gatewayList.get(0));
}
/**
@@ -250,14 +268,14 @@
* @param liveParam
* @return
*/
- private Optional<ServiceReplyReceiver> publishLiveStart(String topic, LiveTypeDTO liveParam) {
+ private Optional<ServiceReply> publishLiveStart(String topic, LiveTypeDTO liveParam) {
CommonTopicResponse<LiveTypeDTO> response = new CommonTopicResponse<>();
response.setTid(UUID.randomUUID().toString());
response.setBid(UUID.randomUUID().toString());
response.setData(liveParam);
- response.setMethod(LiveMethodEnum.LIVE_START_PUSH.getMethod());
+ response.setMethod(ServicesMethodEnum.LIVE_START_PUSH.getMethod());
- return this.publishLive(topic, response);
+ return messageSender.publishWithReply(topic, response);
}
/**
@@ -266,17 +284,17 @@
* @param liveParam
* @return
*/
- private Optional<ServiceReplyReceiver> publishLiveSetQuality(String respTopic, LiveTypeDTO liveParam) {
+ private Optional<ServiceReply> publishLiveSetQuality(String respTopic, LiveTypeDTO liveParam) {
Map<String, Object> data = new ConcurrentHashMap<>(Map.of(
"video_id", liveParam.getVideoId(),
"video_quality", liveParam.getVideoQuality()));
CommonTopicResponse<Map<String, Object>> response = new CommonTopicResponse<>();
response.setTid(UUID.randomUUID().toString());
response.setBid(UUID.randomUUID().toString());
- response.setMethod(LiveMethodEnum.LIVE_SET_QUALITY.getMethod());
+ response.setMethod(ServicesMethodEnum.LIVE_SET_QUALITY.getMethod());
response.setData(data);
- return this.publishLive(respTopic, response);
+ return messageSender.publishWithReply(respTopic, response);
}
/**
@@ -285,42 +303,15 @@
* @param videoId
* @return
*/
- private Optional<ServiceReplyReceiver> publishLiveStop(String topic, String videoId) {
+ private Optional<ServiceReply> publishLiveStop(String topic, String videoId) {
Map<String, String> data = new ConcurrentHashMap<>(Map.of("video_id", videoId));
CommonTopicResponse<Map<String, String>> response = new CommonTopicResponse<>();
response.setTid(UUID.randomUUID().toString());
response.setBid(UUID.randomUUID().toString());
response.setData(data);
- response.setMethod(LiveMethodEnum.LIVE_STOP_PUSH.getMethod());
+ response.setMethod(ServicesMethodEnum.LIVE_STOP_PUSH.getMethod());
- return this.publishLive(topic, 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
- */
- private Optional<ServiceReplyReceiver> publishLive(String topic, CommonTopicResponse response) {
- AtomicInteger time = new AtomicInteger(0);
- // Retry three times
- while (time.getAndIncrement() < 3) {
- messageSender.publish(topic, response);
-
- Chan<CommonTopicReceiver<ServiceReplyReceiver>> chan = Chan.getInstance();
- // If the message is not received in 0.5 seconds then resend it again.
- CommonTopicReceiver<ServiceReplyReceiver> 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();
+ return messageSender.publishWithReply(topic, response);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/manage/service/impl/TopologyServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/TopologyServiceImpl.java
index aefc059..64d7d07 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/TopologyServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/TopologyServiceImpl.java
@@ -31,7 +31,7 @@
List<DeviceDTO> gatewayList = deviceService.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
- .domain(DeviceDomainEnum.GATEWAY.getVal())
+ .domains(List.of(DeviceDomainEnum.GATEWAY.getVal()))
.build());
List<TopologyDTO> topologyList = new ArrayList<>();
diff --git a/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
index c3c9a1b..8f3df63 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
@@ -1,15 +1,22 @@
package com.dji.sample.manage.service.impl;
import com.auth0.jwt.JWT;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.common.model.CustomClaim;
+import com.dji.sample.common.model.Pagination;
+import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.common.util.JwtUtil;
import com.dji.sample.component.mqtt.config.MqttConfiguration;
import com.dji.sample.manage.dao.IUserMapper;
import com.dji.sample.manage.model.dto.UserDTO;
+import com.dji.sample.manage.model.dto.UserListDTO;
import com.dji.sample.manage.model.dto.WorkspaceDTO;
import com.dji.sample.manage.model.entity.UserEntity;
+import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.service.IUserService;
import com.dji.sample.manage.service.IWorkspaceService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,7 +25,12 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.List;
import java.util.Optional;
+import java.util.stream.Collectors;
@Service
@Transactional
@@ -51,7 +63,7 @@
}
@Override
- public ResponseResult userLogin(String username, String password) {
+ public ResponseResult userLogin(String username, String password, Integer flag) {
// check user
UserEntity userEntity = this.getUserByUsername(username);
if (userEntity == null) {
@@ -60,6 +72,9 @@
.message("invalid username")
.build();
}
+ if (flag.intValue() != userEntity.getUserType().intValue()) {
+ return ResponseResult.error("The account type does not match.");
+ }
if (!password.equals(userEntity.getPassword())) {
return ResponseResult.builder()
.code(HttpStatus.UNAUTHORIZED.value())
@@ -67,7 +82,7 @@
.build();
}
- Optional<WorkspaceDTO> workspaceOpt = workspaceService.getWorkspaceById(userEntity.getWorkspaceId());
+ Optional<WorkspaceDTO> workspaceOpt = workspaceService.getWorkspaceByWorkspaceId(userEntity.getWorkspaceId());
if (workspaceOpt.isEmpty()) {
return ResponseResult.builder()
.code(HttpStatus.UNAUTHORIZED.value())
@@ -109,6 +124,60 @@
return Optional.of(user);
}
+ @Override
+ public PaginationData<UserListDTO> getUsersByWorkspaceId(long page, long pageSize, String workspaceId) {
+ Page<UserEntity> userEntityPage = mapper.selectPage(
+ new Page<>(page, pageSize),
+ new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getWorkspaceId, workspaceId));
+
+ List<UserListDTO> usersList = userEntityPage.getRecords()
+ .stream()
+ .map(this::entity2UserListDTO)
+ .collect(Collectors.toList());
+ return new PaginationData<>(usersList, new Pagination(userEntityPage));
+ }
+
+ @Override
+ public Boolean updateUser(String workspaceId, String userId, UserListDTO user) {
+ UserEntity userEntity = mapper.selectOne(
+ new LambdaQueryWrapper<UserEntity>()
+ .eq(UserEntity::getUserId, userId)
+ .eq(UserEntity::getWorkspaceId, workspaceId));
+ if (userEntity == null) {
+ return false;
+ }
+ userEntity.setMqttUsername(user.getMqttUsername());
+ userEntity.setMqttPassword(user.getMqttPassword());
+ userEntity.setUpdateTime(System.currentTimeMillis());
+ int id = mapper.update(userEntity, new LambdaUpdateWrapper<UserEntity>()
+ .eq(UserEntity::getUserId, userId)
+ .eq(UserEntity::getWorkspaceId, workspaceId));
+
+ return id > 0;
+ }
+
+ /**
+ * Convert database entity objects into user data transfer object.
+ * @param entity
+ * @return
+ */
+ private UserListDTO entity2UserListDTO(UserEntity entity) {
+ UserListDTO.UserListDTOBuilder builder = UserListDTO.builder();
+ if (entity != null) {
+ builder.userId(entity.getUserId())
+ .username(entity.getUsername())
+ .mqttUsername(entity.getMqttUsername())
+ .mqttPassword(entity.getMqttPassword())
+ .userType(UserTypeEnum.find(entity.getUserType()).getDesc())
+ .createTime(LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()));
+ Optional<WorkspaceDTO> workspaceOpt = workspaceService.getWorkspaceByWorkspaceId(entity.getWorkspaceId());
+ workspaceOpt.ifPresent(workspace -> builder.workspaceName(workspace.getWorkspaceName()));
+ }
+
+ return builder.build();
+ }
+
/**
* Query a user by username.
* @param username
@@ -119,6 +188,11 @@
.eq("username", username));
}
+ /**
+ * Convert database entity objects into user data transfer object.
+ * @param entity
+ * @return
+ */
private UserDTO entityConvertToDTO(UserEntity entity) {
if (entity == null) {
return new UserDTO();
diff --git a/src/main/java/com/dji/sample/manage/service/impl/WorkspaceServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/WorkspaceServiceImpl.java
index d6ed3ab..b90d262 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/WorkspaceServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/WorkspaceServiceImpl.java
@@ -1,14 +1,24 @@
package com.dji.sample.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.dji.sample.common.error.CommonErrorEnum;
+import com.dji.sample.component.mqtt.model.*;
+import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.manage.dao.IWorkspaceMapper;
import com.dji.sample.manage.model.dto.WorkspaceDTO;
import com.dji.sample.manage.model.entity.WorkspaceEntity;
+import com.dji.sample.manage.model.receiver.OrganizationGetReceiver;
import com.dji.sample.manage.service.IWorkspaceService;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import java.util.Map;
import java.util.Optional;
@Service
@@ -18,10 +28,11 @@
@Autowired
private IWorkspaceMapper mapper;
- @Override
- public Optional<WorkspaceDTO> getWorkspaceById(int id) {
- return Optional.ofNullable(entityConvertToDto(mapper.selectById(id)));
- }
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Autowired
+ private IMessageSenderService messageSenderService;
@Override
public Optional<WorkspaceDTO> getWorkspaceByWorkspaceId(String workspaceId) {
@@ -31,22 +42,57 @@
.eq(WorkspaceEntity::getWorkspaceId, workspaceId))));
}
+ @Override
+ public Optional<WorkspaceDTO> getWorkspaceNameByBindCode(String bindCode) {
+ return Optional.ofNullable(entityConvertToDto(
+ mapper.selectOne(new LambdaQueryWrapper<WorkspaceEntity>().eq(WorkspaceEntity::getBindCode, bindCode))));
+ }
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_GET, outputChannel = ChannelName.OUTBOUND)
+ public void replyOrganizationGet(CommonTopicReceiver receiver, MessageHeaders headers) {
+ OrganizationGetReceiver organizationGet = objectMapper.convertValue(receiver.getData(), OrganizationGetReceiver.class);
+ CommonTopicResponse.CommonTopicResponseBuilder<RequestsReply> builder = CommonTopicResponse.<RequestsReply>builder()
+ .tid(receiver.getTid())
+ .bid(receiver.getBid())
+ .method(RequestsMethodEnum.AIRPORT_ORGANIZATION_GET.getMethod())
+ .timestamp(System.currentTimeMillis());
+
+ String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString() + TopicConst._REPLY_SUF;
+
+ if (!StringUtils.hasText(organizationGet.getDeviceBindingCode())) {
+ builder.data(RequestsReply.error(CommonErrorEnum.ILLEGAL_ARGUMENT));
+ messageSenderService.publish(topic, builder.build());
+ return;
+ }
+
+ Optional<WorkspaceDTO> workspace = this.getWorkspaceNameByBindCode(organizationGet.getDeviceBindingCode());
+ if (workspace.isEmpty()) {
+ builder.data(RequestsReply.error(CommonErrorEnum.GET_ORGANIZATION_FAILED));
+ messageSenderService.publish(topic, builder.build());
+ return;
+ }
+
+ builder.data(RequestsReply.success(Map.of(MapKeyConst.ORGANIZATION_NAME, workspace.get().getWorkspaceName())));
+ messageSenderService.publish(topic, builder.build());
+ }
+
/**
* Convert database entity objects into workspace data transfer object.
* @param entity
* @return
*/
private WorkspaceDTO entityConvertToDto(WorkspaceEntity entity) {
- WorkspaceDTO.WorkspaceDTOBuilder builder = WorkspaceDTO.builder();
if (entity == null) {
- return builder.build();
+ return null;
}
- return builder
+ return WorkspaceDTO.builder()
.id(entity.getId())
.workspaceId(entity.getWorkspaceId())
.platformName(entity.getPlatformName())
.workspaceDesc(entity.getWorkspaceDesc())
.workspaceName(entity.getWorkspaceName())
+ .bindCode(entity.getBindCode())
.build();
}
}
diff --git a/src/main/java/com/dji/sample/map/controller/WorkspaceElementController.java b/src/main/java/com/dji/sample/map/controller/WorkspaceElementController.java
index 1ad52b8..8afaf16 100644
--- a/src/main/java/com/dji/sample/map/controller/WorkspaceElementController.java
+++ b/src/main/java/com/dji/sample/map/controller/WorkspaceElementController.java
@@ -4,8 +4,8 @@
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
-import com.dji.sample.component.websocket.model.WebSocketManager;
import com.dji.sample.component.websocket.service.ISendMessageService;
+import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.map.model.dto.*;
import com.dji.sample.map.service.IWorkspaceElementService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +33,9 @@
@Autowired
private ISendMessageService sendMessageService;
+
+ @Autowired
+ private IWebSocketManageService webSocketManageService;
/**
* In the first connection, pilot will send out this http request to obtain the group element list.
@@ -78,7 +81,7 @@
elementService.getElementByElementId(elementCreate.getId())
.ifPresent(groupElement ->
sendMessageService.sendBatch(
- WebSocketManager.getValueWithWorkspace(workspaceId),
+ webSocketManageService.getValueWithWorkspace(workspaceId),
CustomWebSocketMessage.<GroupElementDTO>builder()
.timestamp(System.currentTimeMillis())
.bizCode(BizCodeEnum.MAP_ELEMENT_CREATE.getCode())
@@ -114,7 +117,7 @@
elementService.getElementByElementId(elementId)
.ifPresent(groupElement ->
sendMessageService.sendBatch(
- WebSocketManager.getValueWithWorkspace(workspaceId),
+ webSocketManageService.getValueWithWorkspace(workspaceId),
CustomWebSocketMessage.<GroupElementDTO>builder()
.timestamp(System.currentTimeMillis())
.bizCode(BizCodeEnum.MAP_ELEMENT_UPDATE.getCode())
@@ -142,7 +145,7 @@
if (ResponseResult.CODE_SUCCESS == response.getCode()) {
elementOpt.ifPresent(element ->
sendMessageService.sendBatch(
- WebSocketManager.getValueWithWorkspace(workspaceId),
+ webSocketManageService.getValueWithWorkspace(workspaceId),
CustomWebSocketMessage.<WebSocketElementDelDTO>builder()
.timestamp(System.currentTimeMillis())
.bizCode(BizCodeEnum.MAP_ELEMENT_DELETE.getCode())
@@ -171,7 +174,7 @@
if (ResponseResult.CODE_SUCCESS == response.getCode()) {
sendMessageService.sendBatch(
- WebSocketManager.getValueWithWorkspace(workspaceId),
+ webSocketManageService.getValueWithWorkspace(workspaceId),
CustomWebSocketMessage.builder()
.timestamp(System.currentTimeMillis())
.bizCode(BizCodeEnum.MAP_GROUP_REFRESH.getCode())
diff --git a/src/main/java/com/dji/sample/media/controller/FileController.java b/src/main/java/com/dji/sample/media/controller/FileController.java
index 25a6015..8fa8451 100644
--- a/src/main/java/com/dji/sample/media/controller/FileController.java
+++ b/src/main/java/com/dji/sample/media/controller/FileController.java
@@ -1,15 +1,15 @@
package com.dji.sample.media.controller;
+import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.media.model.MediaFileDTO;
import com.dji.sample.media.service.IFileService;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
-import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URL;
/**
* @author sean
@@ -29,8 +29,29 @@
* @return
*/
@GetMapping("/{workspace_id}/files")
- public ResponseResult<List<MediaFileDTO>> getFilesList(@PathVariable(name = "workspace_id") String workspaceId) {
- List<MediaFileDTO> filesList = fileService.getAllFilesByWorkspaceId(workspaceId);
+ public ResponseResult<PaginationData<MediaFileDTO>> getFilesList(@RequestParam(defaultValue = "1") Long page,
+ @RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
+ @PathVariable(name = "workspace_id") String workspaceId) {
+ PaginationData<MediaFileDTO> filesList = fileService.getJobsPaginationByWorkspaceId(workspaceId, page, pageSize);
return ResponseResult.success(filesList);
}
+
+ /**
+ * Query the download address of the file according to the media file fingerprint,
+ * and redirect to this address directly for download.
+ * @param workspaceId
+ * @param fingerprint
+ * @param response
+ */
+ @GetMapping("/{workspace_id}/file/{fingerprint}/url")
+ public void getFileUrl(@PathVariable(name = "workspace_id") String workspaceId,
+ @PathVariable String fingerprint, HttpServletResponse response) {
+
+ try {
+ URL url = fileService.getObjectUrl(workspaceId, fingerprint);
+ response.sendRedirect(url.toString());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
diff --git a/src/main/java/com/dji/sample/media/controller/MediaController.java b/src/main/java/com/dji/sample/media/controller/MediaController.java
index 0e73743..b02f8ad 100644
--- a/src/main/java/com/dji/sample/media/controller/MediaController.java
+++ b/src/main/java/com/dji/sample/media/controller/MediaController.java
@@ -1,8 +1,10 @@
package com.dji.sample.media.controller;
import com.dji.sample.common.model.ResponseResult;
+import com.dji.sample.component.mqtt.model.MapKeyConst;
import com.dji.sample.media.model.FileUploadDTO;
import com.dji.sample.media.service.IMediaService;
+import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -10,7 +12,6 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
/**
* @author sean
@@ -36,7 +37,7 @@
boolean isExist = mediaService.fastUpload(workspaceId, file.getFingerprint());
- return isExist ? ResponseResult.success() : ResponseResult.error(file.getFingerprint() + "already exists.");
+ return isExist ? ResponseResult.success() : ResponseResult.error(file.getFingerprint() + "don't exist.");
}
/**
@@ -56,18 +57,17 @@
/**
* Query the files that already exist in this workspace based on the workspace id and the collection of tiny fingerprints.
* @param workspaceId
- * @param tinyFingerprints
+ * @param tinyFingerprints There is only one tiny_fingerprint parameter in the body.
+ * But it is not recommended to use Map to receive the parameter.
* @return
*/
- @GetMapping("/{workspace_id}/files/tiny-fingerprints")
- public ResponseResult<Map<String, List<String>>> uploadCallback(@PathVariable(name = "workspace_id") String workspaceId,
- @RequestParam(value = "tiny_fingerprint") List<String> tinyFingerprints) {
- List<String> tinyFingerprintList = mediaService.getAllTinyFingerprintsByWorkspaceId(workspaceId);
- List<String> existingList = tinyFingerprints
- .stream()
- .filter(tinyFingerprintList::contains)
- .collect(Collectors.toList());
- return ResponseResult.success(new ConcurrentHashMap<>(Map.of("tiny_fingerprints", existingList)));
+ @PostMapping("/{workspace_id}/files/tiny-fingerprints")
+ public ResponseResult<Map<String, List<String>>> uploadCallback(
+ @PathVariable(name = "workspace_id") String workspaceId,
+ @RequestBody Map<String, List<String>> tinyFingerprints) throws JsonProcessingException {
+
+ List<String> existingList = mediaService.getExistTinyFingerprints(workspaceId, tinyFingerprints.get(MapKeyConst.TINY_FINGERPRINTS));
+ return ResponseResult.success(new ConcurrentHashMap<>(Map.of(MapKeyConst.TINY_FINGERPRINTS, existingList)));
}
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/media/model/CredentialsDTO.java b/src/main/java/com/dji/sample/media/model/CredentialsDTO.java
index 2662254..be146bd 100644
--- a/src/main/java/com/dji/sample/media/model/CredentialsDTO.java
+++ b/src/main/java/com/dji/sample/media/model/CredentialsDTO.java
@@ -2,7 +2,9 @@
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import io.minio.credentials.Credentials;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
/**
@@ -11,6 +13,8 @@
* @date 2021/12/7
*/
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class CredentialsDTO {
private String accessKeyId;
@@ -35,6 +39,10 @@
this.expire = Math.toIntExact(expire);
}
- public CredentialsDTO() {
+ public CredentialsDTO(com.amazonaws.services.securitytoken.model.Credentials credentials) {
+ this.accessKeyId = credentials.getAccessKeyId();
+ this.accessKeySecret = credentials.getSecretAccessKey();
+ this.securityToken = credentials.getSessionToken();
+ this.expire = Math.toIntExact((credentials.getExpiration().getTime() - System.currentTimeMillis()) / 1000);
}
}
diff --git a/src/main/java/com/dji/sample/media/model/FileExtensionDTO.java b/src/main/java/com/dji/sample/media/model/FileExtensionDTO.java
index 5a33bc6..c1f96b7 100644
--- a/src/main/java/com/dji/sample/media/model/FileExtensionDTO.java
+++ b/src/main/java/com/dji/sample/media/model/FileExtensionDTO.java
@@ -23,4 +23,6 @@
private String sn;
+ private String flightId;
+
}
diff --git a/src/main/java/com/dji/sample/media/model/FileUploadCallback.java b/src/main/java/com/dji/sample/media/model/FileUploadCallback.java
new file mode 100644
index 0000000..62bbcc7
--- /dev/null
+++ b/src/main/java/com/dji/sample/media/model/FileUploadCallback.java
@@ -0,0 +1,18 @@
+package com.dji.sample.media.model;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+@Data
+public class FileUploadCallback {
+
+ private Integer result;
+
+ private Integer progress;
+
+ private FileUploadDTO file;
+}
diff --git a/src/main/java/com/dji/sample/media/model/MediaFileDTO.java b/src/main/java/com/dji/sample/media/model/MediaFileDTO.java
index b42acf8..8b34e17 100644
--- a/src/main/java/com/dji/sample/media/model/MediaFileDTO.java
+++ b/src/main/java/com/dji/sample/media/model/MediaFileDTO.java
@@ -5,6 +5,8 @@
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.time.LocalDateTime;
+
/**
* @author sean
* @version 0.2
@@ -31,4 +33,8 @@
private String payload;
private String tinnyFingerprint;
+
+ private String fingerprint;
+
+ private LocalDateTime createTime;
}
diff --git a/src/main/java/com/dji/sample/media/model/MediaFileEntity.java b/src/main/java/com/dji/sample/media/model/MediaFileEntity.java
index a3dd2aa..ab17263 100644
--- a/src/main/java/com/dji/sample/media/model/MediaFileEntity.java
+++ b/src/main/java/com/dji/sample/media/model/MediaFileEntity.java
@@ -53,6 +53,9 @@
@TableField("payload")
private String payload;
+ @TableField("job_id")
+ private String jobId;
+
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Long createTime;
diff --git a/src/main/java/com/dji/sample/media/service/IFileService.java b/src/main/java/com/dji/sample/media/service/IFileService.java
index 9347ccf..804f419 100644
--- a/src/main/java/com/dji/sample/media/service/IFileService.java
+++ b/src/main/java/com/dji/sample/media/service/IFileService.java
@@ -1,8 +1,10 @@
package com.dji.sample.media.service;
+import com.dji.sample.common.model.PaginationData;
import com.dji.sample.media.model.FileUploadDTO;
import com.dji.sample.media.model.MediaFileDTO;
+import java.net.URL;
import java.util.List;
/**
@@ -34,4 +36,21 @@
* @return
*/
List<MediaFileDTO> getAllFilesByWorkspaceId(String workspaceId);
+
+ /**
+ * Paginate through all media files in this workspace.
+ * @param workspaceId
+ * @param page
+ * @param pageSize
+ * @return
+ */
+ PaginationData<MediaFileDTO> getJobsPaginationByWorkspaceId(String workspaceId, long page, long pageSize);
+
+ /**
+ * Get the download address of the file.
+ * @param workspaceId
+ * @param fingerprint
+ * @return
+ */
+ URL getObjectUrl(String workspaceId, String fingerprint);
}
diff --git a/src/main/java/com/dji/sample/media/service/IMediaService.java b/src/main/java/com/dji/sample/media/service/IMediaService.java
index f8fc42d..75085df 100644
--- a/src/main/java/com/dji/sample/media/service/IMediaService.java
+++ b/src/main/java/com/dji/sample/media/service/IMediaService.java
@@ -1,5 +1,6 @@
package com.dji.sample.media.service;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.media.model.FileUploadDTO;
import java.util.List;
@@ -33,4 +34,19 @@
* @return
*/
List<String> getAllTinyFingerprintsByWorkspaceId(String workspaceId);
+
+ /**
+ * Query the fingerprints that already exist in it based on the incoming tiny fingerprints data.
+ * @param workspaceId
+ * @param tinyFingerprints
+ * @return
+ */
+ List<String> getExistTinyFingerprints(String workspaceId, List<String> tinyFingerprints);
+
+ /**
+ * Handle media files messages reported by dock.
+ * @param receiver
+ * @return
+ */
+ void handleFileUploadCallBack(CommonTopicReceiver receiver);
}
diff --git a/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java b/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
index 744d9d7..2037099 100644
--- a/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
+++ b/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
@@ -1,6 +1,11 @@
package com.dji.sample.media.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.dji.sample.common.model.Pagination;
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.service.impl.OssServiceContext;
import com.dji.sample.manage.model.dto.DeviceDictionaryDTO;
import com.dji.sample.manage.service.IDeviceDictionaryService;
import com.dji.sample.media.dao.IFileMapper;
@@ -12,6 +17,10 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.net.URL;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@@ -26,19 +35,28 @@
@Transactional
public class FileServiceImpl implements IFileService {
-
@Autowired
private IFileMapper mapper;
@Autowired
private IDeviceDictionaryService deviceDictionaryService;
- @Override
- public Boolean checkExist(String workspaceId, String fingerprint) {
+ @Autowired
+ private OssServiceContext ossService;
+
+ @Autowired
+ private OssConfiguration configuration;
+
+ private Optional<MediaFileEntity> getMediaByFingerprint(String workspaceId, String fingerprint) {
MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
.eq(MediaFileEntity::getWorkspaceId, workspaceId)
.eq(MediaFileEntity::getFingerprint, fingerprint));
- return fileEntity != null;
+ return Optional.ofNullable(fileEntity);
+ }
+
+ @Override
+ public Boolean checkExist(String workspaceId, String fingerprint) {
+ return this.getMediaByFingerprint(workspaceId, fingerprint).isPresent();
}
@Override
@@ -57,6 +75,30 @@
.collect(Collectors.toList());
}
+ @Override
+ public PaginationData<MediaFileDTO> getJobsPaginationByWorkspaceId(String workspaceId, long page, long pageSize) {
+ Page<MediaFileEntity> pageData = mapper.selectPage(
+ new Page<MediaFileEntity>(page, pageSize),
+ new LambdaQueryWrapper<MediaFileEntity>()
+ .eq(MediaFileEntity::getWorkspaceId, workspaceId));
+ List<MediaFileDTO> records = pageData.getRecords()
+ .stream()
+ .map(this::entityConvertToDto)
+ .collect(Collectors.toList());
+
+ return new PaginationData<MediaFileDTO>(records, new Pagination(pageData));
+ }
+
+ @Override
+ public URL getObjectUrl(String workspaceId, String fingerprint) {
+ Optional<MediaFileEntity> mediaFileOpt = getMediaByFingerprint(workspaceId, fingerprint);
+ if (mediaFileOpt.isEmpty()) {
+ throw new IllegalArgumentException("{} doesn't exist.");
+ }
+
+ return ossService.getObjectUrl(configuration.getBucket(), mediaFileOpt.get().getObjectKey());
+ }
+
/**
* Convert the received file object into a database entity object.
* @param file
@@ -72,6 +114,7 @@
.objectKey(file.getObjectKey())
.subFileType(file.getSubFileType())
.isOriginal(file.getExt().getIsOriginal())
+ .jobId(file.getExt().getFlightId())
.drone(file.getExt().getSn())
.tinnyFingerprint(file.getExt().getTinnyFingerprint());
@@ -81,7 +124,7 @@
.mapToInt(Integer::intValue)
.toArray();
Optional<DeviceDictionaryDTO> payloadDict = deviceDictionaryService
- .getOneDictionaryInfoByDomainTypeSubType(payloadModel[0], payloadModel[1], payloadModel[2]);
+ .getOneDictionaryInfoByTypeSubType(payloadModel[1], payloadModel[2]);
payloadDict.ifPresent(payload -> builder.payload(payload.getDeviceName()));
}
return builder.build();
@@ -99,9 +142,12 @@
builder.fileName(entity.getFileName())
.filePath(entity.getFilePath())
.isOriginal(entity.getIsOriginal())
+ .fingerprint(entity.getFingerprint())
.objectKey(entity.getObjectKey())
.tinnyFingerprint(entity.getTinnyFingerprint())
.payload(entity.getPayload())
+ .createTime(LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
.drone(entity.getDrone());
}
diff --git a/src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java b/src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java
index f7758d8..0e92b0b 100644
--- a/src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java
+++ b/src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java
@@ -1,13 +1,22 @@
package com.dji.sample.media.service.impl;
+import com.dji.sample.common.model.ResponseResult;
+import com.dji.sample.component.mqtt.model.*;
+import com.dji.sample.component.mqtt.service.IMessageSenderService;
+import com.dji.sample.media.model.FileUploadCallback;
import com.dji.sample.media.model.FileUploadDTO;
import com.dji.sample.media.model.MediaFileDTO;
import com.dji.sample.media.service.IFileService;
import com.dji.sample.media.service.IMediaService;
+import com.dji.sample.wayline.model.dto.WaylineJobDTO;
+import com.dji.sample.wayline.service.IWaylineJobService;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.stereotype.Service;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
/**
@@ -20,6 +29,15 @@
@Autowired
private IFileService fileService;
+
+ @Autowired
+ private IWaylineJobService waylineJobService;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Autowired
+ private IMessageSenderService messageSenderService;
@Override
public Boolean fastUpload(String workspaceId, String fingerprint) {
@@ -38,4 +56,42 @@
.map(MediaFileDTO::getTinnyFingerprint)
.collect(Collectors.toList());
}
+
+ @Override
+ public List<String> getExistTinyFingerprints(String workspaceId, List<String> tinyFingerprints) {
+ List<String> tinyFingerprintList = this.getAllTinyFingerprintsByWorkspaceId(workspaceId);
+ return tinyFingerprints
+ .stream()
+ .filter(tinyFingerprintList::contains)
+ .collect(Collectors.toList());
+
+ }
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK, outputChannel = ChannelName.OUTBOUND)
+ public void handleFileUploadCallBack(CommonTopicReceiver receiver) {
+ FileUploadCallback callback = objectMapper.convertValue(receiver.getData(), FileUploadCallback.class);
+
+ String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + receiver.getGateway()
+ + TopicConst.EVENTS_SUF + TopicConst._REPLY_SUF;
+ CommonTopicResponse<Object> data = CommonTopicResponse.builder()
+ .timestamp(System.currentTimeMillis())
+ .method(EventsMethodEnum.FILE_UPLOAD_CALLBACK.getMethod())
+ .data(ResponseResult.success())
+ .tid(receiver.getTid())
+ .bid(receiver.getBid())
+ .build();
+ if (callback.getResult() == ResponseResult.CODE_SUCCESS) {
+ String jobId = callback.getFile().getExt().getFlightId();
+ Optional<WaylineJobDTO> jobOpt = waylineJobService.getJobByJobId(jobId);
+ if (jobOpt.isPresent()) {
+ int id = fileService.saveFile(jobOpt.get().getWorkspaceId(), callback.getFile());
+ if (id <= 0) {
+ data.setData(ResponseResult.error());
+ }
+ }
+ }
+
+ messageSenderService.publish(topic, data);
+ }
}
diff --git a/src/main/java/com/dji/sample/storage/controller/StorageController.java b/src/main/java/com/dji/sample/storage/controller/StorageController.java
index 7c40607..01147e7 100644
--- a/src/main/java/com/dji/sample/storage/controller/StorageController.java
+++ b/src/main/java/com/dji/sample/storage/controller/StorageController.java
@@ -1,13 +1,8 @@
package com.dji.sample.storage.controller;
import com.dji.sample.common.model.ResponseResult;
-import com.dji.sample.component.oss.model.AliyunOSSConfiguration;
-import com.dji.sample.component.oss.model.MinIOConfiguration;
import com.dji.sample.media.model.StsCredentialsDTO;
import com.dji.sample.storage.service.IStorageService;
-import com.dji.sample.storage.service.impl.AliyunStorageServiceImpl;
-import com.dji.sample.storage.service.impl.MinIOStorageServiceImpl;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@@ -21,24 +16,11 @@
*/
@RestController
@RequestMapping("${url.storage.prefix}${url.storage.version}/workspaces/")
-@Slf4j
public class StorageController {
+ @Autowired
private IStorageService storageService;
- @Autowired
- private void setOssService(@Autowired(required = false) AliyunStorageServiceImpl aliyunStorageService,
- @Autowired(required = false) MinIOStorageServiceImpl minIOStorageService) {
- if (AliyunOSSConfiguration.enable) {
- this.storageService = aliyunStorageService;
- return;
- }
- if (MinIOConfiguration.enable) {
- this.storageService = minIOStorageService;
- return;
- }
- log.error("storageService is null.");
- }
/**
* Get temporary credentials for uploading the media and wayline in DJI Pilot.
* @param workspaceId
@@ -50,4 +32,5 @@
StsCredentialsDTO stsCredentials = storageService.getSTSCredentials();
return ResponseResult.success(stsCredentials);
}
+
}
diff --git a/src/main/java/com/dji/sample/storage/service/IStorageService.java b/src/main/java/com/dji/sample/storage/service/IStorageService.java
index 0dc98c9..9bca0ef 100644
--- a/src/main/java/com/dji/sample/storage/service/IStorageService.java
+++ b/src/main/java/com/dji/sample/storage/service/IStorageService.java
@@ -1,6 +1,8 @@
package com.dji.sample.storage.service;
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.media.model.StsCredentialsDTO;
+import org.springframework.messaging.MessageHeaders;
/**
* @author sean
@@ -14,4 +16,11 @@
* @return temporary credentials object
*/
StsCredentialsDTO getSTSCredentials();
+
+ /**
+ * Handles requests from the dock to obtain temporary credentials.
+ * @param receiver
+ * @param headers
+ */
+ void replyConfigGet(CommonTopicReceiver receiver, MessageHeaders headers);
}
diff --git a/src/main/java/com/dji/sample/storage/service/impl/StorageServiceImpl.java b/src/main/java/com/dji/sample/storage/service/impl/StorageServiceImpl.java
new file mode 100644
index 0000000..e47db9c
--- /dev/null
+++ b/src/main/java/com/dji/sample/storage/service/impl/StorageServiceImpl.java
@@ -0,0 +1,56 @@
+package com.dji.sample.storage.service.impl;
+
+import com.dji.sample.component.mqtt.model.*;
+import com.dji.sample.component.mqtt.service.IMessageSenderService;
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.service.impl.OssServiceContext;
+import com.dji.sample.media.model.StsCredentialsDTO;
+import com.dji.sample.storage.service.IStorageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2022/3/9
+ */
+@Service
+public class StorageServiceImpl implements IStorageService {
+
+ @Autowired
+ private IMessageSenderService messageSender;
+
+ @Autowired
+ private OssServiceContext ossService;
+
+ @Autowired
+ private OssConfiguration configuration;
+
+ @Override
+ public StsCredentialsDTO getSTSCredentials() {
+ return StsCredentialsDTO.builder()
+ .endpoint(configuration.getEndpoint())
+ .bucket(configuration.getBucket())
+ .credentials(ossService.getCredentials())
+ .provider(configuration.getProvider())
+ .objectKeyPrefix(configuration.getObjectDirPrefix())
+ .region(configuration.getRegion())
+ .build();
+ }
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET, outputChannel = ChannelName.OUTBOUND)
+ public void replyConfigGet(CommonTopicReceiver receiver, MessageHeaders headers) {
+ CommonTopicResponse<RequestsReply> response = CommonTopicResponse.<RequestsReply>builder()
+ .tid(receiver.getTid())
+ .bid(receiver.getBid())
+ .data(RequestsReply.success(this.getSTSCredentials()))
+ .timestamp(System.currentTimeMillis())
+ .method(receiver.getMethod())
+ .build();
+ messageSender.publish(headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF, response);
+ }
+}
diff --git a/src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java b/src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java
index 5af35a3..93390e4 100644
--- a/src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java
+++ b/src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java
@@ -3,10 +3,9 @@
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.oss.model.AliyunOSSConfiguration;
-import com.dji.sample.wayline.model.WaylineFileDTO;
-import com.dji.sample.wayline.model.WaylineFileUploadDTO;
-import com.dji.sample.wayline.model.WaylineQueryParam;
+import com.dji.sample.wayline.model.dto.WaylineFileDTO;
+import com.dji.sample.wayline.model.dto.WaylineFileUploadDTO;
+import com.dji.sample.wayline.model.param.WaylineQueryParam;
import com.dji.sample.wayline.service.IWaylineFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -15,6 +14,7 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URL;
+import java.sql.SQLException;
import java.util.List;
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
@@ -70,12 +70,10 @@
public void getFileUrl(@PathVariable(name = "workspace_id") String workspaceId,
@PathVariable(name = "wayline_id") String waylineId, HttpServletResponse response) {
- WaylineFileDTO wayline = waylineFileService.getWaylineByWaylineId(workspaceId, waylineId);
- URL url = waylineFileService.getObjectUrl(AliyunOSSConfiguration.bucket, wayline.getObjectKey());
-
try {
+ URL url = waylineFileService.getObjectUrl(workspaceId, waylineId);
response.sendRedirect(url.toString());
- } catch (Exception e) {
+ } catch (IOException | SQLException e) {
e.printStackTrace();
}
}
@@ -147,4 +145,17 @@
return ResponseResult.success(existNamesList);
}
+
+ /**
+ * Delete the wayline file in the workspace according to the wayline id.
+ * @param workspaceId
+ * @param waylineId
+ * @return
+ */
+ @DeleteMapping("/{workspace_id}/waylines/{wayline_id}")
+ public ResponseResult deleteWayline(@PathVariable(name = "workspace_id") String workspaceId,
+ @PathVariable(name = "wayline_id") String waylineId) {
+ boolean isDel = waylineFileService.deleteByWaylineId(workspaceId, waylineId);
+ return isDel ? ResponseResult.success() : ResponseResult.error("Failed to delete wayline.");
+ }
}
diff --git a/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java b/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
new file mode 100644
index 0000000..f066f54
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
@@ -0,0 +1,74 @@
+package com.dji.sample.wayline.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.wayline.model.dto.WaylineJobDTO;
+import com.dji.sample.wayline.model.param.CreateJobParam;
+import com.dji.sample.wayline.service.IWaylineJobService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.sql.SQLException;
+
+import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@RequestMapping("${url.wayline.prefix}${url.wayline.version}/workspaces")
+@RestController
+public class WaylineJobController {
+
+ @Autowired
+ private IWaylineJobService waylineJobService;
+
+ /**
+ * Create a wayline task for the Dock.
+ * @param request
+ * @param param
+ * @param workspaceId
+ * @return
+ * @throws SQLException
+ */
+ @PostMapping("/{workspace_id}/flight-tasks")
+ public ResponseResult createJob(HttpServletRequest request, @RequestBody CreateJobParam param,
+ @PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
+ CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
+ customClaim.setWorkspaceId(workspaceId);
+ boolean isCreate = waylineJobService.createJob(param, customClaim);
+ return isCreate ? ResponseResult.success() : ResponseResult.error();
+ }
+
+ /**
+ * Paginate through all jobs in this workspace.
+ * @param page
+ * @param pageSize
+ * @param workspaceId
+ * @return
+ */
+ @GetMapping("/{workspace_id}/jobs")
+ public ResponseResult<PaginationData<WaylineJobDTO>> getJobs(@RequestParam(defaultValue = "1") Long page,
+ @RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
+ @PathVariable(name = "workspace_id") String workspaceId) {
+ PaginationData<WaylineJobDTO> data = waylineJobService.getJobsByWorkspaceId(workspaceId, page, pageSize);
+ return ResponseResult.success(data);
+ }
+
+ /**
+ * Issue wayline mission to the dock for execution.
+ * @param jobId
+ * @param workspaceId
+ * @return
+ * @throws SQLException
+ */
+ @PostMapping("/{workspace_id}/jobs/{job_id}")
+ public ResponseResult publishJob(@PathVariable(name = "job_id") String jobId,
+ @PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
+ waylineJobService.publishFlightTask(workspaceId, jobId);
+ return ResponseResult.success();
+ }
+}
diff --git a/src/main/java/com/dji/sample/wayline/dao/IWaylineFileMapper.java b/src/main/java/com/dji/sample/wayline/dao/IWaylineFileMapper.java
index 10a0520..5537e4f 100644
--- a/src/main/java/com/dji/sample/wayline/dao/IWaylineFileMapper.java
+++ b/src/main/java/com/dji/sample/wayline/dao/IWaylineFileMapper.java
@@ -1,7 +1,7 @@
package com.dji.sample.wayline.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.dji.sample.wayline.model.WaylineFileEntity;
+import com.dji.sample.wayline.model.entity.WaylineFileEntity;
/**
* @author sean
diff --git a/src/main/java/com/dji/sample/wayline/dao/IWaylineJobMapper.java b/src/main/java/com/dji/sample/wayline/dao/IWaylineJobMapper.java
new file mode 100644
index 0000000..9a18c69
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/dao/IWaylineJobMapper.java
@@ -0,0 +1,12 @@
+package com.dji.sample.wayline.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dji.sample.wayline.model.entity.WaylineJobEntity;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+public interface IWaylineJobMapper extends BaseMapper<WaylineJobEntity> {
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/FLightTaskProgress.java b/src/main/java/com/dji/sample/wayline/model/dto/FLightTaskProgress.java
new file mode 100644
index 0000000..e8e8794
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/FLightTaskProgress.java
@@ -0,0 +1,16 @@
+package com.dji.sample.wayline.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+@Data
+public class FLightTaskProgress {
+
+ private Integer currentStep;
+
+ private Integer percent;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskCreateDTO.java b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskCreateDTO.java
new file mode 100644
index 0000000..736a8c5
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskCreateDTO.java
@@ -0,0 +1,24 @@
+package com.dji.sample.wayline.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FlightTaskCreateDTO {
+
+ private String flightId;
+
+ private String type;
+
+ private FlightTaskFileDTO file;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskFileDTO.java b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskFileDTO.java
new file mode 100644
index 0000000..ca0accb
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskFileDTO.java
@@ -0,0 +1,22 @@
+package com.dji.sample.wayline.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FlightTaskFileDTO {
+
+ private String url;
+
+ private String sign;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressExt.java b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressExt.java
new file mode 100644
index 0000000..c75ef1e
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressExt.java
@@ -0,0 +1,16 @@
+package com.dji.sample.wayline.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+@Data
+public class FlightTaskProgressExt {
+
+ private Integer currentWaypointIndex;
+
+ private Integer mediaCount;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressReceiver.java b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressReceiver.java
new file mode 100644
index 0000000..d2f7c7c
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressReceiver.java
@@ -0,0 +1,19 @@
+package com.dji.sample.wayline.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+@Data
+public class FlightTaskProgressReceiver {
+
+ private FlightTaskProgressExt ext;
+
+ private FLightTaskProgress progress;
+
+ private String status;
+
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/WaylineFileDTO.java b/src/main/java/com/dji/sample/wayline/model/dto/WaylineFileDTO.java
new file mode 100644
index 0000000..8e6282a
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/WaylineFileDTO.java
@@ -0,0 +1,43 @@
+package com.dji.sample.wayline.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2021/12/22
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class WaylineFileDTO {
+
+ private String name;
+
+ @JsonProperty("id")
+ private String waylineId;
+
+ private String droneModelKey;
+
+ private String sign;
+
+ private List<String> payloadModelKeys;
+
+ private Boolean favorited;
+
+ private List<Integer> templateTypes;
+
+ private String objectKey;
+
+ @JsonProperty("user_name")
+ private String username;
+
+ private Long updateTime;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/WaylineFileUploadDTO.java b/src/main/java/com/dji/sample/wayline/model/dto/WaylineFileUploadDTO.java
new file mode 100644
index 0000000..61f7d01
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/WaylineFileUploadDTO.java
@@ -0,0 +1,18 @@
+package com.dji.sample.wayline.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2021/12/23
+ */
+@Data
+public class WaylineFileUploadDTO {
+
+ private String objectKey;
+
+ private String name;
+
+ private WaylineFileDTO metadata;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java b/src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java
new file mode 100644
index 0000000..a8820a7
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java
@@ -0,0 +1,43 @@
+package com.dji.sample.wayline.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/6/1
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class WaylineJobDTO {
+
+ private String jobId;
+
+ private String jobName;
+
+ private String fileId;
+
+ private String fileName;
+
+ private String dockSn;
+
+ private String dockName;
+
+ private String workspaceId;
+
+ private String bid;
+
+ private String type;
+
+ private String username;
+
+ private LocalDateTime updateTime;
+
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/entity/WaylineFileEntity.java b/src/main/java/com/dji/sample/wayline/model/entity/WaylineFileEntity.java
new file mode 100644
index 0000000..27be0bf
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/entity/WaylineFileEntity.java
@@ -0,0 +1,62 @@
+package com.dji.sample.wayline.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2021/12/22
+ */
+@Data
+@TableName("wayline_file")
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class WaylineFileEntity implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @TableField("name")
+ private String name;
+
+ @TableField("wayline_id")
+ private String waylineId;
+
+ @TableField("drone_model_key")
+ private String droneModelKey;
+
+ @TableField("payload_model_keys")
+ private String payloadModelKeys;
+
+ @TableField("sign")
+ private String sign;
+
+ @TableField("workspace_id")
+ private String workspaceId;
+
+ @TableField("favorited")
+ private Boolean favorited;
+
+ @TableField("template_types")
+ private String templateTypes;
+
+ @TableField("object_key")
+ private String objectKey;
+
+ @TableField("user_name")
+ private String username;
+
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+ private Long updateTime;
+
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/entity/WaylineJobEntity.java b/src/main/java/com/dji/sample/wayline/model/entity/WaylineJobEntity.java
new file mode 100644
index 0000000..f2106f6
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/entity/WaylineJobEntity.java
@@ -0,0 +1,56 @@
+package com.dji.sample.wayline.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("wayline_job")
+public class WaylineJobEntity implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @TableField("job_id")
+ private String jobId;
+
+ @TableField("name")
+ private String name;
+
+ @TableField("file_id")
+ private String fileId;
+
+ @TableField("dock_sn")
+ private String dockSn;
+
+ @TableField("workspace_id")
+ private String workspaceId;
+
+ @TableField("bid")
+ private String bid;
+
+ @TableField("type")
+ private String type;
+
+ @TableField("username")
+ private String username;
+
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+ private Long updateTime;
+
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/param/CreateJobParam.java b/src/main/java/com/dji/sample/wayline/model/param/CreateJobParam.java
new file mode 100644
index 0000000..a186838
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/param/CreateJobParam.java
@@ -0,0 +1,22 @@
+package com.dji.sample.wayline.model.param;
+
+import lombok.Data;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@Data
+public class CreateJobParam {
+
+ private String name;
+
+ private String fileId;
+
+ private String dockSn;
+
+ private String type;
+
+ private boolean immediate;
+}
diff --git a/src/main/java/com/dji/sample/wayline/model/param/WaylineQueryParam.java b/src/main/java/com/dji/sample/wayline/model/param/WaylineQueryParam.java
new file mode 100644
index 0000000..e0c39ce
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/model/param/WaylineQueryParam.java
@@ -0,0 +1,30 @@
+package com.dji.sample.wayline.model.param;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author sean
+ * @version 0.3
+ * @date 2021/12/22
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class WaylineQueryParam {
+
+ private boolean favorited;
+
+ @Builder.Default
+ private int page = 1;
+
+ @Builder.Default
+ private int pageSize = 10;
+
+ private String orderBy;
+
+ private Integer[] templateType;
+}
diff --git a/src/main/java/com/dji/sample/wayline/service/IFlightTaskService.java b/src/main/java/com/dji/sample/wayline/service/IFlightTaskService.java
new file mode 100644
index 0000000..8bc6e63
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/service/IFlightTaskService.java
@@ -0,0 +1,18 @@
+package com.dji.sample.wayline.service;
+
+import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
+import org.springframework.messaging.MessageHeaders;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+public interface IFlightTaskService {
+
+ /**
+ * Handle the progress messages of the flight tasks reported by the dock.
+ * @param receiver
+ */
+ void handleProgress(CommonTopicReceiver receiver, MessageHeaders headers);
+}
diff --git a/src/main/java/com/dji/sample/wayline/service/IWaylineFileService.java b/src/main/java/com/dji/sample/wayline/service/IWaylineFileService.java
index 941890d..83f1820 100644
--- a/src/main/java/com/dji/sample/wayline/service/IWaylineFileService.java
+++ b/src/main/java/com/dji/sample/wayline/service/IWaylineFileService.java
@@ -1,11 +1,13 @@
package com.dji.sample.wayline.service;
import com.dji.sample.common.model.PaginationData;
-import com.dji.sample.wayline.model.WaylineFileDTO;
-import com.dji.sample.wayline.model.WaylineQueryParam;
+import com.dji.sample.wayline.model.dto.WaylineFileDTO;
+import com.dji.sample.wayline.model.param.WaylineQueryParam;
import java.net.URL;
+import java.sql.SQLException;
import java.util.List;
+import java.util.Optional;
/**
* @author sean
@@ -28,15 +30,15 @@
* @param waylineId
* @return
*/
- WaylineFileDTO getWaylineByWaylineId(String workspaceId, String waylineId);
+ Optional<WaylineFileDTO> getWaylineByWaylineId(String workspaceId, String waylineId);
/**
* Get the download address of the file object.
- * @param bucket bucket name
- * @param objectKey object name
+ * @param workspaceId
+ * @param waylineId
* @return
*/
- URL getObjectUrl(String bucket, String objectKey);
+ URL getObjectUrl(String workspaceId, String waylineId) throws SQLException;
/**
* Save the basic information of the wayline file.
@@ -62,4 +64,11 @@
* @return
*/
List<String> getDuplicateNames(String workspaceId, List<String> names);
+
+ /**
+ * Delete the wayline file based on the wayline id.
+ * @param workspaceId
+ * @param waylineId
+ */
+ Boolean deleteByWaylineId(String workspaceId, String waylineId);
}
diff --git a/src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java b/src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java
new file mode 100644
index 0000000..4dc78d9
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java
@@ -0,0 +1,56 @@
+package com.dji.sample.wayline.service;
+
+import com.dji.sample.common.model.CustomClaim;
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.wayline.model.dto.WaylineJobDTO;
+import com.dji.sample.wayline.model.param.CreateJobParam;
+
+import java.sql.SQLException;
+import java.util.Optional;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+public interface IWaylineJobService {
+
+ /**
+ * Create a wayline mission for the dock.
+ * @param param
+ * @param customClaim user info
+ * @return
+ */
+ Boolean createJob(CreateJobParam param, CustomClaim customClaim) throws SQLException;
+
+ /**
+ * Issue wayline mission to the dock for execution.
+ * @param workspaceId
+ * @param jobId
+ * @return
+ */
+ void publishFlightTask(String workspaceId, String jobId) throws SQLException;
+
+ /**
+ * Query job information based on job id.
+ * @param jobId
+ * @return job information
+ */
+ Optional<WaylineJobDTO> getJobByJobId(String jobId);
+
+ /**
+ * Update job data.
+ * @param dto
+ * @return
+ */
+ Boolean updateJob(WaylineJobDTO dto);
+
+ /**
+ * Paginate through all jobs in this workspace.
+ * @param workspaceId
+ * @param page
+ * @param pageSize
+ * @return
+ */
+ PaginationData<WaylineJobDTO> getJobsByWorkspaceId(String workspaceId, long page, long pageSize);
+}
diff --git a/src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java b/src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java
new file mode 100644
index 0000000..46774bb
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java
@@ -0,0 +1,84 @@
+package com.dji.sample.wayline.service.impl;
+
+import com.dji.sample.common.model.ResponseResult;
+import com.dji.sample.component.mqtt.model.*;
+import com.dji.sample.component.mqtt.service.IMessageSenderService;
+import com.dji.sample.component.redis.RedisConst;
+import com.dji.sample.component.redis.RedisOpsUtils;
+import com.dji.sample.component.websocket.model.BizCodeEnum;
+import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
+import com.dji.sample.component.websocket.service.ISendMessageService;
+import com.dji.sample.component.websocket.service.IWebSocketManageService;
+import com.dji.sample.manage.model.dto.DeviceDTO;
+import com.dji.sample.manage.model.enums.UserTypeEnum;
+import com.dji.sample.wayline.model.dto.FlightTaskProgressReceiver;
+import com.dji.sample.wayline.service.IFlightTaskService;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/9
+ */
+@Service
+@Slf4j
+public class FlightTaskServiceImpl implements IFlightTaskService {
+
+ @Autowired
+ private IMessageSenderService messageSender;
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ @Autowired
+ private ISendMessageService websocketMessageService;
+
+ @Autowired
+ private IWebSocketManageService webSocketManageService;
+
+ @Autowired
+ private RedisOpsUtils redisOps;
+
+ @Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS, outputChannel = ChannelName.OUTBOUND)
+ public void handleProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
+ EventsReceiver<FlightTaskProgressReceiver> eventsReceiver = mapper.convertValue(receiver.getData(),
+ new TypeReference<EventsReceiver<FlightTaskProgressReceiver>>(){});
+ eventsReceiver.setBid(receiver.getBid());
+
+ log.info("Task progress: " + eventsReceiver.getOutput().getProgress().toString());
+
+ if (eventsReceiver.getResult() != ResponseResult.CODE_SUCCESS) {
+ log.error("Error code: " + eventsReceiver.getResult());
+ }
+
+ DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
+ websocketMessageService.sendBatch(
+ webSocketManageService.getValueWithWorkspaceAndUserType(
+ device.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
+ CustomWebSocketMessage.builder()
+ .data(eventsReceiver)
+ .timestamp(System.currentTimeMillis())
+ .bizCode(BizCodeEnum.FLIGHT_TASK_PROGRESS.getCode())
+ .build());
+
+ if (receiver.getNeedReply() == 1) {
+ String topic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF;
+ messageSender.publish(topic,
+ CommonTopicResponse.builder()
+ .tid(receiver.getTid())
+ .bid(receiver.getBid())
+ .method(EventsMethodEnum.FLIGHT_TASK_PROGRESS.getMethod())
+ .timestamp(System.currentTimeMillis())
+ .data(ResponseResult.success())
+ .build());
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java b/src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java
index 3d25fb6..f12979a 100644
--- a/src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java
+++ b/src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java
@@ -5,25 +5,24 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.common.model.Pagination;
import com.dji.sample.common.model.PaginationData;
-import com.dji.sample.component.oss.model.AliyunOSSConfiguration;
-import com.dji.sample.component.oss.model.MinIOConfiguration;
-import com.dji.sample.component.oss.service.IOssService;
-import com.dji.sample.component.oss.service.impl.AliyunOssServiceImpl;
-import com.dji.sample.component.oss.service.impl.MinIOServiceImpl;
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.service.impl.OssServiceContext;
import com.dji.sample.wayline.dao.IWaylineFileMapper;
-import com.dji.sample.wayline.model.WaylineFileDTO;
-import com.dji.sample.wayline.model.WaylineFileEntity;
-import com.dji.sample.wayline.model.WaylineQueryParam;
+import com.dji.sample.wayline.model.dto.WaylineFileDTO;
+import com.dji.sample.wayline.model.entity.WaylineFileEntity;
+import com.dji.sample.wayline.model.param.WaylineQueryParam;
import com.dji.sample.wayline.service.IWaylineFileService;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.net.URL;
+import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -34,27 +33,16 @@
*/
@Service
@Transactional
-@Slf4j
public class WaylineFileServiceImpl implements IWaylineFileService {
@Autowired
private IWaylineFileMapper mapper;
- private IOssService ossService;
+ @Autowired
+ private OssServiceContext ossService;
@Autowired
- private void setOssService(@Autowired(required = false) AliyunOssServiceImpl aliyunOssService,
- @Autowired(required = false) MinIOServiceImpl minIOService) {
- if (AliyunOSSConfiguration.enable) {
- this.ossService = aliyunOssService;
- return;
- }
- if (MinIOConfiguration.enable) {
- this.ossService = minIOService;
- return;
- }
- log.error("ossService is null.");
- }
+ private OssConfiguration configuration;
@Override
public PaginationData<WaylineFileDTO> getWaylinesByParam(String workspaceId, WaylineQueryParam param) {
@@ -82,17 +70,22 @@
}
@Override
- public WaylineFileDTO getWaylineByWaylineId(String workspaceId, String waylineId) {
- return this.entityConvertToDTO(
- mapper.selectOne(
- new LambdaQueryWrapper<WaylineFileEntity>()
- .eq(WaylineFileEntity::getWorkspaceId, workspaceId)
- .eq(WaylineFileEntity::getWaylineId, waylineId)));
+ public Optional<WaylineFileDTO> getWaylineByWaylineId(String workspaceId, String waylineId) {
+ return Optional.ofNullable(
+ this.entityConvertToDTO(
+ mapper.selectOne(
+ new LambdaQueryWrapper<WaylineFileEntity>()
+ .eq(WaylineFileEntity::getWorkspaceId, workspaceId)
+ .eq(WaylineFileEntity::getWaylineId, waylineId))));
}
@Override
- public URL getObjectUrl(String bucket, String objectKey) {
- return ossService.getObjectUrl(bucket, objectKey);
+ public URL getObjectUrl(String workspaceId, String waylineId) throws SQLException {
+ Optional<WaylineFileDTO> waylineOpt = this.getWaylineByWaylineId(workspaceId, waylineId);
+ if (waylineOpt.isEmpty()) {
+ throw new SQLException(waylineId + " does not exist.");
+ }
+ return ossService.getObjectUrl(configuration.getBucket(), waylineOpt.get().getObjectKey());
}
@Override
@@ -101,6 +94,13 @@
file.setWaylineId(UUID.randomUUID().toString());
file.setWorkspaceId(workspaceId);
+ byte[] object = ossService.getObject(configuration.getBucket(), metadata.getObjectKey());
+ if (object.length == 0) {
+ throw new RuntimeException("The file " + metadata.getObjectKey() +
+ " does not exist in the bucket[" + configuration.getBucket() + "].");
+ }
+
+ file.setSign(DigestUtils.md5DigestAsHex(object));
int insertId = mapper.insert(file);
return insertId > 0 ? file.getId() : insertId;
}
@@ -129,30 +129,48 @@
.collect(Collectors.toList());
}
+ @Override
+ public Boolean deleteByWaylineId(String workspaceId, String waylineId) {
+ Optional<WaylineFileDTO> waylineOpt = this.getWaylineByWaylineId(workspaceId, waylineId);
+ if (waylineOpt.isEmpty()) {
+ return true;
+ }
+ WaylineFileDTO wayline = waylineOpt.get();
+ boolean isDel = mapper.delete(new LambdaUpdateWrapper<WaylineFileEntity>()
+ .eq(WaylineFileEntity::getWorkspaceId, workspaceId)
+ .eq(WaylineFileEntity::getWaylineId, waylineId))
+ > 0;
+ if (!isDel) {
+ return false;
+ }
+ return ossService.deleteObject(configuration.getBucket(), wayline.getObjectKey());
+ }
+
/**
* Convert database entity objects into wayline data transfer object.
* @param entity
* @return
*/
private WaylineFileDTO entityConvertToDTO(WaylineFileEntity entity) {
- WaylineFileDTO.WaylineFileDTOBuilder builder = WaylineFileDTO.builder();
-
- if (entity != null) {
- builder.droneModelKey(entity.getDroneModelKey())
- .favorited(entity.getFavorited())
- .name(entity.getName())
- .payloadModelKeys(entity.getPayloadModelKeys() != null ?
- Arrays.asList(entity.getPayloadModelKeys().split(",")) : null)
- .templateTypes(Arrays.stream(entity.getTemplateTypes().split(","))
- .map(Integer::parseInt)
- .collect(Collectors.toList()))
- .username(entity.getUsername())
- .objectKey(entity.getObjectKey())
- .updateTime(entity.getUpdateTime())
- .waylineId(entity.getWaylineId());
+ if (entity == null) {
+ return null;
}
+ return WaylineFileDTO.builder()
+ .droneModelKey(entity.getDroneModelKey())
+ .favorited(entity.getFavorited())
+ .name(entity.getName())
+ .payloadModelKeys(entity.getPayloadModelKeys() != null ?
+ Arrays.asList(entity.getPayloadModelKeys().split(",")) : null)
+ .templateTypes(Arrays.stream(entity.getTemplateTypes().split(","))
+ .map(Integer::parseInt)
+ .collect(Collectors.toList()))
+ .username(entity.getUsername())
+ .objectKey(entity.getObjectKey())
+ .sign(entity.getSign())
+ .updateTime(entity.getUpdateTime())
+ .waylineId(entity.getWaylineId())
+ .build();
- return builder.build();
}
/**
diff --git a/src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java b/src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java
new file mode 100644
index 0000000..9a2336c
--- /dev/null
+++ b/src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java
@@ -0,0 +1,212 @@
+package com.dji.sample.wayline.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.dji.sample.common.model.CustomClaim;
+import com.dji.sample.common.model.Pagination;
+import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.component.mqtt.model.CommonTopicResponse;
+import com.dji.sample.component.mqtt.model.ServiceReply;
+import com.dji.sample.component.mqtt.model.ServicesMethodEnum;
+import com.dji.sample.component.mqtt.model.TopicConst;
+import com.dji.sample.component.mqtt.service.IMessageSenderService;
+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.service.IDeviceService;
+import com.dji.sample.wayline.dao.IWaylineJobMapper;
+import com.dji.sample.wayline.model.dto.FlightTaskCreateDTO;
+import com.dji.sample.wayline.model.dto.FlightTaskFileDTO;
+import com.dji.sample.wayline.model.dto.WaylineFileDTO;
+import com.dji.sample.wayline.model.dto.WaylineJobDTO;
+import com.dji.sample.wayline.model.entity.WaylineJobEntity;
+import com.dji.sample.wayline.model.param.CreateJobParam;
+import com.dji.sample.wayline.service.IWaylineFileService;
+import com.dji.sample.wayline.service.IWaylineJobService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.net.URL;
+import java.sql.SQLException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * @author sean
+ * @version 1.1
+ * @date 2022/6/1
+ */
+@Service
+@Transactional
+@Slf4j
+public class WaylineJobServiceImpl implements IWaylineJobService {
+
+ @Autowired
+ private IWaylineJobMapper mapper;
+
+ @Autowired
+ private IWaylineFileService waylineFileService;
+
+ @Autowired
+ private IDeviceService deviceService;
+
+ @Autowired
+ private IMessageSenderService messageSender;
+
+ @Autowired
+ private RedisOpsUtils redisOps;
+
+ @Override
+ public Boolean createJob(CreateJobParam param, CustomClaim customClaim) throws SQLException {
+ if (param == null) {
+ return false;
+ }
+ WaylineJobEntity jobEntity = WaylineJobEntity.builder()
+ .name(param.getName())
+ .dockSn(param.getDockSn())
+ .fileId(param.getFileId())
+ .username(customClaim.getUsername())
+ .workspaceId(customClaim.getWorkspaceId())
+ .jobId(UUID.randomUUID().toString())
+ .type(param.getType())
+ .build();
+ int id = mapper.insert(jobEntity);
+ if (id <= 0) {
+ return false;
+ }
+ if (param.isImmediate()) {
+ publishFlightTask(jobEntity.getWorkspaceId(), jobEntity.getJobId());
+ }
+ return true;
+ }
+
+ @Override
+ public void publishFlightTask(String workspaceId, String jobId) throws SQLException {
+ // get job
+ Optional<WaylineJobDTO> waylineJob = this.getJobByJobId(jobId);
+ if (waylineJob.isEmpty()) {
+ throw new IllegalArgumentException("Job doesn't exist.");
+ }
+
+ long expire = redisOps.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + waylineJob.get().getDockSn());
+ if (expire < 0) {
+ throw new RuntimeException("Dock is offline.");
+ }
+
+ // get wayline file
+ Optional<WaylineFileDTO> waylineFile = waylineFileService.getWaylineByWaylineId(workspaceId, waylineJob.get().getFileId());
+ if (waylineFile.isEmpty()) {
+ throw new IllegalArgumentException("Wayline file doesn't exist.");
+ }
+
+ // get file url
+ URL url = waylineFileService.getObjectUrl(workspaceId, waylineFile.get().getWaylineId());
+
+ WaylineJobDTO job = waylineJob.get();
+ FlightTaskCreateDTO flightTask = FlightTaskCreateDTO.builder()
+ .flightId(jobId)
+ .type(job.getType())
+ .file(FlightTaskFileDTO.builder()
+ .url(url.toString())
+ .sign(waylineFile.get().getSign())
+ .build())
+ .build();
+
+ String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT +
+ job.getDockSn() + TopicConst.SERVICES_SUF;
+ CommonTopicResponse<Object> response = CommonTopicResponse.builder()
+ .tid(UUID.randomUUID().toString())
+ .bid(UUID.randomUUID().toString())
+ .timestamp(System.currentTimeMillis())
+ .data(flightTask)
+ .method(ServicesMethodEnum.FLIGHTTASK_CREATE.getMethod())
+ .build();
+
+ Optional<ServiceReply> serviceReplyOpt = messageSender.publishWithReply(topic, response);
+ if (serviceReplyOpt.isEmpty()) {
+ log.info("Timeout to receive reply.");
+ throw new RuntimeException("Timeout to receive reply.");
+ }
+ if (serviceReplyOpt.get().getResult() != 0) {
+ log.info("Error code: {}", serviceReplyOpt.get().getResult());
+ throw new RuntimeException("Error code: " + serviceReplyOpt.get().getResult());
+ }
+
+ job.setBid(response.getBid());
+ boolean isUpd = this.updateJob(job);
+ if (!isUpd) {
+ throw new SQLException("Failed to update data.");
+ }
+ }
+
+ @Override
+ public Optional<WaylineJobDTO> getJobByJobId(String jobId) {
+ WaylineJobEntity jobEntity = mapper.selectOne(
+ new LambdaQueryWrapper<WaylineJobEntity>()
+ .eq(WaylineJobEntity::getJobId, jobId));
+ return Optional.ofNullable(entity2Dto(jobEntity));
+ }
+
+ @Override
+ public Boolean updateJob(WaylineJobDTO dto) {
+ return mapper.update(this.dto2Entity(dto),
+ new LambdaUpdateWrapper<WaylineJobEntity>()
+ .eq(WaylineJobEntity::getWorkspaceId, dto.getWorkspaceId())
+ .eq(WaylineJobEntity::getJobId, dto.getJobId()))
+ > 0;
+ }
+
+ @Override
+ public PaginationData<WaylineJobDTO> getJobsByWorkspaceId(String workspaceId, long page, long pageSize) {
+ Page<WaylineJobEntity> pageData = mapper.selectPage(
+ new Page<WaylineJobEntity>(page, pageSize),
+ new LambdaQueryWrapper<WaylineJobEntity>()
+ .eq(WaylineJobEntity::getWorkspaceId, workspaceId));
+ List<WaylineJobDTO> records = pageData.getRecords()
+ .stream()
+ .map(this::entity2Dto)
+ .collect(Collectors.toList());
+
+ return new PaginationData<WaylineJobDTO>(records, new Pagination(pageData));
+ }
+
+ private WaylineJobEntity dto2Entity(WaylineJobDTO dto) {
+ WaylineJobEntity.WaylineJobEntityBuilder builder = WaylineJobEntity.builder();
+ if (dto == null) {
+ return builder.build();
+ }
+ return builder.type(dto.getType())
+ .bid(dto.getBid())
+ .name(dto.getJobName())
+ .build();
+ }
+
+ private WaylineJobDTO entity2Dto(WaylineJobEntity entity) {
+ if (entity == null) {
+ return null;
+ }
+ return WaylineJobDTO.builder()
+ .jobId(entity.getJobId())
+ .bid(entity.getBid())
+ .updateTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getUpdateTime()), ZoneId.systemDefault()))
+ .jobName(entity.getName())
+ .fileId(entity.getFileId())
+ .fileName(waylineFileService.getWaylineByWaylineId(entity.getWorkspaceId(), entity.getFileId())
+ .orElse(WaylineFileDTO.builder().build()).getName())
+ .dockSn(entity.getDockSn())
+ .dockName(deviceService.getDeviceBySn(entity.getDockSn())
+ .orElse(DeviceDTO.builder().build()).getNickname())
+ .username(entity.getUsername())
+ .workspaceId(entity.getWorkspaceId())
+ .type(entity.getType())
+ .build();
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 8c95358..5d93be2 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -7,7 +7,7 @@
druid:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true
+ url: jdbc:mysql://cloud_api_sample_mysql:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
initial-size: 10
@@ -15,12 +15,18 @@
max-active: 20
max-wait: 60000
- jackson:
- property-naming-strategy: SNAKE_CASE
- date-format: yyyy-MM-dd HH:mm:ss
- default-property-inclusion: NON_NULL
- deserialization:
- FAIL_ON_UNKNOWN_PROPERTIES: false
+ redis:
+ host: cloud_api_sample_redis
+ port: 6379
+ database: 0
+ username: # if you enable
+ password:
+ lettuce:
+ pool:
+ max-active: 8
+ max-idle: 8
+ min-idle: 0
+
jwt:
issuer: DJI
@@ -30,13 +36,13 @@
mqtt:
protocol: tcp
- host: Please enter the address of the emqx server. # Example: 192.168.1.1
+ host: Please enter your ip. # 192.168.1.1
port: 1883
username: JavaServer
password: 123456
client-id: 123456
# Topics that need to be subscribed when initially connecting to mqtt, multiple topics are divided by ",".
- inbound-topic: sys/product/+/status
+ inbound-topic: sys/product/+/status,thing/product/+/requests
url:
manage:
@@ -56,29 +62,43 @@
version: /api/v1
# Tutorial: https://help.aliyun.com/document_detail/100624.htm?spm=a2c4g.11186623.0.0.74075e34eIhK7T#concept-xzh-nzk-2gb
-aliyun:
- oss:
- enable: false
- endpoint: Please enter your endpoint. # Example: https://oss-cn-shenzhen.aliyuncs.com
- access-key: Please enter your access key.
- secret-key: Please enter your secret key.
- expire: 3600
- region: Please enter oss region. # Example: cn-shenzhen
- role-session-name: Please enter session name. # A custom role session name to distinguish the different tokens, for example it could be filled in as SessionTest.
- role-arn: Please enter role ARN. # Example: acs:ram::123456789:role/oss
- bucket: Please enter bucket name.
- object-dir-prefix: Please enter object prefix.
+oss:
+ enable: true
+ provider: ali # @see com.dji.sample.component.OssConfiguration.model.enums.OssTypeEnum
+ endpoint: https://oss-cn-hangzhou.aliyuncs.com
+ access-key: Please enter your access key.
+ secret-key: Please enter your secret key.
+ expire: 3600
+ region: Please enter your oss region. # cn-hangzhou
+ role-session-name: cloudApi
+ role-arn: Please enter your role arn. # acs:ram::123456789:role/stsrole
+ bucket: Please enter your bucket name.
+ object-dir-prefix: Please enter a folder name.
+
+#oss:
+# enable: true
+# provider: aws
+# endpoint: https://s3.us-east-1.amazonaws.com
+# access-key:
+# secret-key:
+# expire: 3600
+# region: us-east-1
+# role-session-name: cloudApi
+# role-arn:
+# bucket: cloudapi-bucket
+# object-dir-prefix: wayline
# MinIO is temporarily unavailable.
-minio:
- enable: false
- endpoint: Please enter your endpoint. #http://192.168.1.1:9000/
- access-key: minioadmin
- secret-key: minioadmin
- bucket: Please enter bucket name.
- expire: 3600
- region: Please enter minio region.
- object-dir-prefix: Please enter object prefix.
+#oss:
+# enable: false
+# provider: minio
+# endpoint:
+# access-key:
+# secret-key:
+# bucket:
+# expire:
+# region:
+# object-dir-prefix:
logging:
level:
--
Gitblit v1.9.3