Browse Source

What's new?

1. Wayline management: added `pause wayline task` and `recover wayline task`.
2. Added command flight function.
3. Fixed some issues.
v1.4.0
sean.zhou 2 years ago
parent
commit
694b9483c7
  1. 317
      api/Cloud API Demo.postman_collection.json
  2. 2
      pom.xml
  3. 5
      sql/cloud_sample.sql
  4. 2
      src/main/java/com/dji/sample/component/GlobalExceptionHandler.java
  5. 11
      src/main/java/com/dji/sample/component/GlobalScheduleService.java
  6. 27
      src/main/java/com/dji/sample/component/mqtt/config/MqttConfiguration.java
  7. 29
      src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java
  8. 29
      src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java
  9. 9
      src/main/java/com/dji/sample/component/mqtt/handler/ServicesReplyHandler.java
  10. 12
      src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java
  11. 10
      src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java
  12. 4
      src/main/java/com/dji/sample/component/mqtt/model/EventsOutputProgressReceiver.java
  13. 5
      src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java
  14. 50
      src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java
  15. 78
      src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java
  16. 12
      src/main/java/com/dji/sample/component/redis/RedisConst.java
  17. 17
      src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java
  18. 4
      src/main/java/com/dji/sample/component/websocket/service/ISendMessageService.java
  19. 27
      src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java
  20. 40
      src/main/java/com/dji/sample/control/controller/DockController.java
  21. 55
      src/main/java/com/dji/sample/control/controller/DrcController.java
  22. 4
      src/main/java/com/dji/sample/control/model/dto/AlarmState.java
  23. 4
      src/main/java/com/dji/sample/control/model/dto/BatteryStoreMode.java
  24. 32
      src/main/java/com/dji/sample/control/model/dto/DrcModeDTO.java
  25. 15
      src/main/java/com/dji/sample/control/model/dto/DrcModeReasonReceiver.java
  26. 18
      src/main/java/com/dji/sample/control/model/dto/DrcStatusNotifyReceiver.java
  27. 22
      src/main/java/com/dji/sample/control/model/dto/FlyToProgressReceiver.java
  28. 26
      src/main/java/com/dji/sample/control/model/dto/JwtAclDTO.java
  29. 4
      src/main/java/com/dji/sample/control/model/dto/LinkWorkMode.java
  30. 31
      src/main/java/com/dji/sample/control/model/dto/MqttBrokerDTO.java
  31. 31
      src/main/java/com/dji/sample/control/model/dto/PointDTO.java
  32. 25
      src/main/java/com/dji/sample/control/model/dto/RemoteDebugOpenState.java
  33. 24
      src/main/java/com/dji/sample/control/model/dto/ResultNotifyDTO.java
  34. 27
      src/main/java/com/dji/sample/control/model/dto/ReturnHomeState.java
  35. 25
      src/main/java/com/dji/sample/control/model/dto/TakeoffProgressReceiver.java
  36. 26
      src/main/java/com/dji/sample/control/model/enums/CameraModeEnum.java
  37. 26
      src/main/java/com/dji/sample/control/model/enums/CameraStateEnum.java
  38. 38
      src/main/java/com/dji/sample/control/model/enums/CameraTypeEnum.java
  39. 22
      src/main/java/com/dji/sample/control/model/enums/DrcMethodEnum.java
  40. 47
      src/main/java/com/dji/sample/control/model/enums/DrcModeReasonEnum.java
  41. 52
      src/main/java/com/dji/sample/control/model/enums/DrcStatusErrorEnum.java
  42. 25
      src/main/java/com/dji/sample/control/model/enums/DroneAuthorityEnum.java
  43. 28
      src/main/java/com/dji/sample/control/model/enums/DroneControlMethodEnum.java
  44. 39
      src/main/java/com/dji/sample/control/model/enums/FlyToStatusEnum.java
  45. 26
      src/main/java/com/dji/sample/control/model/enums/GimbalResetModeEnum.java
  46. 24
      src/main/java/com/dji/sample/control/model/enums/MqttAclAccessEnum.java
  47. 52
      src/main/java/com/dji/sample/control/model/enums/PayloadCommandsEnum.java
  48. 20
      src/main/java/com/dji/sample/control/model/enums/RemoteDebugMethodEnum.java
  49. 47
      src/main/java/com/dji/sample/control/model/enums/TakeoffStatusEnum.java
  50. 19
      src/main/java/com/dji/sample/control/model/param/DeviceDrcInfoParam.java
  51. 19
      src/main/java/com/dji/sample/control/model/param/DrcConnectParam.java
  52. 35
      src/main/java/com/dji/sample/control/model/param/DrcModeParam.java
  53. 54
      src/main/java/com/dji/sample/control/model/param/DronePayloadParam.java
  54. 37
      src/main/java/com/dji/sample/control/model/param/FlyToPointParam.java
  55. 27
      src/main/java/com/dji/sample/control/model/param/PayloadCommandsParam.java
  56. 49
      src/main/java/com/dji/sample/control/model/param/TakeoffToPointParam.java
  57. 56
      src/main/java/com/dji/sample/control/service/IControlService.java
  58. 60
      src/main/java/com/dji/sample/control/service/IDrcService.java
  59. 24
      src/main/java/com/dji/sample/control/service/impl/CameraAimImpl.java
  60. 41
      src/main/java/com/dji/sample/control/service/impl/CameraFocalLengthSetImpl.java
  61. 31
      src/main/java/com/dji/sample/control/service/impl/CameraModeSwitchImpl.java
  62. 22
      src/main/java/com/dji/sample/control/service/impl/CameraPhotoTakeImpl.java
  63. 25
      src/main/java/com/dji/sample/control/service/impl/CameraRecordingStartImpl.java
  64. 22
      src/main/java/com/dji/sample/control/service/impl/CameraRecordingStopImpl.java
  65. 271
      src/main/java/com/dji/sample/control/service/impl/ControlServiceImpl.java
  66. 249
      src/main/java/com/dji/sample/control/service/impl/DrcServiceImpl.java
  67. 22
      src/main/java/com/dji/sample/control/service/impl/GimbalResetImpl.java
  68. 82
      src/main/java/com/dji/sample/control/service/impl/PayloadCommandsHandler.java
  69. 23
      src/main/java/com/dji/sample/control/service/impl/RemoteDebugHandler.java
  70. 35
      src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java
  71. 26
      src/main/java/com/dji/sample/manage/model/dto/DeviceAuthorityDTO.java
  72. 4
      src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java
  73. 6
      src/main/java/com/dji/sample/manage/model/dto/DevicePayloadDTO.java
  74. 3
      src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java
  75. 26
      src/main/java/com/dji/sample/manage/model/enums/ControlSourceEnum.java
  76. 10
      src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java
  77. 64
      src/main/java/com/dji/sample/manage/model/enums/DeviceModeCodeEnum.java
  78. 5
      src/main/java/com/dji/sample/manage/model/enums/DeviceSetPropertyEnum.java
  79. 36
      src/main/java/com/dji/sample/manage/model/enums/DockDrcStateEnum.java
  80. 42
      src/main/java/com/dji/sample/manage/model/enums/DockModeCodeEnum.java
  81. 26
      src/main/java/com/dji/sample/manage/model/enums/DroneRcLostActionEnum.java
  82. 14
      src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java
  83. 26
      src/main/java/com/dji/sample/manage/model/enums/WaylineRcLostActionEnum.java
  84. 5
      src/main/java/com/dji/sample/manage/model/receiver/BasicDeviceProperty.java
  85. 2
      src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java
  86. 14
      src/main/java/com/dji/sample/manage/model/receiver/FirmwareProgressExtReceiver.java
  87. 20
      src/main/java/com/dji/sample/manage/model/receiver/LiveviewWorldRegionReceiver.java
  88. 34
      src/main/java/com/dji/sample/manage/model/receiver/OsdCameraReceiver.java
  89. 8
      src/main/java/com/dji/sample/manage/model/receiver/OsdDockReceiver.java
  90. 16
      src/main/java/com/dji/sample/manage/model/receiver/OsdSubDeviceReceiver.java
  91. 29
      src/main/java/com/dji/sample/manage/model/receiver/OutOfControlActionReceiver.java
  92. 32
      src/main/java/com/dji/sample/manage/model/receiver/RthAltitudeReceiver.java
  93. 9
      src/main/java/com/dji/sample/manage/service/IDeviceFirmwareService.java
  94. 3
      src/main/java/com/dji/sample/manage/service/IDeviceLogsService.java
  95. 15
      src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java
  96. 95
      src/main/java/com/dji/sample/manage/service/IDeviceRedisService.java
  97. 57
      src/main/java/com/dji/sample/manage/service/IDeviceService.java
  98. 2
      src/main/java/com/dji/sample/manage/service/IWorkspaceService.java
  99. 8
      src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java
  100. 105
      src/main/java/com/dji/sample/manage/service/impl/DeviceFirmwareServiceImpl.java
  101. Some files were not shown because too many files have changed in this diff Show More

317
api/Cloud API Demo.postman_collection.json

@ -887,7 +887,7 @@ @@ -887,7 +887,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NzAzMTU2MDEsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NzA0MDIwMDEsImlhdCI6MTY3MDMxNTYwMSwidXNlcm5hbWUiOiJhZG1pblBDIn0.yh8SkHZVsoIXo_vtlTGNB-ZX92XayalGe_q7mNRVcdI",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2ODIyMzI5MDYsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE3Njg2MzI5MDYsImlhdCI6MTY4MjIzMjkwNiwidXNlcm5hbWUiOiJhZG1pblBDIn0.ilO-3PcvWAX9r8z3AR4VAw3kVhavYjiTx_187ACBc1M",
"type": "string"
},
{
@ -1537,7 +1537,7 @@ @@ -1537,7 +1537,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Njg2NTk4MjYsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2Njg3NDYyMjYsImlhdCI6MTY2ODY1OTgyNiwidXNlcm5hbWUiOiJhZG1pblBDIn0.ykCpfJcReeb3etUzmNMQk1n0vaoDT6dl47J_aHRoTbU",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2ODAyNjAxNTYsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE3NjY2NjAxNTYsImlhdCI6MTY4MDI2MDE1NiwidXNlcm5hbWUiOiJhZG1pblBDIn0._QhvfhBxxfQN7xpFqZma1rCYbBtouo2pErtm8737L_8",
"type": "string"
},
{
@ -1578,7 +1578,7 @@ @@ -1578,7 +1578,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"name\": \"\",\r\n \"file_id\": \"\",\r\n \"dock_sn\": \"\",\r\n \"wayline_type\": 0,\r\n \"task_type\": 0,\r\n \"execute_time\": 123456789123,\r\n \"rth_altitude\": 20,\r\n \"out_of_control_action\": 1\r\n}",
"raw": "{\r\n \"name\": \"\",\r\n \"file_id\": \"\",\r\n \"dock_sn\": \"\",\r\n \"wayline_type\": 0,\r\n \"task_type\": 0,\r\n \"task_days\": [1676029468],\r\n \"task_periods\": [[1676029468]],\r\n \"rth_altitude\": 20,\r\n \"out_of_control_action\": 1\r\n}",
"options": {
"raw": {
"language": "json"
@ -1679,6 +1679,64 @@ @@ -1679,6 +1679,64 @@
}
},
"response": []
},
{
"name": "Pause Job",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"status\": 0\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{wayline_version}}/workspaces/{{workspace_id}}/jobs/{{job_id}}",
"host": [
"{{base_url}}{{wayline_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"jobs",
"{{job_id}}"
]
}
},
"response": []
},
{
"name": "Resume Job",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"status\": 1\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{wayline_version}}/workspaces/{{workspace_id}}/jobs/{{job_id}}",
"host": [
"{{base_url}}{{wayline_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"jobs",
"{{job_id}}"
]
}
},
"response": []
}
],
"auth": {
@ -1686,7 +1744,7 @@ @@ -1686,7 +1744,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Njg2NTk4MjYsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2Njg3NDYyMjYsImlhdCI6MTY2ODY1OTgyNiwidXNlcm5hbWUiOiJhZG1pblBDIn0.ykCpfJcReeb3etUzmNMQk1n0vaoDT6dl47J_aHRoTbU",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Nzg4NjM0NzMsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE3NjUyNjM0NzMsImlhdCI6MTY3ODg2MzQ3MywidXNlcm5hbWUiOiJhZG1pblBDIn0.r3ODgJtAHxrBCzDnCwTDCdUq8hLyfIUiDYzasYAIUII",
"type": "string"
},
{
@ -1727,7 +1785,7 @@ @@ -1727,7 +1785,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"action\": 0\r\n}",
"raw": "",
"options": {
"raw": {
"language": "json"
@ -1735,7 +1793,7 @@ @@ -1735,7 +1793,7 @@
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/jobs/alarm_state_switch",
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/jobs/return_home",
"host": [
"{{base_url}}{{control_version}}"
],
@ -1743,7 +1801,250 @@ @@ -1743,7 +1801,250 @@
"devices",
"{{device_sn}}",
"jobs",
"alarm_state_switch"
"return_home"
]
}
},
"response": []
},
{
"name": "Web Drc Connect",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"client_id\": \"xxx\",\r\n \"expire_sec\": 1800\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/workspaces/{{workspace_id}}/drc/connect",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"drc",
"connect"
]
}
},
"response": []
},
{
"name": "Enter Drc Mode",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"client_id\": \"\",\r\n \"dock_sn\": \"\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/workspaces/{{workspace_id}}/drc/enter",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"drc",
"enter"
]
}
},
"response": []
},
{
"name": "Drc Mode Exit",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"client_id\": \"\",\r\n \"dock_sn\": \"\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/workspaces/{{workspace_id}}/drc/exit",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"drc",
"exit"
]
}
},
"response": []
},
{
"name": "Fly to Point",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"max_speed\": 15,\r\n \"points\":[\r\n {\r\n \"latitude\": 22.5818,\r\n \"longitude\": 113.9394,\r\n \"height\": 20\r\n }\r\n ]\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/jobs/fly-to-point",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"jobs",
"fly-to-point"
]
}
},
"response": []
},
{
"name": "Stop Flying to Point",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/jobs/fly-to-point",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"jobs",
"fly-to-point"
]
}
},
"response": []
},
{
"name": "Take off to Point",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"target_latitude\": 22.579,\r\n \"target_longitude\": 113.9392,\r\n \"target_height\": 20,\r\n \"security_takeoff_height\": 20,\r\n \"rth_altitude\": 20,\r\n \"rc_lost_action\": 0,\r\n \"exit_wayline_when_rc_lost\": 0,\r\n \"max_speed\": 12\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/jobs/takeoff-to-point",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"jobs",
"takeoff-to-point"
]
}
},
"response": []
},
{
"name": "Payload Commands",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"cmd\":\"camera_mode_switch\",\r\n \"data\":{\r\n \"payload_index\":\"53-0-0\",\r\n \"camera_mode\": 1\r\n }\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/payload/commands",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"payload",
"commands"
]
}
},
"response": []
},
{
"name": "Flight Authority Grab",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/authority/flight",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"authority",
"flight"
]
}
},
"response": []
},
{
"name": "Payload Authority Grab",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"payload_index\":\"53-0-0\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/authority/payload",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"authority",
"payload"
]
}
},
@ -1755,7 +2056,7 @@ @@ -1755,7 +2056,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Njk2MzMzMzQsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2Njk3MTk3MzQsImlhdCI6MTY2OTYzMzMzNCwidXNlcm5hbWUiOiJhZG1pblBDIn0.OoIfdpyI5eL6bFm8akq8_stzClQU41YpIJkx6_kxVHU",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2ODIyMzI5MDYsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE3Njg2MzI5MDYsImlhdCI6MTY4MjIzMjkwNiwidXNlcm5hbWUiOiJhZG1pblBDIn0.ilO-3PcvWAX9r8z3AR4VAw3kVhavYjiTx_187ACBc1M",
"type": "string"
},
{

2
pom.xml

@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
<groupId>com.dji</groupId>
<artifactId>cloud-api-sample</artifactId>
<version>1.3.1</version>
<version>1.4.0</version>
<name>cloud-api-sample</name>
<properties>

5
sql/cloud_sample.sql

@ -66,7 +66,7 @@ CREATE TABLE `manage_device` ( @@ -66,7 +66,7 @@ CREATE TABLE `manage_device` (
`device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'dock, drone, remote control',
`device_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined' COMMENT 'model of the device. This parameter corresponds to the device name in the device dictionary table.',
`user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT 'The account used when the device was bound.',
`nickname` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT 'custom name of the device',
`nickname` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'custom name of the device',
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT 'The workspace to which the current device belongs.',
`device_type` int NOT NULL DEFAULT '-1' COMMENT 'This parameter corresponds to the device type in the device dictionary table.',
`sub_type` int NOT NULL DEFAULT '-1' COMMENT 'This parameter corresponds to the sub type in the device dictionary table.',
@ -226,6 +226,7 @@ CREATE TABLE `manage_device_payload` ( @@ -226,6 +226,7 @@ CREATE TABLE `manage_device_payload` (
`payload_index` smallint NOT NULL COMMENT 'The location of the payload on the device.',
`device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'Which device the current payload belongs to.',
`payload_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`control_source` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
PRIMARY KEY (`id`),
@ -452,7 +453,7 @@ CREATE TABLE `wayline_job` ( @@ -452,7 +453,7 @@ CREATE TABLE `wayline_job` (
`completed_time` bigint DEFAULT NULL COMMENT 'actual end time',
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The name of the creator.',
`begin_time` bigint NOT NULL COMMENT 'planned begin time',
`end_time` bigint NOT NULL COMMENT 'planned end time',
`end_time` bigint DEFAULT NULL COMMENT 'planned end time',
`error_code` int DEFAULT NULL,
`status` int NOT NULL COMMENT '1: pending; 2: in progress; 3: success; 4: cancel; 5: failed',
`rth_altitude` int NOT NULL COMMENT 'return to home altitude. min: 20m; max: 500m',

2
src/main/java/com/dji/sample/component/GlobalExceptionHandler.java

@ -36,7 +36,7 @@ public class GlobalExceptionHandler { @@ -36,7 +36,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
public ResponseResult methodArgumentNotValidExceptionHandler(BindException e) {
e.printStackTrace();
return ResponseResult.error(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
return ResponseResult.error(e.getFieldError().getField() + e.getFieldError().getDefaultMessage());
}
}

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

@ -7,6 +7,7 @@ import com.dji.sample.manage.model.dto.DeviceDTO; @@ -7,6 +7,7 @@ import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.wayline.service.IWaylineJobService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@ -32,11 +33,12 @@ public class GlobalScheduleService { @@ -32,11 +33,12 @@ public class GlobalScheduleService {
@Autowired
private IWaylineJobService waylineJobService;
@Autowired
private ObjectMapper mapper;
/**
* Check the status of the devices every 30 seconds. It is recommended to use cache.
*/
@Scheduled(initialDelay = 30, fixedRate = 30, timeUnit = TimeUnit.SECONDS)
@Scheduled(initialDelay = 10, fixedRate = 30, timeUnit = TimeUnit.SECONDS)
private void deviceStatusListen() {
int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
@ -49,8 +51,9 @@ public class GlobalScheduleService { @@ -49,8 +51,9 @@ public class GlobalScheduleService {
} else {
deviceService.unsubscribeTopicOffline(key.substring(start));
deviceService.pushDeviceOfflineTopo(device.getWorkspaceId(), device.getDeviceSn());
RedisOpsUtils.hashDel(RedisConst.LIVE_CAPACITY, new String[]{key});
RedisOpsUtils.del(RedisConst.HMS_PREFIX + key);
RedisOpsUtils.hashDel(RedisConst.LIVE_CAPACITY, new String[]{device.getDeviceSn()});
RedisOpsUtils.del(RedisConst.HMS_PREFIX + device.getDeviceSn());
RedisOpsUtils.del(RedisConst.OSD_PREFIX + device.getDeviceSn());
}
RedisOpsUtils.del(key);
}

27
src/main/java/com/dji/sample/component/mqtt/config/MqttConfiguration.java

@ -5,6 +5,7 @@ import com.dji.sample.common.util.JwtUtil; @@ -5,6 +5,7 @@ import com.dji.sample.common.util.JwtUtil;
import com.dji.sample.component.mqtt.model.MqttClientOptions;
import com.dji.sample.component.mqtt.model.MqttProtocolEnum;
import com.dji.sample.component.mqtt.model.MqttUseEnum;
import com.dji.sample.control.model.dto.MqttBrokerDTO;
import lombok.Data;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -70,6 +71,32 @@ public class MqttConfiguration { @@ -70,6 +71,32 @@ public class MqttConfiguration {
return addr.toString();
}
/**
* Get the connection parameters of the mqtt client of the drc link.
* @param clientId
* @param username
* @param age The validity period of the token. unit: s
* @param map Custom data added in token.
* @return
*/
public static MqttBrokerDTO getMqttBrokerWithDrc(String clientId, String username, Long age, Map<String, ?> map) {
if (!mqtt.containsKey(MqttUseEnum.DRC)) {
throw new RuntimeException("Please configure the drc link parameters of mqtt in the backend configuration file first.");
}
Algorithm algorithm = JwtUtil.algorithm;
String token = JwtUtil.createToken(map, age, algorithm, null, null);
return MqttBrokerDTO.builder()
.address(getMqttAddress(mqtt.get(MqttUseEnum.DRC)))
.username(username)
.clientId(clientId)
.expireTime(System.currentTimeMillis() / 1000 + age)
.password(token)
.build();
}
@Bean
public MqttConnectOptions mqttConnectOptions() {
MqttClientOptions customizeOptions = getBasicClientOptions();

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

@ -107,6 +107,11 @@ public class MqttMessageChannel { @@ -107,6 +107,11 @@ public class MqttMessageChannel {
return new DirectChannel();
}
@Bean(name = ChannelName.OUTBOUND_EVENTS)
public MessageChannel eventsOutboundChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS)
public MessageChannel eventsFlightTaskProgressChannel() {
return new DirectChannel();
@ -172,4 +177,28 @@ public class MqttMessageChannel { @@ -172,4 +177,28 @@ public class MqttMessageChannel {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_READY)
public MessageChannel eventsEventsFlightTaskReady() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_FLY_TO_POINT_PROGRESS)
public MessageChannel eventsFlyToPointProgress() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_TAKE_OFF_TO_POINT_PROGRESS)
public MessageChannel eventsTakeoffToPointProgress() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_DRC_STATUS_NOTIFY)
public MessageChannel eventsDrcStatusNotify() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_DRC_MODE_EXIT_NOTIFY)
public MessageChannel eventsDrcModeExitNotify() {
return new DirectChannel();
}
}

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

@ -1,17 +1,20 @@ @@ -1,17 +1,20 @@
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.dji.sample.component.mqtt.model.*;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
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.annotation.ServiceActivator;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.MessageHeaders;
import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;
/**
* @author sean
@ -24,6 +27,9 @@ public class EventsRouter { @@ -24,6 +27,9 @@ public class EventsRouter {
@Autowired
private ObjectMapper mapper;
@Autowired
private IMessageSenderService messageSenderService;
@Bean
public IntegrationFlow eventsMethodRouterFlow() {
return IntegrationFlows
@ -42,4 +48,21 @@ public class EventsRouter { @@ -42,4 +48,21 @@ public class EventsRouter {
methodEnum -> mapping.channelMapping(methodEnum, methodEnum.getChannelName())))
.get();
}
@ServiceActivator(inputChannel = ChannelName.OUTBOUND_EVENTS, outputChannel = ChannelName.OUTBOUND)
public void replyEventsOutbound(CommonTopicReceiver receiver, MessageHeaders headers) {
if (Optional.ofNullable(receiver).map(CommonTopicReceiver::getNeedReply).flatMap(val -> Optional.of(1 != val)).orElse(true)) {
return;
}
messageSenderService.publish(headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF,
CommonTopicResponse.builder()
.tid(receiver.getTid())
.bid(receiver.getBid())
.method(receiver.getMethod())
.timestamp(System.currentTimeMillis())
.data(RequestsReply.success())
.build());
}
}

9
src/main/java/com/dji/sample/component/mqtt/handler/ServicesReplyHandler.java

@ -36,13 +36,16 @@ public class ServicesReplyHandler { @@ -36,13 +36,16 @@ public class ServicesReplyHandler {
byte[] payload = (byte[])message.getPayload();
CommonTopicReceiver receiver = mapper.readValue(payload, new TypeReference<CommonTopicReceiver>() {});
ServiceReply reply;
if (LogsFileMethodEnum.FILE_UPLOAD_LIST.getMethod().equals(receiver.getMethod())) {
LogsFileUploadList list = mapper.convertValue(receiver.getData(), new TypeReference<LogsFileUploadList>() {});
receiver.setData(list);
reply = new ServiceReply();
reply.setResult(list.getResult());
reply.setOutput(list.getFiles());
} else {
ServiceReply reply = mapper.convertValue(receiver.getData(), new TypeReference<ServiceReply>() {});
receiver.setData(reply);
reply = mapper.convertValue(receiver.getData(), new TypeReference<ServiceReply>() {});
}
receiver.setData(reply);
Chan<CommonTopicReceiver<?>> chan = Chan.getInstance();
// Put the message to the chan object.
chan.put(receiver);

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

@ -51,6 +51,8 @@ public class ChannelName { @@ -51,6 +51,8 @@ public class ChannelName {
public static final String INBOUND_EVENTS = "inboundEvents";
public static final String OUTBOUND_EVENTS = "outboundEvents";
public static final String INBOUND_EVENTS_FLIGHT_TASK_PROGRESS = "inboundEventsFlightTaskProgress";
public static final String INBOUND_EVENTS_FILE_UPLOAD_CALLBACK = "inboundEventsFileUploadCallback";
@ -76,4 +78,14 @@ public class ChannelName { @@ -76,4 +78,14 @@ public class ChannelName {
public static final String INBOUND_REQUESTS_CONFIG = "inboundRequestsConfig";
public static final String INBOUND_EVENTS_HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA = "inboundEventsHighestPriorityUploadFlightTaskMedia";
public static final String INBOUND_EVENTS_FLIGHT_TASK_READY = "inboundEventsFlightTaskReady";
public static final String INBOUND_EVENTS_FLY_TO_POINT_PROGRESS = "inboundFlyToPointProgress";
public static final String INBOUND_EVENTS_TAKE_OFF_TO_POINT_PROGRESS = "inboundTakeoffToPointProgress";
public static final String INBOUND_EVENTS_DRC_STATUS_NOTIFY = "inboundDrcStatusNotify";
public static final String INBOUND_EVENTS_DRC_MODE_EXIT_NOTIFY = "inboundDrcModeExitNotify";
}

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

@ -45,6 +45,16 @@ public enum EventsMethodEnum { @@ -45,6 +45,16 @@ public enum EventsMethodEnum {
HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA("highest_priority_upload_flighttask_media", ChannelName.INBOUND_EVENTS_HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA),
FLIGHT_TASK_READY("flighttask_ready", ChannelName.INBOUND_EVENTS_FLIGHT_TASK_READY),
FLY_TO_POINT_PROGRESS("fly_to_point_progress", ChannelName.INBOUND_EVENTS_FLY_TO_POINT_PROGRESS),
TAKE_OFF_TO_POINT_PROGRESS("takeoff_to_point_progress", ChannelName.INBOUND_EVENTS_TAKE_OFF_TO_POINT_PROGRESS),
DRC_STATUS_NOTIFY("drc_status_notify", ChannelName.INBOUND_EVENTS_DRC_STATUS_NOTIFY),
JOYSTICK_INVALID_NOTIFY("joystick_invalid_notify", ChannelName.INBOUND_EVENTS_DRC_MODE_EXIT_NOTIFY),
UNKNOWN("Unknown", ChannelName.DEFAULT);
private String method;

4
src/main/java/com/dji/sample/component/mqtt/model/EventsOutputReceiver.java → src/main/java/com/dji/sample/component/mqtt/model/EventsOutputProgressReceiver.java

@ -8,9 +8,11 @@ import lombok.Data; @@ -8,9 +8,11 @@ import lombok.Data;
* @date 2022/7/29
*/
@Data
public class EventsOutputReceiver {
public class EventsOutputProgressReceiver<T> {
private String status;
private OutputProgressReceiver progress;
private T ext;
}

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

@ -34,4 +34,9 @@ public class TopicConst { @@ -34,4 +34,9 @@ public class TopicConst {
public static final String REGEX_SN = "[A-Za-z0-9]+";
public static final String DRC = "/drc";
public static final String UP = "/up";
public static final String DOWN = "/down";
}

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

@ -2,6 +2,7 @@ package com.dji.sample.component.mqtt.service; @@ -2,6 +2,7 @@ package com.dji.sample.component.mqtt.service;
import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.mqtt.model.ServiceReply;
import com.fasterxml.jackson.core.type.TypeReference;
/**
* @author sean.zhou
@ -26,15 +27,16 @@ public interface IMessageSenderService { @@ -26,15 +27,16 @@ public interface IMessageSenderService {
void publish(String topic, int qos, CommonTopicResponse response);
/**
* Send live streaming start message and receive a response at the same time.
* Send message and receive a response at the same time.
* @param clazz
* @param topic
* @param response notification of whether the start is successful.
* @return
*/
ServiceReply publishWithReply(String topic, CommonTopicResponse response);
<T> T publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response);
/**
* Send live streaming start message and receive a response at the same time.
* Send message and receive a response at the same time.
* @param clazz
* @param topic
* @param response
@ -43,4 +45,46 @@ public interface IMessageSenderService { @@ -43,4 +45,46 @@ public interface IMessageSenderService {
* @return
*/
<T> T publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response, int retryTime);
/**
* Used exclusively for sending messages for services.
* @param clazz The generic class for ServiceReply.
* @param sn
* @param method
* @param data
* @param bid
* @param <T>
* @return
*/
<T> ServiceReply<T> publishServicesTopic(TypeReference<T> clazz, String sn, String method, Object data, String bid);
/**
* Used exclusively for sending messages for services, and does not set the received subtype.
* @param sn
* @param method
* @param data
* @param bid
* @return
*/
ServiceReply publishServicesTopic(String sn, String method, Object data, String bid);
/**
* Used exclusively for sending messages for services.
* @param clazz The generic class for ServiceReply.
* @param sn
* @param method
* @param data
* @param <T>
* @return
*/
<T> ServiceReply<T> publishServicesTopic(TypeReference<T> clazz, String sn, String method, Object data);
/**
* Used exclusively for sending messages for services, and does not set the received subtype.
* @param sn
* @param method
* @param data
* @return
*/
ServiceReply publishServicesTopic(String sn, String method, Object data);
}

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

@ -1,17 +1,19 @@ @@ -1,17 +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.model.*;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.component.mqtt.service.IMqttMessageGateway;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -30,17 +32,12 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -30,17 +32,12 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
private ObjectMapper mapper;
public void publish(String topic, CommonTopicResponse response) {
try {
log.info("send topic: {}, payload: {}", topic, response.toString());
messageGateway.publish(topic, mapper.writeValueAsBytes(response));
} catch (JsonProcessingException e) {
log.info("Failed to publish the message. {}", response.toString());
e.printStackTrace();
}
this.publish(topic, 1, response);
}
public void publish(String topic, int qos, CommonTopicResponse response) {
try {
log.info("send topic: {}, payload: {}", topic, response.toString());
messageGateway.publish(topic, mapper.writeValueAsBytes(response), qos);
} catch (JsonProcessingException e) {
log.info("Failed to publish the message. {}", response.toString());
@ -48,12 +45,11 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -48,12 +45,11 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
}
}
public ServiceReply publishWithReply(String topic, CommonTopicResponse response) {
return this.publishWithReply(ServiceReply.class, topic, response, 2);
public <T> T publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response) {
return this.publishWithReply(clazz, topic, response, 2);
}
public <T> T publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response, int retryTime) {
log.info("send topic: {}, payload: {}", topic, response.toString());
AtomicInteger time = new AtomicInteger(0);
// Retry three times
while (time.getAndIncrement() <= retryTime) {
@ -62,15 +58,59 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -62,15 +58,59 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
Chan<CommonTopicReceiver<T>> chan = Chan.getInstance();
// If the message is not received in 0.5 seconds then resend it again.
CommonTopicReceiver<T> receiver = chan.get(response.getTid());
if (receiver == null) {
continue;
}
// Need to match tid and bid.
if (receiver.getTid().equals(response.getTid()) &&
if (Objects.nonNull(receiver) && receiver.getTid().equals(response.getTid()) &&
receiver.getBid().equals(response.getBid())) {
return receiver.getData();
if (clazz.isAssignableFrom(receiver.getData().getClass())) {
return receiver.getData();
}
throw new TypeMismatchException(receiver.getData(), clazz);
}
// It must be guaranteed that the tid and bid of each message are different.
response.setBid(UUID.randomUUID().toString());
response.setTid(UUID.randomUUID().toString());
}
throw new RuntimeException("No message reply received.");
}
@Override
public <T> ServiceReply<T> publishServicesTopic(TypeReference<T> clazz, String sn, String method, Object data, String bid) {
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + sn + TopicConst.SERVICES_SUF;
ServiceReply reply = this.publishWithReply(ServiceReply.class, topic,
CommonTopicResponse.builder()
.tid(UUID.randomUUID().toString())
.bid(StringUtils.hasText(bid) ? bid : UUID.randomUUID().toString())
.timestamp(System.currentTimeMillis())
.method(method)
.data(Objects.requireNonNullElse(data, ""))
.build());
if (Objects.isNull(clazz)) {
return reply;
}
// put together in "output"
if (Objects.nonNull(reply.getInfo())) {
reply.setOutput(mapper.convertValue(reply.getInfo(), clazz));
}
if (Objects.nonNull(reply.getOutput())) {
reply.setOutput(mapper.convertValue(reply.getOutput(), clazz));
}
return reply;
}
@Override
public ServiceReply publishServicesTopic(String sn, String method, Object data, String bid) {
return this.publishServicesTopic(null, sn, method, data, bid);
}
@Override
public <T> ServiceReply<T> publishServicesTopic(TypeReference<T> clazz, String sn, String method, Object data) {
return this.publishServicesTopic(clazz, sn, method, data, null);
}
@Override
public ServiceReply publishServicesTopic(String sn, String method, Object data) {
return this.publishServicesTopic(null, sn, method, data, null);
}
}

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

@ -39,6 +39,10 @@ public final class RedisConst { @@ -39,6 +39,10 @@ public final class RedisConst {
public static final String WAYLINE_JOB_TIMED_EXECUTE = "wayline_job_timed_execute";
public static final String WAYLINE_JOB_CONDITION_PREPARE = "wayline_job_condition_prepare";
public static final String WAYLINE_JOB_CONDITION_PREFIX = WAYLINE_JOB_CONDITION_PREPARE + DELIMITER;
public static final String WAYLINE_JOB_BLOCK_PREFIX = "wayline_job_block" + DELIMITER;
public static final String WAYLINE_JOB_RUNNING_PREFIX = "wayline_job_running" + DELIMITER;
@ -53,7 +57,13 @@ public final class RedisConst { @@ -53,7 +57,13 @@ public final class RedisConst {
public static final String LIVE_CAPACITY = "live_capacity";
public static final String DRC_PREFIX = "drc" + DELIMITER;
public static final Integer DRC_MODE_ALIVE_SECOND = 3600;
public static final String MQTT_ACL_PREFIX = "mqtt_acl" + DELIMITER;
public static final String FILE_UPLOADING_PREFIX = "file_uploading" + DELIMITER;
}
public static final String DRONE_CONTROL_PREFiX = "control_source" + DELIMITER;
}

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

@ -57,7 +57,22 @@ public enum BizCodeEnum { @@ -57,7 +57,22 @@ public enum BizCodeEnum {
FILE_UPLOAD_CALLBACK("file_upload_callback"),
HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA("HIGHEST_PRIORITY_UPLOAD_FLIGHTTASK_MEDIA");
FILE_UPLOAD_PROGRESS("fileupload_progress"),
OTA_PROGRESS("ota_progress"),
HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA("highest_priority_upload_flighttask_media"),
CONTROL_SOURCE_CHANGE("control_source_change"),
FLY_TO_POINT_PROGRESS("fly_to_point_progress"),
TAKE_OFF_TO_POINT_PROGRESS("takeoff_to_point_progress"),
DRC_STATUS_NOTIFY("drc_status_notify"),
JOYSTICK_INVALID_NOTIFY("joystick_invalid_notify")
;
private String code;

4
src/main/java/com/dji/sample/component/websocket/service/ISendMessageService.java

@ -25,4 +25,8 @@ public interface ISendMessageService { @@ -25,4 +25,8 @@ public interface ISendMessageService {
* @param message message
*/
void sendBatch(Collection<ConcurrentWebSocketSession> sessions, CustomWebSocketMessage message);
void sendBatch(String workspaceId, Integer userType, String bizCode, Object data);
void sendBatch(String workspaceId, String bizCode, Object data);
}

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

@ -3,14 +3,17 @@ package com.dji.sample.component.websocket.service.impl; @@ -3,14 +3,17 @@ package com.dji.sample.component.websocket.service.impl;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
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.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.TextMessage;
import java.io.IOException;
import java.util.Collection;
import java.util.Objects;
/**
* @author sean.zhou
@ -24,6 +27,9 @@ public class SendMessageServiceImpl implements ISendMessageService { @@ -24,6 +27,9 @@ public class SendMessageServiceImpl implements ISendMessageService {
@Autowired
private ObjectMapper mapper;
@Autowired
private IWebSocketManageService webSocketManageService;
@Override
public void sendMessage(ConcurrentWebSocketSession session, CustomWebSocketMessage message) {
if (session == null) {
@ -70,4 +76,25 @@ public class SendMessageServiceImpl implements ISendMessageService { @@ -70,4 +76,25 @@ public class SendMessageServiceImpl implements ISendMessageService {
e.printStackTrace();
}
}
@Override
public void sendBatch(String workspaceId, Integer userType, String bizCode, Object data) {
if (!StringUtils.hasText(workspaceId)) {
throw new RuntimeException("Workspace ID does not exist.");
}
Collection<ConcurrentWebSocketSession> sessions = Objects.isNull(userType) ?
webSocketManageService.getValueWithWorkspace(workspaceId) :
webSocketManageService.getValueWithWorkspaceAndUserType(workspaceId, userType);
this.sendBatch(sessions, CustomWebSocketMessage.builder()
.data(data)
.timestamp(System.currentTimeMillis())
.bizCode(bizCode)
.build());
}
@Override
public void sendBatch(String workspaceId, String bizCode, Object data) {
this.sendBatch(workspaceId, null, bizCode, data);
}
}

40
src/main/java/com/dji/sample/control/controller/DockController.java

@ -1,12 +1,15 @@ @@ -1,12 +1,15 @@
package com.dji.sample.control.controller;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.control.model.param.RemoteDebugParam;
import com.dji.sample.control.model.enums.DroneAuthorityEnum;
import com.dji.sample.control.model.param.*;
import com.dji.sample.control.service.IControlService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* @author sean
* @version 1.2
@ -24,6 +27,39 @@ public class DockController { @@ -24,6 +27,39 @@ public class DockController {
public ResponseResult createControlJob(@PathVariable String sn,
@PathVariable("service_identifier") String serviceIdentifier,
@RequestBody(required = false) RemoteDebugParam param) {
return controlService.controlDock(sn, serviceIdentifier, param);
return controlService.controlDockDebug(sn, serviceIdentifier, param);
}
@PostMapping("/{sn}/jobs/fly-to-point")
public ResponseResult flyToPoint(@PathVariable String sn, @Valid @RequestBody FlyToPointParam param) {
return controlService.flyToPoint(sn, param);
}
@DeleteMapping("/{sn}/jobs/fly-to-point")
public ResponseResult flyToPointStop(@PathVariable String sn) {
return controlService.flyToPointStop(sn);
}
@PostMapping("/{sn}/jobs/takeoff-to-point")
public ResponseResult takeoffToPoint(@PathVariable String sn, @Valid @RequestBody TakeoffToPointParam param) {
return controlService.takeoffToPoint(sn, param);
}
@PostMapping("/{sn}/authority/flight")
public ResponseResult seizeFlightAuthority(@PathVariable String sn) {
return controlService.seizeAuthority(sn, DroneAuthorityEnum.FLIGHT, null);
}
@PostMapping("/{sn}/authority/payload")
public ResponseResult seizePayloadAuthority(@PathVariable String sn, @Valid @RequestBody DronePayloadParam param) {
return controlService.seizeAuthority(sn, DroneAuthorityEnum.PAYLOAD, param);
}
@PostMapping("/{sn}/payload/commands")
public ResponseResult payloadCommands(@PathVariable String sn, @Valid @RequestBody PayloadCommandsParam param) throws Exception {
param.setSn(sn);
return controlService.payloadCommands(param);
}
}

55
src/main/java/com/dji/sample/control/controller/DrcController.java

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
package com.dji.sample.control.controller;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.control.model.dto.JwtAclDTO;
import com.dji.sample.control.model.dto.MqttBrokerDTO;
import com.dji.sample.control.model.param.DrcConnectParam;
import com.dji.sample.control.model.param.DrcModeParam;
import com.dji.sample.control.service.IDrcService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
@RestController
@Slf4j
@RequestMapping("${url.control.prefix}${url.control.version}")
public class DrcController {
@Autowired
private IDrcService drcService;
@PostMapping("/workspaces/{workspace_id}/drc/connect")
public ResponseResult drcConnect(@PathVariable("workspace_id") String workspaceId, HttpServletRequest request, @Valid @RequestBody DrcConnectParam param) {
CustomClaim claims = (CustomClaim) request.getAttribute(TOKEN_CLAIM);
MqttBrokerDTO brokerDTO = drcService.userDrcAuth(workspaceId, claims.getId(), claims.getUsername(), param);
return ResponseResult.success(brokerDTO);
}
@PostMapping("/workspaces/{workspace_id}/drc/enter")
public ResponseResult drcEnter(@PathVariable("workspace_id") String workspaceId, @Valid @RequestBody DrcModeParam param) {
JwtAclDTO acl = drcService.deviceDrcEnter(workspaceId, param);
return ResponseResult.success(acl);
}
@PostMapping("/workspaces/{workspace_id}/drc/exit")
public ResponseResult drcExit(@PathVariable("workspace_id") String workspaceId, @Valid @RequestBody DrcModeParam param) {
drcService.deviceDrcExit(workspaceId, param);
return ResponseResult.success();
}
}

4
src/main/java/com/dji/sample/control/model/dto/AlarmState.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.service.impl.RemoteDebugHandler;
import com.dji.sample.manage.model.enums.StateSwitchEnum;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -18,7 +18,7 @@ import java.util.Objects; @@ -18,7 +18,7 @@ import java.util.Objects;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AlarmState extends BasicDeviceProperty {
public class AlarmState extends RemoteDebugHandler {
private Integer action;

4
src/main/java/com/dji/sample/control/model/dto/BatteryStoreMode.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.model.enums.BatteryStoreModeEnum;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import com.dji.sample.control.service.impl.RemoteDebugHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -18,7 +18,7 @@ import java.util.Objects; @@ -18,7 +18,7 @@ import java.util.Objects;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BatteryStoreMode extends BasicDeviceProperty {
public class BatteryStoreMode extends RemoteDebugHandler {
private Integer action;

32
src/main/java/com/dji/sample/control/model/dto/DrcModeDTO.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package com.dji.sample.control.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.3
* @date 2023/1/12
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DrcModeDTO {
private MqttBrokerDTO mqttBroker;
/**
* range: 1 - 30
*/
@Builder.Default
private Integer osdFrequency = 10;
/**
* range: 1 - 30
*/
@Builder.Default
private Integer hsiFrequency = 1;
}

15
src/main/java/com/dji/sample/control/model/dto/DrcModeReasonReceiver.java

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.model.enums.DrcModeReasonEnum;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/14
*/
@Data
public class DrcModeReasonReceiver {
private DrcModeReasonEnum reason;
}

18
src/main/java/com/dji/sample/control/model/dto/DrcStatusNotifyReceiver.java

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.model.enums.DrcStatusErrorEnum;
import com.dji.sample.manage.model.enums.DockDrcStateEnum;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/17
*/
@Data
public class DrcStatusNotifyReceiver {
private DrcStatusErrorEnum result;
private DockDrcStateEnum drcState;
}

22
src/main/java/com/dji/sample/control/model/dto/FlyToProgressReceiver.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.model.enums.FlyToStatusEnum;
import com.dji.sample.wayline.model.enums.WaylineErrorCodeEnum;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/14
*/
@Data
public class FlyToProgressReceiver {
private WaylineErrorCodeEnum result;
private FlyToStatusEnum status;
private String flyToId;
private Integer wayPointIndex;
}

26
src/main/java/com/dji/sample/control/model/dto/JwtAclDTO.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.control.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author sean
* @version 1.3
* @date 2023/1/12
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JwtAclDTO {
private List<String> sub;
private List<String> pub;
private List<String> all;
}

4
src/main/java/com/dji/sample/control/model/dto/LinkWorkMode.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.model.enums.LinkWorkModeEnum;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import com.dji.sample.control.service.impl.RemoteDebugHandler;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -19,7 +19,7 @@ import java.util.Objects; @@ -19,7 +19,7 @@ import java.util.Objects;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LinkWorkMode extends BasicDeviceProperty {
public class LinkWorkMode extends RemoteDebugHandler {
@JsonProperty("link_workmode")
private Integer linkWorkMode;

31
src/main/java/com/dji/sample/control/model/dto/MqttBrokerDTO.java

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
package com.dji.sample.control.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MqttBrokerDTO {
private String address;
private String username;
private String password;
private String clientId;
private Long expireTime;
@Builder.Default
private Boolean enableTls = false;
}

31
src/main/java/com/dji/sample/control/model/dto/PointDTO.java

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
package com.dji.sample.control.model.dto;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
/**
* @author sean
* @version 1.3
* @date 2023/2/14
*/
@Data
public class PointDTO {
@Range(min = -90, max = 90)
@NotNull
private Double latitude;
@NotNull
@Range(min = -180, max = 180)
private Double longitude;
/**
* WGS84
* The M30 series are ellipsoidal heights.
*/
@NotNull
@Range(min = 2, max = 1500)
private Double height;
}

25
src/main/java/com/dji/sample/control/model/dto/RemoteDebugOpenState.java

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.common.util.SpringBeanUtils;
import com.dji.sample.control.service.impl.RemoteDebugHandler;
import com.dji.sample.manage.model.enums.DockModeCodeEnum;
import com.dji.sample.manage.service.IDeviceService;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author sean
* @version 1.4
* @date 2023/4/14
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class RemoteDebugOpenState extends RemoteDebugHandler {
@Override
public boolean canPublish(String sn) {
IDeviceService deviceService = SpringBeanUtils.getBean(IDeviceService.class);
DockModeCodeEnum dockMode = deviceService.getDockMode(sn);
return DockModeCodeEnum.IDLE == dockMode;
}
}

24
src/main/java/com/dji/sample/control/model/dto/ResultNotifyDTO.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package com.dji.sample.control.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.4
* @date 2023/3/1
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ResultNotifyDTO {
private Integer result;
private String message;
private String sn;
}

27
src/main/java/com/dji/sample/control/model/dto/ReturnHomeState.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.common.util.SpringBeanUtils;
import com.dji.sample.control.service.impl.RemoteDebugHandler;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver;
import com.dji.sample.manage.service.IDeviceRedisService;
/**
* @author sean
* @version 1.4
* @date 2023/4/19
*/
public class ReturnHomeState extends RemoteDebugHandler {
@Override
public boolean canPublish(String sn) {
IDeviceRedisService deviceRedisService = SpringBeanUtils.getBean(IDeviceRedisService.class);
return deviceRedisService.getDeviceOnline(sn)
.map(DeviceDTO::getChildDeviceSn)
.flatMap(deviceSn -> deviceRedisService.getDeviceOsd(deviceSn, OsdSubDeviceReceiver.class))
.map(OsdSubDeviceReceiver::getElevation)
.map(elevation -> elevation > 0)
.orElse(false);
}
}

25
src/main/java/com/dji/sample/control/model/dto/TakeoffProgressReceiver.java

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
package com.dji.sample.control.model.dto;
import com.dji.sample.control.model.enums.TakeoffStatusEnum;
import com.dji.sample.wayline.model.enums.WaylineErrorCodeEnum;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/14
*/
@Data
public class TakeoffProgressReceiver {
private WaylineErrorCodeEnum result;
private TakeoffStatusEnum status;
private String flightId;
private String trackId;
private Integer wayPointIndex;
}

26
src/main/java/com/dji/sample/control/model/enums/CameraModeEnum.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/3
*/
public enum CameraModeEnum {
PHOTO, VIDEO;
@JsonValue
public int getVal() {
return ordinal();
}
@JsonCreator
public static CameraModeEnum find(int val) {
return Arrays.stream(values()).filter(modeEnum -> modeEnum.ordinal() == val).findAny().get();
}
}

26
src/main/java/com/dji/sample/control/model/enums/CameraStateEnum.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public enum CameraStateEnum {
IDLE, WORKING;
@JsonValue
public int getVal() {
return ordinal();
}
@JsonCreator
public static CameraStateEnum find(int val) {
return Arrays.stream(values()).filter(stateEnum -> stateEnum.ordinal() == val).findAny().get();
}
}

38
src/main/java/com/dji/sample/control/model/enums/CameraTypeEnum.java

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/3
*/
@Getter
public enum CameraTypeEnum {
ZOOM("zoom"),
WIDE("wide"),
IR("ir");
String type;
CameraTypeEnum(String type) {
this.type = type;
}
@JsonValue
public String getType() {
return type;
}
@JsonCreator
public static CameraTypeEnum find(String cameraType) {
return Arrays.stream(CameraTypeEnum.values()).filter(typeEnum -> typeEnum.type.equals(cameraType)).findAny().get();
}
}

22
src/main/java/com/dji/sample/control/model/enums/DrcMethodEnum.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package com.dji.sample.control.model.enums;
import lombok.Getter;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
@Getter
public enum DrcMethodEnum {
DRC_MODE_ENTER("drc_mode_enter"),
DRC_MODE_EXIT("drc_mode_exit");
String method;
DrcMethodEnum(String method) {
this.method = method;
}
}

47
src/main/java/com/dji/sample/control/model/enums/DrcModeReasonEnum.java

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/14
*/
public enum DrcModeReasonEnum {
UNKNOWN(-1, "unknown"),
RC_LOST(0, "The remote controller is lost."),
BATTERY_LOW_GO_HOME(1, "Due to low battery, the drone automatically returned home."),
BATTERY_SUPER_LOW_LANDING(2, "Due to the serious low battery, the drone landed automatically."),
NEAR_BOUNDARY(3, "The drone is near a not-fly zone."),
RC_AUTHORITY(4, "The remote controller grabs control authority.");
int val;
String message;
DrcModeReasonEnum(int val, String message) {
this.val = val;
this.message = message;
}
public int getVal() {
return val;
}
public String getMessage() {
return message;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static DrcModeReasonEnum find(int val) {
return Arrays.stream(values()).filter(reasonEnum -> reasonEnum.val == val).findAny().orElse(UNKNOWN);
}
}

52
src/main/java/com/dji/sample/control/model/enums/DrcStatusErrorEnum.java

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
package com.dji.sample.control.model.enums;
import com.dji.sample.common.error.IErrorInfo;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/17
*/
public enum DrcStatusErrorEnum implements IErrorInfo {
SUCCESS(0, "success"),
MQTT_ERR(514300, "The mqtt connection error."),
HEARTBEAT_TIMEOUT(514301, "The heartbeat times out and the dock disconnects."),
MQTT_CERTIFICATE_ERR(514302, "The mqtt certificate is abnormal and the connection fails."),
MQTT_LOST(514303, "The dock network is abnormal and the mqtt connection is lost."),
MQTT_REFUSE(514304, "The dock connection to mqtt server was refused."),
UNKNOWN(-1, "Unknown");
String msg;
int code;
DrcStatusErrorEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public String getErrorMsg() {
return msg;
}
@Override
public Integer getErrorCode() {
return code;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static DrcStatusErrorEnum find(int code) {
return Arrays.stream(values()).filter(error -> error.code == code).findAny().orElse(UNKNOWN);
}
}

25
src/main/java/com/dji/sample/control/model/enums/DroneAuthorityEnum.java

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* @author sean
* @version 1.4
* @date 2023/3/1
*/
public enum DroneAuthorityEnum {
FLIGHT(1), PAYLOAD(2);
int val;
DroneAuthorityEnum(int val) {
this.val = val;
}
@JsonValue
public int getVal() {
return val;
}
}

28
src/main/java/com/dji/sample/control/model/enums/DroneControlMethodEnum.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package com.dji.sample.control.model.enums;
import lombok.Getter;
/**
* @author sean
* @version 1.3
* @date 2023/2/21
*/
@Getter
public enum DroneControlMethodEnum {
FLIGHT_AUTHORITY_GRAB("flight_authority_grab"),
PAYLOAD_AUTHORITY_GRAB("payload_authority_grab"),
FLY_TO_POINT("fly_to_point"),
FLY_TO_POINT_STOP("fly_to_point_stop"),
TAKE_OFF_TO_POINT("takeoff_to_point");
String method;
DroneControlMethodEnum(String method) {
this.method = method;
}
}

39
src/main/java/com/dji/sample/control/model/enums/FlyToStatusEnum.java

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/14
*/
public enum FlyToStatusEnum {
WAYLINE_PROGRESS("wayline_progress", "The FlyTo job is in progress."),
WAYLINE_FAILED("wayline_failed", "The Fly To task execution failed."),
WAYLINE_OK("wayline_ok", "The FlyTo job executed successfully."),
WAYLINE_CANCEL("wayline_cancel", "The FlyTo job is closed.");
String status;
String message;
FlyToStatusEnum(String status, String message) {
this.status = status;
this.message = message;
}
public String getMessage() {
return message;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static FlyToStatusEnum find(String status) {
return Arrays.stream(values()).filter(statusEnum -> statusEnum.status.equals(status)).findAny().get();
}
}

26
src/main/java/com/dji/sample/control/model/enums/GimbalResetModeEnum.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/13
*/
public enum GimbalResetModeEnum {
RECENTER, DOWN, RECENTER_PAN, PITCH_DOWN;
@JsonValue
public int getVal() {
return ordinal();
}
@JsonCreator
public static GimbalResetModeEnum find(int value) {
return Arrays.stream(values()).filter(resetModeEnum -> resetModeEnum.ordinal() == value).findAny().get();
}
}

24
src/main/java/com/dji/sample/control/model/enums/MqttAclAccessEnum.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package com.dji.sample.control.model.enums;
import lombok.Getter;
/**
* @author sean
* @version 1.3
* @date 2023/1/13
*/
@Getter
public enum MqttAclAccessEnum {
SUB(1),
PUB(2),
ALL(3);
int value;
MqttAclAccessEnum(int value) {
this.value = value;
}
}

52
src/main/java/com/dji/sample/control/model/enums/PayloadCommandsEnum.java

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
package com.dji.sample.control.model.enums;
import com.dji.sample.control.service.impl.*;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/2
*/
public enum PayloadCommandsEnum {
CAMERA_MODE_SWitCH("camera_mode_switch", CameraModeSwitchImpl.class),
CAMERA_PHOTO_TAKE("camera_photo_take", CameraPhotoTakeImpl.class),
CAMERA_RECORDING_START("camera_recording_start", CameraRecordingStartImpl.class),
CAMERA_RECORDING_STOP("camera_recording_stop", CameraRecordingStopImpl.class),
CAMERA_AIM("camera_aim", CameraAimImpl.class),
CAMERA_FOCAL_LENGTH_SET("camera_focal_length_set", CameraFocalLengthSetImpl.class),
GIMBAL_RESET("gimbal_reset", GimbalResetImpl.class);
String cmd;
Class<? extends PayloadCommandsHandler> clazz;
PayloadCommandsEnum(String cmd, Class<? extends PayloadCommandsHandler> clazz) {
this.cmd = cmd;
this.clazz = clazz;
}
@JsonValue
public String getCmd() {
return cmd;
}
public Class<? extends PayloadCommandsHandler> getClazz() {
return clazz;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static PayloadCommandsEnum find(String cmd) {
return Arrays.stream(values()).filter(cmdEnum -> cmdEnum.cmd.equals(cmd)).findAny().get();
}
}

20
src/main/java/com/dji/sample/control/model/enums/RemoteControlMethodEnum.java → src/main/java/com/dji/sample/control/model/enums/RemoteDebugMethodEnum.java

@ -1,9 +1,7 @@ @@ -1,9 +1,7 @@
package com.dji.sample.control.model.enums;
import com.dji.sample.control.model.dto.AlarmState;
import com.dji.sample.control.model.dto.BatteryStoreMode;
import com.dji.sample.control.model.dto.LinkWorkMode;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import com.dji.sample.control.model.dto.*;
import com.dji.sample.control.service.impl.RemoteDebugHandler;
import lombok.Getter;
import java.util.Arrays;
@ -14,9 +12,9 @@ import java.util.Arrays; @@ -14,9 +12,9 @@ import java.util.Arrays;
* @date 2022/11/14
*/
@Getter
public enum RemoteControlMethodEnum {
public enum RemoteDebugMethodEnum {
DEBUG_MODE_OPEN("debug_mode_open", false, null),
DEBUG_MODE_OPEN("debug_mode_open", false, RemoteDebugOpenState.class),
DEBUG_MODE_CLOSE("debug_mode_close", false, null),
@ -24,7 +22,7 @@ public enum RemoteControlMethodEnum { @@ -24,7 +22,7 @@ public enum RemoteControlMethodEnum {
SUPPLEMENT_LIGHT_CLOSE("supplement_light_close", false, null),
RETURN_HOME("return_home", false, null),
RETURN_HOME("return_home", false, ReturnHomeState.class),
DEVICE_REBOOT("device_reboot", true, null),
@ -64,16 +62,16 @@ public enum RemoteControlMethodEnum { @@ -64,16 +62,16 @@ public enum RemoteControlMethodEnum {
private Boolean progress;
private Class<? extends BasicDeviceProperty> clazz;
private Class<? extends RemoteDebugHandler> clazz;
RemoteControlMethodEnum(String method, Boolean progress, Class<? extends BasicDeviceProperty> clazz) {
RemoteDebugMethodEnum(String method, Boolean progress, Class<? extends RemoteDebugHandler> clazz) {
this.method = method;
this.progress = progress;
this.clazz = clazz;
}
public static RemoteControlMethodEnum find(String method) {
return Arrays.stream(RemoteControlMethodEnum.values())
public static RemoteDebugMethodEnum find(String method) {
return Arrays.stream(RemoteDebugMethodEnum.values())
.filter(methodEnum -> methodEnum.method.equals(method))
.findAny()
.orElse(UNKNOWN);

47
src/main/java/com/dji/sample/control/model/enums/TakeoffStatusEnum.java

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
package com.dji.sample.control.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/17
*/
public enum TakeoffStatusEnum {
TASK_READY("task_ready", "The drone is preparing to take off."),
WAYLINE_PROGRESS("wayline_progress", "The drone is taking off."),
WAYLINE_FAILED("wayline_failed", "The drone failed to take off."),
WAYLINE_OK("wayline_ok", "The drone took off successfully."),
WAYLINE_CANCEL("wayline_cancel", "The drone takeoff job has been cancelled."),
TASK_FINISH("task_finish", "The drone takeoff job is completed.");
String status;
String message;
TakeoffStatusEnum(String status, String message) {
this.status = status;
this.message = message;
}
public String getStatus() {
return status;
}
public String getMessage() {
return message;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static TakeoffStatusEnum find(String status) {
return Arrays.stream(values()).filter(statusEnum -> statusEnum.status.equals(status)).findAny().get();
}
}

19
src/main/java/com/dji/sample/control/model/param/DeviceDrcInfoParam.java

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
package com.dji.sample.control.model.param;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
/**
* @author sean
* @version 1.3
* @date 2023/2/2
*/
@Data
public class DeviceDrcInfoParam {
@Range(min = 1, max = 30)
private Integer osdFrequency = 10;
@Range(min = 1, max = 30)
private Integer hsiFrequency = 1;
}

19
src/main/java/com/dji/sample/control/model/param/DrcConnectParam.java

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
package com.dji.sample.control.model.param;
import com.dji.sample.component.redis.RedisConst;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
@Data
public class DrcConnectParam {
private String clientId;
@Range(min = 1800, max = 86400)
private long expireSec = RedisConst.DRC_MODE_ALIVE_SECOND;
}

35
src/main/java/com/dji/sample/control/model/param/DrcModeParam.java

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
package com.dji.sample.control.model.param;
import com.dji.sample.component.redis.RedisConst;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Range;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DrcModeParam {
@NotBlank
private String clientId;
@NotBlank
private String dockSn;
@Range(min = 1800, max = 86400)
private long expireSec = RedisConst.DRC_MODE_ALIVE_SECOND;
@Valid
private DeviceDrcInfoParam deviceInfo = new DeviceDrcInfoParam();
}

54
src/main/java/com/dji/sample/control/model/param/DronePayloadParam.java

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
package com.dji.sample.control.model.param;
import com.dji.sample.control.model.enums.CameraModeEnum;
import com.dji.sample.control.model.enums.CameraTypeEnum;
import com.dji.sample.control.model.enums.GimbalResetModeEnum;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
/**
* @author sean
* @version 1.4
* @date 2023/3/1
*/
@Data
public class DronePayloadParam {
@Pattern(regexp = "\\d+-\\d+-\\d+")
@NotNull
private String payloadIndex;
private CameraTypeEnum cameraType;
@Range(min = 2, max = 200)
private Float zoomFactor;
private CameraModeEnum cameraMode;
/**
* true: Lock the gimbal, the gimbal and the drone rotate together.
* false: Only the gimbal rotates, but the drone does not.
*/
private Boolean locked;
private Double pitchSpeed;
/**
* Only valid when locked is false.
*/
private Double yawSpeed;
/**
* upper left corner as center point
*/
@Range(min = 0, max = 1)
private Double x;
@Range(min = 0, max = 1)
private Double y;
private GimbalResetModeEnum resetMode;
}

37
src/main/java/com/dji/sample/control/model/param/FlyToPointParam.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
package com.dji.sample.control.model.param;
import com.dji.sample.control.model.dto.PointDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Range;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
/**
* @author sean
* @version 1.3
* @date 2023/2/14
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FlyToPointParam {
private String flyToId;
@Range(min = 1, max = 15)
@NotNull
private Integer maxSpeed;
/**
* The M30 series only support one point.
*/
@Size(min = 1)
@Valid
@NotNull
private List<PointDTO> points;
}

27
src/main/java/com/dji/sample/control/model/param/PayloadCommandsParam.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
package com.dji.sample.control.model.param;
import com.dji.sample.control.model.enums.PayloadCommandsEnum;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
/**
* @author sean
* @version 1.4
* @date 2023/3/2
*/
@Data
public class PayloadCommandsParam {
private String sn;
@NotNull
@Valid
private PayloadCommandsEnum cmd;
@Valid
@NotNull
private DronePayloadParam data;
}

49
src/main/java/com/dji/sample/control/model/param/TakeoffToPointParam.java

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
package com.dji.sample.control.model.param;
import com.dji.sample.manage.model.enums.DroneRcLostActionEnum;
import com.dji.sample.manage.model.enums.WaylineRcLostActionEnum;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
/**
* @author sean
* @version 1.4
* @date 2023/3/1
*/
@Data
public class TakeoffToPointParam {
private String flightId;
@Range(min = -180, max = 180)
@NotNull
private Double targetLongitude;
@Range(min = -90, max = 90)
@NotNull
private Double targetLatitude;
@Range(min = 2, max = 1500)
@NotNull
private Double targetHeight;
@Range(min = 2, max = 1500)
@NotNull
private Double securityTakeoffHeight;
@Range(min = 2, max = 1500)
@NotNull
private Double rthAltitude;
@NotNull
private DroneRcLostActionEnum rcLostAction;
@NotNull
private WaylineRcLostActionEnum exitWaylineWhenRcLost;
@Range(min = 1, max = 15)
@NotNull
private Double maxSpeed;
}

56
src/main/java/com/dji/sample/control/service/IControlService.java

@ -2,7 +2,8 @@ package com.dji.sample.control.service; @@ -2,7 +2,8 @@ package com.dji.sample.control.service;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.control.model.param.RemoteDebugParam;
import com.dji.sample.control.model.enums.DroneAuthorityEnum;
import com.dji.sample.control.model.param.*;
import org.springframework.messaging.MessageHeaders;
/**
@ -19,13 +20,60 @@ public interface IControlService { @@ -19,13 +20,60 @@ public interface IControlService {
* @param param
* @return
*/
ResponseResult controlDock(String sn, String serviceIdentifier, RemoteDebugParam param);
ResponseResult controlDockDebug(String sn, String serviceIdentifier, RemoteDebugParam param);
/**
* Handles multi-state command progress information.
* Make the drone fly to the target point.
* @param sn
* @param param
* @return
*/
ResponseResult flyToPoint(String sn, FlyToPointParam param);
/**
* End the mission of flying the drone to the target point.
* @param sn
* @return
*/
ResponseResult flyToPointStop(String sn);
/**
* Handle progress result notifications for fly to target point.
* @param receiver
* @param headers
* @return
*/
CommonTopicReceiver handleFlyToPointProgress(CommonTopicReceiver receiver, MessageHeaders headers);
/**
* Control the drone to take off.
* @param sn
* @param param
* @return
*/
ResponseResult takeoffToPoint(String sn, TakeoffToPointParam param);
/**
* Handle progress result notifications for takeoff to target point.
* @param receiver
* @param headers
* @return
*/
void handleControlProgress(CommonTopicReceiver receiver, MessageHeaders headers);
CommonTopicReceiver handleTakeoffToPointProgress(CommonTopicReceiver receiver, MessageHeaders headers);
/**
* Seize the control authority of the drone or the payload control authority.
* @param sn
* @param authority
* @param param
* @return
*/
ResponseResult seizeAuthority(String sn, DroneAuthorityEnum authority, DronePayloadParam param);
/**
* Control the payload of the drone.
* @param param
* @return
*/
ResponseResult payloadCommands(PayloadCommandsParam param) throws Exception;
}

60
src/main/java/com/dji/sample/control/service/IDrcService.java

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
package com.dji.sample.control.service;
import com.dji.sample.control.model.dto.JwtAclDTO;
import com.dji.sample.control.model.dto.MqttBrokerDTO;
import com.dji.sample.control.model.param.DrcConnectParam;
import com.dji.sample.control.model.param.DrcModeParam;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
public interface IDrcService {
/**
* Save the drc mode of dock in redis.
* @param dockSn
* @param clientId
*/
void setDrcModeInRedis(String dockSn, String clientId);
/**
* Query the client that is controlling the dock.
* @param dockSn
* @return clientId
*/
String getDrcModeInRedis(String dockSn);
/**
* Delete the drc mode of dock in redis.
* @param dockSn
* @return
*/
Boolean delDrcModeInRedis(String dockSn);
/**
* Provide mqtt options for the control terminal.
* @param workspaceId
* @param userId
* @param username
* @param param
* @return
*/
MqttBrokerDTO userDrcAuth(String workspaceId, String userId, String username, DrcConnectParam param);
/**
* Make the dock enter drc mode. And grant relevant permissions.
* @param workspaceId
* @param param
* @return
*/
JwtAclDTO deviceDrcEnter(String workspaceId, DrcModeParam param);
/**
* Make the dock exit drc mode.
* @param workspaceId
* @param param
*/
void deviceDrcExit(String workspaceId, DrcModeParam param);
}

24
src/main/java/com/dji/sample/control/service/impl/CameraAimImpl.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.param.DronePayloadParam;
import java.util.Objects;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class CameraAimImpl extends PayloadCommandsHandler {
public CameraAimImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean valid() {
return Objects.nonNull(param.getX()) && Objects.nonNull(param.getY())
&& Objects.nonNull(param.getLocked()) && Objects.nonNull(param.getCameraType());
}
}

41
src/main/java/com/dji/sample/control/service/impl/CameraFocalLengthSetImpl.java

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.enums.CameraStateEnum;
import com.dji.sample.control.model.enums.CameraTypeEnum;
import com.dji.sample.control.model.param.DronePayloadParam;
import java.util.Objects;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class CameraFocalLengthSetImpl extends PayloadCommandsHandler {
public CameraFocalLengthSetImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean valid() {
return Objects.nonNull(param.getCameraType()) && Objects.nonNull(param.getZoomFactor())
&& (CameraTypeEnum.ZOOM == param.getCameraType()
|| CameraTypeEnum.IR == param.getCameraType());
}
@Override
public boolean canPublish(String deviceSn) {
super.canPublish(deviceSn);
if (CameraStateEnum.WORKING == osdCamera.getPhotoState()) {
return false;
}
switch (param.getCameraType()) {
case IR:
return param.getZoomFactor().intValue() != osdCamera.getIrZoomFactor();
case ZOOM:
return param.getZoomFactor().intValue() != osdCamera.getZoomFactor();
}
return false;
}
}

31
src/main/java/com/dji/sample/control/service/impl/CameraModeSwitchImpl.java

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.enums.CameraStateEnum;
import com.dji.sample.control.model.param.DronePayloadParam;
import java.util.Objects;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class CameraModeSwitchImpl extends PayloadCommandsHandler {
public CameraModeSwitchImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean valid() {
return Objects.nonNull(param.getCameraMode());
}
@Override
public boolean canPublish(String deviceSn) {
super.canPublish(deviceSn);
return param.getCameraMode() != osdCamera.getCameraMode()
&& CameraStateEnum.IDLE == osdCamera.getPhotoState()
&& CameraStateEnum.IDLE == osdCamera.getRecordingState();
}
}

22
src/main/java/com/dji/sample/control/service/impl/CameraPhotoTakeImpl.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.enums.CameraStateEnum;
import com.dji.sample.control.model.param.DronePayloadParam;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class CameraPhotoTakeImpl extends PayloadCommandsHandler {
public CameraPhotoTakeImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean canPublish(String deviceSn) {
super.canPublish(deviceSn);
return CameraStateEnum.WORKING != osdCamera.getPhotoState() && osdCamera.getRemainPhotoNum() > 0;
}
}

25
src/main/java/com/dji/sample/control/service/impl/CameraRecordingStartImpl.java

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.enums.CameraModeEnum;
import com.dji.sample.control.model.enums.CameraStateEnum;
import com.dji.sample.control.model.param.DronePayloadParam;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class CameraRecordingStartImpl extends PayloadCommandsHandler {
public CameraRecordingStartImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean canPublish(String deviceSn) {
super.canPublish(deviceSn);
return CameraModeEnum.VIDEO == osdCamera.getCameraMode()
&& CameraStateEnum.IDLE == osdCamera.getRecordingState()
&& osdCamera.getRemainRecordDuration() > 0;
}
}

22
src/main/java/com/dji/sample/control/service/impl/CameraRecordingStopImpl.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.enums.CameraStateEnum;
import com.dji.sample.control.model.param.DronePayloadParam;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class CameraRecordingStopImpl extends PayloadCommandsHandler {
public CameraRecordingStopImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean canPublish(String deviceSn) {
super.canPublish(deviceSn);
return CameraStateEnum.WORKING == osdCamera.getRecordingState();
}
}

271
src/main/java/com/dji/sample/control/service/impl/ControlServiceImpl.java

@ -6,26 +6,34 @@ import com.dji.sample.component.mqtt.model.*; @@ -6,26 +6,34 @@ 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.CustomWebSocketMessage;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.service.ISendMessageService;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.control.model.enums.RemoteControlMethodEnum;
import com.dji.sample.control.model.param.RemoteDebugParam;
import com.dji.sample.control.model.dto.FlyToProgressReceiver;
import com.dji.sample.control.model.dto.ResultNotifyDTO;
import com.dji.sample.control.model.dto.TakeoffProgressReceiver;
import com.dji.sample.control.model.enums.DroneAuthorityEnum;
import com.dji.sample.control.model.enums.DroneControlMethodEnum;
import com.dji.sample.control.model.enums.RemoteDebugMethodEnum;
import com.dji.sample.control.model.param.*;
import com.dji.sample.control.service.IControlService;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.DeviceModeCodeEnum;
import com.dji.sample.manage.model.enums.DockModeCodeEnum;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import com.dji.sample.manage.service.IDevicePayloadService;
import com.dji.sample.manage.service.IDeviceRedisService;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.wayline.model.enums.WaylineErrorCodeEnum;
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;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
/**
@ -44,55 +52,49 @@ public class ControlServiceImpl implements IControlService { @@ -44,55 +52,49 @@ public class ControlServiceImpl implements IControlService {
private ISendMessageService webSocketMessageService;
@Autowired
private IWebSocketManageService webSocketManageService;
private IDeviceService deviceService;
@Autowired
private IDeviceService deviceService;
private IDeviceRedisService deviceRedisService;
@Autowired
private ObjectMapper mapper;
@Autowired
private IDevicePayloadService devicePayloadService;
private RemoteDebugHandler checkDebugCondition(String sn, RemoteDebugParam param, RemoteDebugMethodEnum controlMethodEnum) {
RemoteDebugHandler handler = Objects.nonNull(controlMethodEnum.getClazz()) ?
mapper.convertValue(Objects.nonNull(param) ? param : new Object(), controlMethodEnum.getClazz())
: new RemoteDebugHandler();
if (!handler.canPublish(sn)) {
throw new RuntimeException("The current state of the dock does not support this function.");
}
if (Objects.nonNull(param) && !handler.valid()) {
throw new RuntimeException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg());
}
return handler;
}
@Override
public ResponseResult controlDock(String sn, String serviceIdentifier, RemoteDebugParam param) {
RemoteControlMethodEnum controlMethodEnum = RemoteControlMethodEnum.find(serviceIdentifier);
if (RemoteControlMethodEnum.UNKNOWN == controlMethodEnum) {
public ResponseResult controlDockDebug(String sn, String serviceIdentifier, RemoteDebugParam param) {
RemoteDebugMethodEnum controlMethodEnum = RemoteDebugMethodEnum.find(serviceIdentifier);
if (RemoteDebugMethodEnum.UNKNOWN == controlMethodEnum) {
return ResponseResult.error("The " + serviceIdentifier + " method does not exist.");
}
Object data = "";
// Add parameter validation.
if (Objects.nonNull(controlMethodEnum.getClazz())) {
if (Objects.isNull(param)) {
return ResponseResult.error(CommonErrorEnum.ILLEGAL_ARGUMENT);
}
BasicDeviceProperty basicDeviceProperty = mapper.convertValue(param.getAction(), controlMethodEnum.getClazz());
if (!basicDeviceProperty.valid()) {
return ResponseResult.error(CommonErrorEnum.ILLEGAL_ARGUMENT);
}
data = basicDeviceProperty;
}
RemoteDebugHandler data = checkDebugCondition(sn, param, controlMethodEnum);
boolean isExist = deviceService.checkDeviceOnline(sn);
boolean isExist = deviceRedisService.checkDeviceOnline(sn);
if (!isExist) {
return ResponseResult.error("The dock is offline.");
}
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + sn + TopicConst.SERVICES_SUF;
String bid = UUID.randomUUID().toString();
ServiceReply serviceReplyOpt = messageSenderService.publishWithReply(
topic, CommonTopicResponse.builder()
.tid(UUID.randomUUID().toString())
.bid(bid)
.method(serviceIdentifier)
.timestamp(System.currentTimeMillis())
.data(data)
.build());
ServiceReply serviceReply = messageSenderService.publishServicesTopic(sn, serviceIdentifier, data, bid);
ServiceReply<EventsOutputReceiver> serviceReply = mapper.convertValue(
serviceReplyOpt, new TypeReference<ServiceReply<EventsOutputReceiver>>() {});
if (ResponseResult.CODE_SUCCESS != serviceReply.getResult()) {
return ResponseResult.error(serviceReply.getResult(),
Objects.nonNull(serviceReply.getOutput()) ? serviceReply.getOutput().getStatus()
: "error: " + serviceIdentifier + serviceReply.getResult());
"error: " + serviceIdentifier + serviceReply.getResult());
}
if (controlMethodEnum.getProgress()) {
RedisOpsUtils.setWithExpire(serviceIdentifier + RedisConst.DELIMITER + bid, sn,
@ -101,17 +103,22 @@ public class ControlServiceImpl implements IControlService { @@ -101,17 +103,22 @@ public class ControlServiceImpl implements IControlService {
return ResponseResult.success();
}
@Override
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS, outputChannel = ChannelName.OUTBOUND)
public void handleControlProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
/**
* Handles multi-state command progress information.
* @param receiver
* @param headers
* @return
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
public CommonTopicReceiver handleControlProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
String key = receiver.getMethod() + RedisConst.DELIMITER + receiver.getBid();
if (RedisOpsUtils.getExpire(key) <= 0) {
return;
return receiver;
}
String sn = RedisOpsUtils.get(key).toString();
EventsReceiver<EventsOutputReceiver> eventsReceiver = mapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<EventsOutputReceiver>>(){});
EventsReceiver<EventsOutputProgressReceiver> eventsReceiver = mapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<EventsOutputProgressReceiver>>(){});
eventsReceiver.setBid(receiver.getBid());
eventsReceiver.setSn(sn);
@ -127,26 +134,168 @@ public class ControlServiceImpl implements IControlService { @@ -127,26 +134,168 @@ public class ControlServiceImpl implements IControlService {
RedisOpsUtils.del(key);
}
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
webSocketMessageService.sendBatch(
webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
CustomWebSocketMessage.builder()
.data(eventsReceiver)
.timestamp(System.currentTimeMillis())
.bizCode(receiver.getMethod())
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(sn);
if (deviceOpt.isEmpty()) {
throw new RuntimeException("The device is offline.");
}
DeviceDTO device = deviceOpt.get();
webSocketMessageService.sendBatch(device.getWorkspaceId(), UserTypeEnum.WEB.getVal(),
receiver.getMethod(), eventsReceiver);
return receiver;
}
private void checkFlyToCondition(String dockSn) {
// TODO 设备固件版本不兼容情况
Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(dockSn);
if (dockOpt.isEmpty()) {
throw new RuntimeException("The dock is offline, please restart the dock.");
}
DeviceModeCodeEnum deviceMode = deviceService.getDeviceMode(dockOpt.get().getChildDeviceSn());
if (DeviceModeCodeEnum.MANUAL != deviceMode) {
throw new RuntimeException("The current state of the drone does not support this function, please try again later.");
}
ResponseResult result = seizeAuthority(dockSn, DroneAuthorityEnum.FLIGHT, null);
if (ResponseResult.CODE_SUCCESS != result.getCode()) {
throw new IllegalArgumentException(result.getMessage());
}
}
@Override
public ResponseResult flyToPoint(String sn, FlyToPointParam param) {
checkFlyToCondition(sn);
param.setFlyToId(UUID.randomUUID().toString());
ServiceReply reply = messageSenderService.publishServicesTopic(sn, DroneControlMethodEnum.FLY_TO_POINT.getMethod(), param, param.getFlyToId());
return ResponseResult.CODE_SUCCESS != reply.getResult() ?
ResponseResult.error("Flying to the target point failed." + reply.getResult())
: ResponseResult.success();
}
@Override
public ResponseResult flyToPointStop(String sn) {
ServiceReply reply = messageSenderService.publishServicesTopic(sn, DroneControlMethodEnum.FLY_TO_POINT_STOP.getMethod(), null);
return ResponseResult.CODE_SUCCESS != reply.getResult() ?
ResponseResult.error("The drone flying to the target point failed to stop. " + reply.getResult())
: ResponseResult.success();
}
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FLY_TO_POINT_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
public CommonTopicReceiver handleFlyToPointProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
String dockSn = receiver.getGateway();
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(dockSn);
if (deviceOpt.isEmpty()) {
log.error("The dock is offline.");
return null;
}
FlyToProgressReceiver eventsReceiver = mapper.convertValue(receiver.getData(), new TypeReference<FlyToProgressReceiver>(){});
webSocketMessageService.sendBatch(deviceOpt.get().getWorkspaceId(), UserTypeEnum.WEB.getVal(),
BizCodeEnum.FLY_TO_POINT_PROGRESS.getCode(),
ResultNotifyDTO.builder().sn(dockSn)
.message(WaylineErrorCodeEnum.SUCCESS == eventsReceiver.getResult() ?
eventsReceiver.getStatus().getMessage() : eventsReceiver.getResult().getErrorMsg())
.result(eventsReceiver.getResult().getErrorCode())
.build());
return receiver;
}
private void checkTakeoffCondition(String dockSn) {
Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(dockSn);
if (dockOpt.isEmpty() || DockModeCodeEnum.IDLE != deviceService.getDockMode(dockSn)) {
throw new RuntimeException("The current state does not support takeoff.");
}
ResponseResult result = seizeAuthority(dockSn, DroneAuthorityEnum.FLIGHT, null);
if (ResponseResult.CODE_SUCCESS != result.getCode()) {
throw new IllegalArgumentException(result.getMessage());
}
}
@Override
public ResponseResult takeoffToPoint(String sn, TakeoffToPointParam param) {
checkTakeoffCondition(sn);
param.setFlightId(UUID.randomUUID().toString());
ServiceReply reply = messageSenderService.publishServicesTopic(sn, DroneControlMethodEnum.TAKE_OFF_TO_POINT.getMethod(), param, param.getFlightId());
return ResponseResult.CODE_SUCCESS != reply.getResult() ?
ResponseResult.error("The drone failed to take off. " + reply.getResult())
: ResponseResult.success();
}
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_TAKE_OFF_TO_POINT_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
public CommonTopicReceiver handleTakeoffToPointProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
String dockSn = receiver.getGateway();
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(dockSn);
if (deviceOpt.isEmpty()) {
log.error("The dock is offline.");
return null;
}
TakeoffProgressReceiver eventsReceiver = mapper.convertValue(receiver.getData(), new TypeReference<TakeoffProgressReceiver>(){});
webSocketMessageService.sendBatch(deviceOpt.get().getWorkspaceId(), UserTypeEnum.WEB.getVal(),
BizCodeEnum.TAKE_OFF_TO_POINT_PROGRESS.getCode(),
ResultNotifyDTO.builder().sn(dockSn)
.message(WaylineErrorCodeEnum.SUCCESS == eventsReceiver.getResult() ?
eventsReceiver.getStatus().getMessage() : eventsReceiver.getResult().getErrorMsg())
.result(eventsReceiver.getResult().getErrorCode())
.build());
if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) {
String topic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF;
messageSenderService.publish(topic,
CommonTopicResponse.builder()
.tid(receiver.getTid())
.bid(receiver.getBid())
.method(receiver.getMethod())
.timestamp(System.currentTimeMillis())
.data(RequestsReply.success())
.build());
return receiver;
}
@Override
public ResponseResult seizeAuthority(String sn, DroneAuthorityEnum authority, DronePayloadParam param) {
String method;
switch (authority) {
case FLIGHT:
if (deviceService.checkAuthorityFlight(sn)) {
return ResponseResult.success();
}
method = DroneControlMethodEnum.FLIGHT_AUTHORITY_GRAB.getMethod();
break;
case PAYLOAD:
if (checkPayloadAuthority(sn, param.getPayloadIndex())) {
return ResponseResult.success();
}
method = DroneControlMethodEnum.PAYLOAD_AUTHORITY_GRAB.getMethod();
break;
default:
return ResponseResult.error(CommonErrorEnum.ILLEGAL_ARGUMENT);
}
ServiceReply serviceReply = messageSenderService.publishServicesTopic(sn, method, param);
return ResponseResult.CODE_SUCCESS != serviceReply.getResult() ?
ResponseResult.error(serviceReply.getResult(), "Method: " + method + " Error Code:" + serviceReply.getResult())
: ResponseResult.success();
}
private Boolean checkPayloadAuthority(String sn, String payloadIndex) {
Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(sn);
if (dockOpt.isEmpty()) {
throw new RuntimeException("The dock is offline, please restart the dock.");
}
return devicePayloadService.checkAuthorityPayload(dockOpt.get().getChildDeviceSn(), payloadIndex);
}
@Override
public ResponseResult payloadCommands(PayloadCommandsParam param) throws Exception {
param.getCmd().getClazz()
.getDeclaredConstructor(DronePayloadParam.class)
.newInstance(param.getData())
.checkCondition(param.getSn());
ServiceReply serviceReply = messageSenderService.publishServicesTopic(param.getSn(), param.getCmd().getCmd(), param.getData());
return ResponseResult.CODE_SUCCESS != serviceReply.getResult() ?
ResponseResult.error(serviceReply.getResult(), " Error Code:" + serviceReply.getResult())
: ResponseResult.success();
}
}

249
src/main/java/com/dji/sample/control/service/impl/DrcServiceImpl.java

@ -0,0 +1,249 @@ @@ -0,0 +1,249 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.config.MqttConfiguration;
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.service.ISendMessageService;
import com.dji.sample.control.model.dto.*;
import com.dji.sample.control.model.enums.DrcMethodEnum;
import com.dji.sample.control.model.enums.DrcStatusErrorEnum;
import com.dji.sample.control.model.enums.DroneAuthorityEnum;
import com.dji.sample.control.model.enums.MqttAclAccessEnum;
import com.dji.sample.control.model.param.DrcConnectParam;
import com.dji.sample.control.model.param.DrcModeParam;
import com.dji.sample.control.service.IControlService;
import com.dji.sample.control.service.IDrcService;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.DockModeCodeEnum;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver;
import com.dji.sample.manage.service.IDeviceRedisService;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.wayline.model.dto.WaylineTaskProgressReceiver;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.dji.sample.wayline.model.enums.WaylineTaskStatusEnum;
import com.dji.sample.wayline.model.param.UpdateJobParam;
import com.dji.sample.wayline.service.IWaylineJobService;
import com.dji.sample.wayline.service.IWaylineRedisService;
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.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @author sean
* @version 1.3
* @date 2023/1/11
*/
@Service
@Slf4j
public class DrcServiceImpl implements IDrcService {
@Autowired
private IMessageSenderService messageSenderService;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private IWaylineJobService waylineJobService;
@Autowired
private IDeviceService deviceService;
@Autowired
private ObjectMapper mapper;
@Autowired
private ISendMessageService webSocketMessageService;
@Autowired
private IControlService controlService;
@Autowired
private IDeviceRedisService deviceRedisService;
@Autowired
private IWaylineRedisService waylineRedisService;
@Override
public void setDrcModeInRedis(String dockSn, String clientId) {
RedisOpsUtils.setWithExpire(RedisConst.DRC_PREFIX + dockSn, clientId, RedisConst.DRC_MODE_ALIVE_SECOND);
}
@Override
public String getDrcModeInRedis(String dockSn) {
return (String) RedisOpsUtils.get(RedisConst.DRC_PREFIX + dockSn);
}
@Override
public Boolean delDrcModeInRedis(String dockSn) {
return RedisOpsUtils.del(RedisConst.DRC_PREFIX + dockSn);
}
@Override
public MqttBrokerDTO userDrcAuth(String workspaceId, String userId, String username, DrcConnectParam param) {
// refresh token
String clientId = param.getClientId();
// first time
if (!StringUtils.hasText(clientId) || !RedisOpsUtils.checkExist(RedisConst.MQTT_ACL_PREFIX + clientId)) {
clientId = userId + "-" + System.currentTimeMillis();
RedisOpsUtils.hashSet(RedisConst.MQTT_ACL_PREFIX + clientId, "", MqttAclAccessEnum.ALL.getValue());
}
String key = RedisConst.MQTT_ACL_PREFIX + clientId;
try {
RedisOpsUtils.expireKey(key, RedisConst.DRC_MODE_ALIVE_SECOND);
return MqttConfiguration.getMqttBrokerWithDrc(
clientId, username, param.getExpireSec(), Collections.emptyMap());
} catch (RuntimeException e) {
RedisOpsUtils.del(key);
throw e;
}
}
private void checkDrcModeCondition(String workspaceId, String dockSn) {
Optional<EventsReceiver<WaylineTaskProgressReceiver>> runningOpt = waylineRedisService.getRunningWaylineJob(dockSn);
if (runningOpt.isPresent() && WaylineJobStatusEnum.IN_PROGRESS == waylineJobService.getWaylineState(dockSn)) {
waylineJobService.updateJobStatus(workspaceId, runningOpt.get().getBid(),
UpdateJobParam.builder().status(WaylineTaskStatusEnum.PAUSE).build());
}
DockModeCodeEnum dockMode = deviceService.getDockMode(dockSn);
Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(dockSn);
if (dockOpt.isPresent() && (DockModeCodeEnum.IDLE == dockMode || DockModeCodeEnum.WORKING == dockMode)) {
Optional<OsdSubDeviceReceiver> deviceOsd = deviceRedisService.getDeviceOsd(dockOpt.get().getChildDeviceSn(), OsdSubDeviceReceiver.class);
if (deviceOsd.isEmpty() || deviceOsd.get().getElevation() <= 0) {
throw new RuntimeException("The drone is not in the sky and cannot enter command flight mode.");
}
} else {
throw new RuntimeException("The current state of the dock does not support entering command flight mode.");
}
ResponseResult result = controlService.seizeAuthority(dockSn, DroneAuthorityEnum.FLIGHT, null);
if (ResponseResult.CODE_SUCCESS != result.getCode()) {
throw new IllegalArgumentException(result.getMessage());
}
}
@Override
public JwtAclDTO deviceDrcEnter(String workspaceId, DrcModeParam param) {
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + param.getDockSn() + TopicConst.DRC;
String pubTopic = topic + TopicConst.DOWN;
String subTopic = topic + TopicConst.UP;
// If the dock is in drc mode, refresh the permissions directly.
if (deviceService.checkDockDrcMode(param.getDockSn())
&& param.getClientId().equals(this.getDrcModeInRedis(param.getDockSn()))) {
refreshAcl(param.getDockSn(), param.getClientId(), topic, subTopic);
return JwtAclDTO.builder().sub(List.of(subTopic)).pub(List.of(pubTopic)).build();
}
checkDrcModeCondition(workspaceId, param.getDockSn());
ServiceReply reply = messageSenderService.publishServicesTopic(
param.getDockSn(), DrcMethodEnum.DRC_MODE_ENTER.getMethod(),
DrcModeDTO.builder()
.mqttBroker(MqttConfiguration.getMqttBrokerWithDrc(param.getDockSn() + "-" + System.currentTimeMillis(), param.getDockSn(),
RedisConst.DRC_MODE_ALIVE_SECOND.longValue(),
Map.of(MapKeyConst.ACL, objectMapper.convertValue(JwtAclDTO.builder()
.pub(List.of(subTopic))
.sub(List.of(pubTopic))
.build(), new TypeReference<Map<String, ?>>() {}))))
.build());
if (ResponseResult.CODE_SUCCESS != reply.getResult()) {
throw new RuntimeException("SN: " + param.getDockSn() + "; Error Code:" + reply.getResult() + "; Failed to enter command flight control mode, please try again later!");
}
refreshAcl(param.getDockSn(), param.getClientId(), pubTopic, subTopic);
return JwtAclDTO.builder().sub(List.of(subTopic)).pub(List.of(pubTopic)).build();
}
private void refreshAcl(String dockSn, String clientId, String pubTopic, String subTopic) {
this.setDrcModeInRedis(dockSn, clientId);
// assign acl,Match by clientId. https://www.emqx.io/docs/zh/v4.4/advanced/acl-redis.html
// scheme: HSET mqtt_acl:[clientid] [topic] [access]
String key = RedisConst.MQTT_ACL_PREFIX + clientId;
RedisOpsUtils.hashSet(key, pubTopic, MqttAclAccessEnum.PUB.getValue());
RedisOpsUtils.hashSet(key, subTopic, MqttAclAccessEnum.SUB.getValue());
}
@Override
public void deviceDrcExit(String workspaceId, DrcModeParam param) {
if (!deviceService.checkDockDrcMode(param.getDockSn())) {
throw new RuntimeException("The dock is not in flight control mode.");
}
ServiceReply reply = messageSenderService.publishServicesTopic(
param.getDockSn(), DrcMethodEnum.DRC_MODE_EXIT.getMethod(), "");
if (ResponseResult.CODE_SUCCESS != reply.getResult()) {
throw new RuntimeException("SN: " + param.getDockSn() + "; Error Code:" +
reply.getResult() + "; Failed to exit command flight control mode, please try again later!");
}
String jobId = waylineRedisService.getPausedWaylineJobId(param.getDockSn());
if (StringUtils.hasText(jobId)) {
waylineJobService.updateJobStatus(workspaceId, jobId, UpdateJobParam.builder().status(WaylineTaskStatusEnum.RESUME).build());
}
this.delDrcModeInRedis(param.getDockSn());
RedisOpsUtils.del(RedisConst.MQTT_ACL_PREFIX + param.getClientId());
}
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_DRC_STATUS_NOTIFY, outputChannel = ChannelName.OUTBOUND_EVENTS)
public CommonTopicReceiver handleDrcStatusNotify(CommonTopicReceiver receiver, MessageHeaders headers) {
String dockSn = receiver.getGateway();
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(dockSn);
if (deviceOpt.isEmpty()) {
return null;
}
DrcStatusNotifyReceiver eventsReceiver = mapper.convertValue(receiver.getData(), new TypeReference<DrcStatusNotifyReceiver>(){});
if (DrcStatusErrorEnum.SUCCESS != eventsReceiver.getResult()) {
webSocketMessageService.sendBatch(
deviceOpt.get().getWorkspaceId(), UserTypeEnum.WEB.getVal(), BizCodeEnum.DRC_STATUS_NOTIFY.getCode(),
ResultNotifyDTO.builder().sn(dockSn)
.message(eventsReceiver.getResult().getErrorMsg())
.result(eventsReceiver.getResult().getErrorCode()).build());
}
return receiver;
}
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_DRC_MODE_EXIT_NOTIFY, outputChannel = ChannelName.OUTBOUND_EVENTS)
public CommonTopicReceiver handleDrcModeExitNotify(CommonTopicReceiver receiver, MessageHeaders headers) {
String dockSn = receiver.getGateway();
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(dockSn);
if (deviceOpt.isEmpty()) {
return null;
}
DrcModeReasonReceiver eventsReceiver = mapper.convertValue(receiver.getData(), new TypeReference<DrcModeReasonReceiver>(){});
webSocketMessageService.sendBatch(
deviceOpt.get().getWorkspaceId(), UserTypeEnum.WEB.getVal(), BizCodeEnum.JOYSTICK_INVALID_NOTIFY.getCode(),
ResultNotifyDTO.builder().sn(dockSn)
.message(eventsReceiver.getReason().getMessage())
.result(eventsReceiver.getReason().getVal()).build());
return receiver;
}
}

22
src/main/java/com/dji/sample/control/service/impl/GimbalResetImpl.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.control.model.param.DronePayloadParam;
import java.util.Objects;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public class GimbalResetImpl extends PayloadCommandsHandler {
public GimbalResetImpl(DronePayloadParam param) {
super(param);
}
@Override
public boolean valid() {
return Objects.nonNull(param.getResetMode());
}
}

82
src/main/java/com/dji/sample/control/service/impl/PayloadCommandsHandler.java

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.common.util.SpringBeanUtils;
import com.dji.sample.control.model.param.DronePayloadParam;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.receiver.OsdCameraReceiver;
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver;
import com.dji.sample.manage.service.IDevicePayloadService;
import com.dji.sample.manage.service.IDeviceRedisService;
import java.util.Optional;
/**
* @author sean
* @version 1.4
* @date 2023/4/23
*/
public abstract class PayloadCommandsHandler {
DronePayloadParam param;
OsdCameraReceiver osdCamera;
PayloadCommandsHandler(DronePayloadParam param) {
this.param = param;
}
public boolean valid() {
return true;
}
public boolean canPublish(String deviceSn) {
Optional<OsdSubDeviceReceiver> deviceOpt = SpringBeanUtils.getBean(IDeviceRedisService.class)
.getDeviceOsd(deviceSn, OsdSubDeviceReceiver.class);
if (deviceOpt.isEmpty()) {
throw new RuntimeException("The device is offline.");
}
osdCamera = deviceOpt.get().getCameras().stream()
.filter(osdCamera -> param.getPayloadIndex().equals(osdCamera.getPayloadIndex()))
.findAny()
.orElseThrow(() -> new RuntimeException("Did not receive osd information about the camera, please check the cache data."));
return true;
}
private String checkDockOnline(String dockSn) {
Optional<DeviceDTO> deviceOpt = SpringBeanUtils.getBean(IDeviceRedisService.class).getDeviceOnline(dockSn);
if (deviceOpt.isEmpty()) {
throw new RuntimeException("The dock is offline.");
}
return deviceOpt.get().getChildDeviceSn();
}
private void checkDeviceOnline(String deviceSn) {
boolean isOnline = SpringBeanUtils.getBean(IDeviceRedisService.class).checkDeviceOnline(deviceSn);
if (!isOnline) {
throw new RuntimeException("The device is offline.");
}
}
private void checkAuthority(String deviceSn) {
boolean hasAuthority = SpringBeanUtils.getBean(IDevicePayloadService.class)
.checkAuthorityPayload(deviceSn, param.getPayloadIndex());
if (!hasAuthority) {
throw new RuntimeException("The device does not have payload control authority.");
}
}
public final void checkCondition(String dockSn) {
if (!valid()) {
throw new RuntimeException("illegal argument");
}
String deviceSn = checkDockOnline(dockSn);
checkDeviceOnline(deviceSn);
checkAuthority(deviceSn);
if (!canPublish(deviceSn)) {
throw new RuntimeException("The current state of the drone does not support this function, please try again later.");
}
}
}

23
src/main/java/com/dji/sample/control/service/impl/RemoteDebugHandler.java

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
package com.dji.sample.control.service.impl;
import com.dji.sample.common.util.SpringBeanUtils;
import com.dji.sample.manage.model.enums.DockModeCodeEnum;
import com.dji.sample.manage.service.IDeviceService;
/**
* @author sean
* @version 1.3
* @date 2022/10/27
*/
public class RemoteDebugHandler {
public boolean valid() {
return false;
}
public boolean canPublish(String sn) {
IDeviceService deviceService = SpringBeanUtils.getBean(IDeviceService.class);
DockModeCodeEnum dockMode = deviceService.getDockMode(sn);
return DockModeCodeEnum.REMOTE_DEBUGGING == dockMode;
}
}

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

@ -1,35 +0,0 @@ @@ -1,35 +0,0 @@
package com.dji.sample.manage.controller;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
import com.dji.sample.manage.service.IDevicePayloadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.MessageHeaders;
import org.springframework.web.bind.annotation.RestController;
/**
* @author sean.zhou
* @date 2021/11/19
* @version 0.1
*/
@RestController
public class DevicePayloadController {
@Autowired
private IDevicePayloadService devicePayloadService;
/**
* 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
* according to your business needs.
* @param deviceBasic basic drone data
* @param headers
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC)
public void stateBasic(DeviceBasicReceiver deviceBasic, MessageHeaders headers) {
devicePayloadService.saveDeviceBasicPayload(deviceBasic.getPayloads(), headers.getTimestamp());
}
}

26
src/main/java/com/dji/sample/manage/model/dto/DeviceAuthorityDTO.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.manage.model.dto;
import com.dji.sample.control.model.enums.DroneAuthorityEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.4
* @date 2023/3/2
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DeviceAuthorityDTO {
private String sn;
private DroneAuthorityEnum type;
private String controlSource;
}

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

@ -25,7 +25,7 @@ public class DeviceDTO { @@ -25,7 +25,7 @@ public class DeviceDTO {
private String workspaceId;
private String deviceIndex;
private String controlSource;
private String deviceDesc;
@ -62,4 +62,6 @@ public class DeviceDTO { @@ -62,4 +62,6 @@ public class DeviceDTO {
private Integer firmwareStatus;
private Integer firmwareProgress;
private String parentSn;
}

6
src/main/java/com/dji/sample/manage/model/dto/DevicePayloadDTO.java

@ -23,7 +23,11 @@ public class DevicePayloadDTO { @@ -23,7 +23,11 @@ public class DevicePayloadDTO {
private String payloadName;
private Integer payloadIndex;
private Integer index;
private String payloadDesc;
private String controlSource;
private String payloadIndex;
}

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

@ -53,4 +53,7 @@ public class DevicePayloadEntity implements Serializable { @@ -53,4 +53,7 @@ public class DevicePayloadEntity implements Serializable {
@TableField(value = "payload_desc")
private String payloadDesc;
@TableField(value = "control_source")
private String controlSource;
}

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

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.manage.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/16
*/
public enum ControlSourceEnum {
A, B;
@JsonValue
public String getControlSource() {
return name();
}
@JsonCreator
public static ControlSourceEnum find(String controlSource) {
return Arrays.stream(values()).filter(controlSourceEnum -> controlSourceEnum.name().equals(controlSource)).findAny().get();
}
}

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

@ -2,6 +2,8 @@ package com.dji.sample.manage.model.enums; @@ -2,6 +2,8 @@ package com.dji.sample.manage.model.enums;
import lombok.Getter;
import java.util.Arrays;
/**
*
* @author sean.zhou
@ -17,11 +19,17 @@ public enum DeviceDomainEnum { @@ -17,11 +19,17 @@ public enum DeviceDomainEnum {
PAYLOAD(1),
DOCK (3);
DOCK (3),
UNKNOWN(-1);
int val;
DeviceDomainEnum(int val) {
this.val = val;
}
public static DeviceDomainEnum find(int val) {
return Arrays.stream(values()).filter(domainEnum -> domainEnum.val == val).findAny().orElse(UNKNOWN);
}
}

64
src/main/java/com/dji/sample/manage/model/enums/DeviceModeCodeEnum.java

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
package com.dji.sample.manage.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/9
*/
public enum DeviceModeCodeEnum {
IDLE(0),
TAKEOFF_PREPARE(1),
TAKEOFF_FINISHED(2),
MANUAL(3),
TAKEOFF_AUTO(4),
WAYLINE(5),
PANORAMIC_SHOT(6),
ACTIVE_TRACK(7),
ADS_B_AVOIDANCE(8),
RETURN_AUTO(9),
LANDING_AUTO(10),
LANDING_FORCED(11),
LANDING_THREE_PROPELLER(12),
UPGRADING(13),
DISCONNECTED(14),
APAS(15),
VIRTUAL_JOYSTICK(16);
int val;
DeviceModeCodeEnum(int val) {
this.val = val;
}
@JsonValue
public int getVal() {
return val;
}
@JsonCreator
public static DeviceModeCodeEnum find(int value) {
return Arrays.stream(values()).filter(modeCodeEnum -> modeCodeEnum.ordinal() == value).findAny().orElse(DISCONNECTED);
}
}

5
src/main/java/com/dji/sample/manage/model/enums/DeviceSetPropertyEnum.java

@ -20,8 +20,11 @@ public enum DeviceSetPropertyEnum { @@ -20,8 +20,11 @@ public enum DeviceSetPropertyEnum {
DISTANCE_LIMIT_STATUS("distance_limit_status", DistanceLimitStatusReceiver.class),
OBSTACLE_AVOIDANCE("obstacle_avoidance", ObstacleAvoidanceReceiver.class);
OBSTACLE_AVOIDANCE("obstacle_avoidance", ObstacleAvoidanceReceiver.class),
RTH_ALTITUDE("rth_altitude", RthAltitudeReceiver.class),
OUT_OF_CONTROL_ACTION("out_of_control_action", OutOfControlActionReceiver.class);
String property;

36
src/main/java/com/dji/sample/manage/model/enums/DockDrcStateEnum.java

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
package com.dji.sample.manage.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/2/28
*/
public enum DockDrcStateEnum {
DISCONNECTED(0),
CONNECTING(1),
CONNECTED(2);
int val;
DockDrcStateEnum(int val) {
this.val = val;
}
@JsonValue
public int getVal() {
return val;
}
@JsonCreator
public static DockDrcStateEnum find(int val) {
return Arrays.stream(values()).filter(drcState -> drcState.getVal() == val).findAny().orElse(DISCONNECTED);
}
}

42
src/main/java/com/dji/sample/manage/model/enums/DockModeCodeEnum.java

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
package com.dji.sample.manage.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/2/28
*/
public enum DockModeCodeEnum {
IDLE(0),
DEBUGGING(1),
REMOTE_DEBUGGING(2),
UPGRADING(3),
WORKING(4),
DISCONNECTED(-1);
int val;
DockModeCodeEnum(int val) {
this.val = val;
}
@JsonValue
public int getVal() {
return val;
}
@JsonCreator
public static DockModeCodeEnum find(int val) {
return Arrays.stream(values()).filter(modeCode -> modeCode.getVal() == val).findAny().orElse(DISCONNECTED);
}
}

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

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.manage.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/1
*/
public enum DroneRcLostActionEnum {
HOVER, LAND, RETURN_HOME;
@JsonValue
public int getVal() {
return ordinal();
}
@JsonCreator
public static DroneRcLostActionEnum find(int val) {
return Arrays.stream(values()).filter(controlActionEnum -> controlActionEnum.ordinal() == val).findAny().get();
}
}

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

@ -37,20 +37,6 @@ public enum HmsEnum { @@ -37,20 +37,6 @@ public enum HmsEnum {
}
}
@Getter
public enum DomainType {
DRONE_NEST("drone_nest"),
DRONE("drone");
private String domain;
DomainType(String domain) {
this.domain = domain;
}
}
@Getter
public enum HmsFaqIdEnum {

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

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package com.dji.sample.manage.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
* @author sean
* @version 1.4
* @date 2023/3/15
*/
public enum WaylineRcLostActionEnum {
CONTINUE_WAYLINE, EXECUTE_RC_LOST_ACTION;
@JsonValue
public int getVal() {
return ordinal();
}
@JsonCreator
public static WaylineRcLostActionEnum find(int val) {
return Arrays.stream(values()).filter(lostActionEnum -> lostActionEnum.ordinal() == val).findAny().get();
}
}

5
src/main/java/com/dji/sample/manage/model/receiver/BasicDeviceProperty.java

@ -1,14 +1,11 @@ @@ -1,14 +1,11 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.3
* @date 2022/10/27
*/
@Data
public class BasicDeviceProperty {
public abstract class BasicDeviceProperty {
public boolean valid() {
return false;

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

@ -14,8 +14,6 @@ public class DeviceHmsReceiver { @@ -14,8 +14,6 @@ public class DeviceHmsReceiver {
private String deviceType;
private String domainType;
private Integer imminent;
private Integer inTheSky;

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

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/30
*/
@Data
public class FirmwareProgressExtReceiver {
private Long rate;
}

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

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/8
*/
@Data
public class LiveviewWorldRegionReceiver {
private Double bottom;
private Double left;
private Double right;
private Double top;
}

34
src/main/java/com/dji/sample/manage/model/receiver/OsdCameraReceiver.java

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.control.model.enums.CameraModeEnum;
import com.dji.sample.control.model.enums.CameraStateEnum;
import lombok.Data;
/**
* @author sean
* @version 1.4
* @date 2023/3/8
*/
@Data
public class OsdCameraReceiver {
private CameraModeEnum cameraMode;
private LiveviewWorldRegionReceiver liveviewWorldRegion;
private String payloadIndex;
private CameraStateEnum photoState;
private Integer recordTime;
private CameraStateEnum recordingState;
private Long remainPhotoNum;
private Long remainRecordDuration;
private Float zoomFactor;
private Float irZoomFactor;
}

8
src/main/java/com/dji/sample/manage/model/receiver/OsdDockReceiver.java

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.DockDrcStateEnum;
import com.dji.sample.manage.model.enums.DockModeCodeEnum;
import lombok.Data;
/**
@ -40,13 +42,13 @@ public class OsdDockReceiver { @@ -40,13 +42,13 @@ public class OsdDockReceiver {
private StorageReceiver storage;
private Integer modeCode;
private DockModeCodeEnum modeCode;
private Integer coverState;
private Integer supplementLightState;
private Integer emergencyStopState;
private Boolean emergencyStopState;
private Integer airConditionerMode;
@ -85,4 +87,6 @@ public class OsdDockReceiver { @@ -85,4 +87,6 @@ public class OsdDockReceiver {
private DockSdrReceiver sdr;
private DockWirelessLinkReceiver wirelessLink;
private DockDrcStateEnum drcState;
}

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

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.DeviceModeCodeEnum;
import com.dji.sample.manage.model.enums.DroneRcLostActionEnum;
import com.dji.sample.manage.model.enums.WaylineRcLostActionEnum;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
@ -41,7 +44,7 @@ public class OsdSubDeviceReceiver { @@ -41,7 +44,7 @@ public class OsdSubDeviceReceiver {
private Double longitude;
private Integer modeCode;
private DeviceModeCodeEnum modeCode;
private Double totalFlightDistance;
@ -67,4 +70,15 @@ public class OsdSubDeviceReceiver { @@ -67,4 +70,15 @@ public class OsdSubDeviceReceiver {
private ObstacleAvoidanceReceiver obstacleAvoidance;
private Long activationTime;
private List<OsdCameraReceiver> cameras;
private DroneRcLostActionEnum rcLostAction;
private Integer rthAltitude;
private Integer totalFlightSorties;
private WaylineRcLostActionEnum exitWaylineWhenRcLost;
}

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

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.DroneRcLostActionEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author sean
* @version 1.4
* @date 2023/3/3
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OutOfControlActionReceiver extends BasicDeviceProperty {
private Integer value;
@Override
public boolean valid() {
return Objects.nonNull(value) && value >= 0 && value < DroneRcLostActionEnum.values().length;
}
}

32
src/main/java/com/dji/sample/manage/model/receiver/RthAltitudeReceiver.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package com.dji.sample.manage.model.receiver;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author sean
* @version 1.4
* @date 2023/3/3
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RthAltitudeReceiver extends BasicDeviceProperty {
private Integer value;
private static final int RTH_ALTITUDE_MAX = 500;
private static final int RTH_ALTITUDE_MIN = 20;
@Override
public boolean valid() {
return Objects.nonNull(this.value) && this.value >= RTH_ALTITUDE_MIN && this.value <= RTH_ALTITUDE_MAX;
}
}

9
src/main/java/com/dji/sample/manage/service/IDeviceFirmwareService.java

@ -1,14 +1,12 @@ @@ -1,14 +1,12 @@
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.DeviceFirmwareDTO;
import com.dji.sample.manage.model.dto.DeviceFirmwareNoteDTO;
import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO;
import com.dji.sample.manage.model.param.DeviceFirmwareQueryParam;
import com.dji.sample.manage.model.param.DeviceFirmwareUploadParam;
import com.dji.sample.manage.model.param.DeviceOtaCreateParam;
import org.springframework.messaging.MessageHeaders;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@ -47,13 +45,6 @@ public interface IDeviceFirmwareService { @@ -47,13 +45,6 @@ public interface IDeviceFirmwareService {
*/
List<DeviceOtaCreateParam> getDeviceOtaFirmware(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS);
/**
* Interface to handle device firmware update progress.
* @param receiver
* @param headers
*/
void handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers);
/**
* Query firmware version information by page.
*

3
src/main/java/com/dji/sample/manage/service/IDeviceLogsService.java

@ -74,8 +74,9 @@ public interface IDeviceLogsService { @@ -74,8 +74,9 @@ public interface IDeviceLogsService {
* Handle logs file upload progress.
* @param receiver
* @param headers
* @return
*/
void handleFileUploadProgress(CommonTopicReceiver receiver, MessageHeaders headers);
CommonTopicReceiver handleFileUploadProgress(CommonTopicReceiver receiver, MessageHeaders headers);
/**
* Update status, which is updated when the logs upload succeeds or fails.

15
src/main/java/com/dji/sample/manage/service/IDevicePayloadService.java

@ -54,16 +54,17 @@ public interface IDevicePayloadService { @@ -54,16 +54,17 @@ public interface IDevicePayloadService {
*/
void updateFirmwareVersion(FirmwareVersionReceiver receiver);
/**
* Handle the topic that contains the payloads field in the state, and save the payloads data.
* @param payloadReceiverList
* @param timestamp
*/
void saveDeviceBasicPayload(List<DevicePayloadReceiver> payloadReceiverList, Long timestamp);
/**
* Delete payload data based on payload sn.
* @param payloadSns
*/
void deletePayloadsByPayloadsSn(Collection<String> payloadSns);
/**
* Check if the device has payload control.
* @param deviceSn
* @param payloadIndex
* @return
*/
Boolean checkAuthorityPayload(String deviceSn, String payloadIndex);
}

95
src/main/java/com/dji/sample/manage/service/IDeviceRedisService.java

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
package com.dji.sample.manage.service;
import com.dji.sample.component.mqtt.model.EventsOutputProgressReceiver;
import com.dji.sample.component.mqtt.model.EventsReceiver;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.receiver.FirmwareProgressExtReceiver;
import java.util.Optional;
import java.util.Set;
/**
* @author sean
* @version 1.4
* @date 2023/3/21
*/
public interface IDeviceRedisService {
/**
* Determine if the device is online.
* @param sn
* @return
*/
Boolean checkDeviceOnline(String sn);
/**
* Query the basic information of the device in redis.
* @param sn
* @return
*/
Optional<DeviceDTO> getDeviceOnline(String sn);
/**
* Save the basic information of the device in redis.
* @param device
*/
void setDeviceOnline(DeviceDTO device);
/**
* Delete the basic device information saved in redis.
* @param sn
* @return
*/
Boolean delDeviceOnline(String sn);
/**
* Get the device's osd real-time data.
* @param sn
* @param clazz
* @param <T>
* @return
*/
<T> Optional<T> getDeviceOsd(String sn, Class<T> clazz);
/**
* Save the firmware update progress of the device in redis.
* @param sn
* @param events
*/
void setFirmwareUpgrading(String sn, EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>> events);
/**
* Query the firmware update progress of the device in redis.
* @param sn
* @return
*/
Optional<EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>>> getFirmwareUpgradingProgress(String sn);
/**
* Delete the firmware update progress of the device in redis.
* @param sn
* @return
*/
Boolean delFirmwareUpgrading(String sn);
/**
* Save the hms key of the device in redis.
* @param sn
* @param keys
*/
void addEndHmsKeys(String sn, String... keys);
/**
* Query all hms keys of the device in redis.
* @param sn
* @return
*/
Set<String> getAllHmsKeys(String sn);
/**
* Delete all hms keys of the device in redis.
* @param sn
* @return
*/
Boolean delHmsKeysBySn(String sn);
}

57
src/main/java/com/dji/sample/manage/service/IDeviceService.java

@ -2,19 +2,18 @@ package com.dji.sample.manage.service; @@ -2,19 +2,18 @@ package com.dji.sample.manage.service;
import com.dji.sample.common.model.PaginationData;
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.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO;
import com.dji.sample.manage.model.dto.TopologyDeviceDTO;
import com.dji.sample.manage.model.enums.DeviceModeCodeEnum;
import com.dji.sample.manage.model.enums.DeviceSetPropertyEnum;
import com.dji.sample.manage.model.enums.DockModeCodeEnum;
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.fasterxml.jackson.databind.JsonNode;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import java.util.Collection;
import java.util.List;
@ -154,24 +153,6 @@ public interface IDeviceService { @@ -154,24 +153,6 @@ public interface IDeviceService {
*/
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
@ -195,12 +176,6 @@ public interface IDeviceService { @@ -195,12 +176,6 @@ public interface IDeviceService {
*/
Optional<DeviceDTO> getDeviceBySn(String sn);
/**
* Update the firmware version information of the device or payload.
* @param receiver
*/
void updateFirmwareVersion(FirmwareVersionReceiver receiver);
/**
* Create job for device firmware updates.
* @param workspaceId
@ -227,9 +202,31 @@ public interface IDeviceService { @@ -227,9 +202,31 @@ public interface IDeviceService {
void deviceOnePropertySet(String topic, DeviceSetPropertyEnum propertyEnum, Map.Entry<String, Object> value);
/**
* Determine if the device is online.
* @param sn
* Check the working status of the dock.
* @param dockSn
* @return
*/
Boolean checkDeviceOnline(String sn);
DockModeCodeEnum getDockMode(String dockSn);
/**
* Query the working status of the aircraft.
* @param deviceSn
* @return
*/
DeviceModeCodeEnum getDeviceMode(String deviceSn);
/**
* Check if the dock is in drc mode.
* @param dockSn
* @return
*/
Boolean checkDockDrcMode(String dockSn);
/**
* Check if the device has flight control.
* @param gatewaySn
* @return
*/
Boolean checkAuthorityFlight(String gatewaySn);
}

2
src/main/java/com/dji/sample/manage/service/IWorkspaceService.java

@ -25,8 +25,6 @@ public interface IWorkspaceService { @@ -25,8 +25,6 @@ public interface IWorkspaceService {
/**
* 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);

8
src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
package com.dji.sample.manage.service.impl;
import com.dji.sample.component.mqtt.model.StateDataEnum;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.CapacityCameraDTO;
@ -36,20 +35,19 @@ public class CapacityCameraServiceImpl implements ICapacityCameraService { @@ -36,20 +35,19 @@ public class CapacityCameraServiceImpl implements ICapacityCameraService {
@Override
public List<CapacityCameraDTO> getCapacityCameraByDeviceSn(String deviceSn) {
return (List<CapacityCameraDTO>) RedisOpsUtils.hashGet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn);
return (List<CapacityCameraDTO>) RedisOpsUtils.hashGet(RedisConst.LIVE_CAPACITY, deviceSn);
}
@Override
public Boolean deleteCapacityCameraByDeviceSn(String deviceSn) {
return RedisOpsUtils.hashDel(StateDataEnum.LIVE_CAPACITY.getDesc(), new String[]{deviceSn});
return RedisOpsUtils.hashDel(RedisConst.LIVE_CAPACITY, new String[]{deviceSn});
}
@Override
public void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn, Long timestamp) {
List<CapacityCameraDTO> capacity = capacityCameraReceivers.stream()
.map(this::receiver2Dto).collect(Collectors.toList());
RedisOpsUtils.hashSet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn, capacity);
RedisOpsUtils.setWithExpire(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + deviceSn, timestamp, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.hashSet(RedisConst.LIVE_CAPACITY, deviceSn, capacity);
}
@Override

105
src/main/java/com/dji/sample/manage/service/impl/DeviceFirmwareServiceImpl.java

@ -13,8 +13,7 @@ import com.dji.sample.component.oss.model.OssConfiguration; @@ -13,8 +13,7 @@ import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.service.impl.OssServiceContext;
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.CustomWebSocketMessage;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.component.websocket.service.impl.SendMessageServiceImpl;
import com.dji.sample.manage.dao.IDeviceFirmwareMapper;
@ -24,15 +23,15 @@ import com.dji.sample.manage.model.enums.UserTypeEnum; @@ -24,15 +23,15 @@ import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.param.DeviceFirmwareQueryParam;
import com.dji.sample.manage.model.param.DeviceFirmwareUploadParam;
import com.dji.sample.manage.model.param.DeviceOtaCreateParam;
import com.dji.sample.manage.model.receiver.FirmwareProgressExtReceiver;
import com.dji.sample.manage.service.IDeviceFirmwareService;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.manage.service.IDeviceRedisService;
import com.dji.sample.manage.service.IFirmwareModelService;
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;
import org.springframework.util.DigestUtils;
@ -76,15 +75,15 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -76,15 +75,15 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
@Autowired
private IWebSocketManageService webSocketManageService;
@Autowired
private IDeviceService deviceService;
@Autowired
private OssServiceContext ossServiceContext;
@Autowired
private IFirmwareModelService firmwareModelService;
@Autowired
private IDeviceRedisService deviceRedisService;
@Override
public Optional<DeviceFirmwareDTO> getFirmware(String workspaceId, String deviceName, String version) {
return Optional.ofNullable(entity2Dto(mapper.selectOne(
@ -108,7 +107,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -108,7 +107,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
public List<DeviceOtaCreateParam> getDeviceOtaFirmware(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) {
List<DeviceOtaCreateParam> deviceOtaList = new ArrayList<>();
upgradeDTOS.forEach(upgradeDevice -> {
boolean exist = deviceService.checkDeviceOnline(upgradeDevice.getSn());
boolean exist = deviceRedisService.checkDeviceOnline(upgradeDevice.getSn());
if (!exist) {
throw new IllegalArgumentException("Device is offline.");
}
@ -125,18 +124,15 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -125,18 +124,15 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
return deviceOtaList;
}
@Override
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_OTA_PROGRESS, outputChannel = ChannelName.OUTBOUND)
public void handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString();
String sn = topic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(),
topic.indexOf(TopicConst.EVENTS_SUF));
EventsReceiver<EventsOutputReceiver> eventsReceiver = objectMapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<EventsOutputReceiver>>(){});
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_OTA_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
public CommonTopicReceiver handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
String sn = receiver.getGateway();
EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>> eventsReceiver = objectMapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>>>(){});
eventsReceiver.setBid(receiver.getBid());
EventsOutputReceiver output = eventsReceiver.getOutput();
EventsOutputProgressReceiver<FirmwareProgressExtReceiver> output = eventsReceiver.getOutput();
log.info("SN: {}, {} ===> Upgrading progress: {}",
sn, receiver.getMethod(), output.getProgress().toString());
@ -144,59 +140,34 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -144,59 +140,34 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
log.error("SN: {}, {} ===> Error code: {}", sn, receiver.getMethod(), eventsReceiver.getResult());
}
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
String childDeviceSn = device.getChildDeviceSn();
boolean upgrade = RedisOpsUtils.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn) > 0;
boolean childUpgrade = RedisOpsUtils.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn) > 0;
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(sn);
if (deviceOpt.isEmpty()) {
return null;
}
// Determine whether it is the ending state, delete the update state key in redis after the job ends.
EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus());
Collection<ConcurrentWebSocketSession> sessions = webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal());
CustomWebSocketMessage<Object> build = CustomWebSocketMessage.builder()
.data(eventsReceiver)
.timestamp(System.currentTimeMillis())
.bizCode(receiver.getMethod())
.build();
if (upgrade) {
if (statusEnum.getEnd()) {
// Delete the cache after the update is complete.
RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn);
} else {
// Update the update progress of the dock in redis.
RedisOpsUtils.setWithExpire(
RedisConst.FIRMWARE_UPGRADING_PREFIX + sn, output.getProgress().getPercent(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
}
eventsReceiver.setSn(sn);
webSocketMessageService.sendBatch(sessions, build);
}
if (childUpgrade) {
if (!StringUtils.hasText(eventsReceiver.getSn())) {
eventsReceiver.setSn(childDeviceSn);
webSocketMessageService.sendBatch(sessions, build);
}
if (statusEnum.getEnd()) {
RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn);
} else {
// Update the update progress of the drone in redis.
RedisOpsUtils.setWithExpire(
RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn, output.getProgress().getPercent(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
}
}
DeviceDTO device = deviceOpt.get();
handleProgress(device.getWorkspaceId(), sn, eventsReceiver, statusEnum.getEnd());
handleProgress(device.getWorkspaceId(), device.getChildDeviceSn(), eventsReceiver, statusEnum.getEnd());
if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) {
String replyTopic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF;
messageSenderService.publish(replyTopic,
CommonTopicResponse.builder()
.tid(receiver.getTid())
.bid(receiver.getBid())
.method(receiver.getMethod())
.timestamp(System.currentTimeMillis())
.data(RequestsReply.success())
.build());
return receiver;
}
private void handleProgress(String workspaceId, String sn,
EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>> events, boolean isEnd) {
boolean upgrade = deviceRedisService.getFirmwareUpgradingProgress(sn).isPresent();
if (!upgrade) {
return;
}
if (isEnd) {
// Delete the cache after the update is complete.
deviceRedisService.delFirmwareUpgrading(sn);
} else {
// Update the update progress of the dock in redis.
deviceRedisService.setFirmwareUpgrading(sn, events);
}
events.setSn(sn);
webSocketMessageService.sendBatch(workspaceId, UserTypeEnum.WEB.getVal(), BizCodeEnum.OTA_PROGRESS.getCode(), events);
}
@Override

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

Loading…
Cancel
Save