Browse Source

initial v1.3.1

Added:
1. Device communication backup link switching.
2. Priority report of the media file uploading.
3. Upload firmware file.
4. HMS updated.

Fixed:
1. Closing the stream prematurely.

Note: There is a change in the structure of the table 'manage_device_firmware'.
v1.3.1
sean.zhou 2 years ago
parent
commit
2d8ded3e77
  1. 159
      api/Cloud API Demo.postman_collection.json
  2. 2
      pom.xml
  3. 13
      sql/cloud_sample.sql
  4. 5
      src/main/java/com/dji/sample/component/ApplicationBootInitial.java
  5. 6
      src/main/java/com/dji/sample/component/GlobalExceptionHandler.java
  6. 13
      src/main/java/com/dji/sample/component/GlobalScheduleService.java
  7. 5
      src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java
  8. 2
      src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java
  9. 2
      src/main/java/com/dji/sample/component/mqtt/model/DeviceTopicEnum.java
  10. 2
      src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java
  11. 46
      src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java
  12. 2
      src/main/java/com/dji/sample/component/oss/service/IOssService.java
  13. 53
      src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java
  14. 62
      src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java
  15. 38
      src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java
  16. 6
      src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java
  17. 15
      src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java
  18. 4
      src/main/java/com/dji/sample/component/redis/RedisConst.java
  19. 61
      src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
  20. 6
      src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java
  21. 22
      src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java
  22. 29
      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. 31
      src/main/java/com/dji/sample/control/model/dto/LinkWorkMode.java
  25. 29
      src/main/java/com/dji/sample/control/model/enums/LinkWorkModeEnum.java
  26. 11
      src/main/java/com/dji/sample/control/model/enums/RemoteControlMethodEnum.java
  27. 20
      src/main/java/com/dji/sample/control/service/impl/ControlServiceImpl.java
  28. 76
      src/main/java/com/dji/sample/manage/controller/DeviceFirmwareController.java
  29. 6
      src/main/java/com/dji/sample/manage/model/dto/DeviceFirmwareDTO.java
  30. 28
      src/main/java/com/dji/sample/manage/model/dto/FirmwareFileProperties.java
  31. 10
      src/main/java/com/dji/sample/manage/model/entity/DeviceFirmwareEntity.java
  32. 7
      src/main/java/com/dji/sample/manage/model/enums/DeviceSetPropertyEnum.java
  33. 18
      src/main/java/com/dji/sample/manage/model/enums/StateSwitchEnum.java
  34. 30
      src/main/java/com/dji/sample/manage/model/enums/StateSwitchReceiver.java
  35. 32
      src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareQueryParam.java
  36. 17
      src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareUpdateParam.java
  37. 23
      src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareUploadParam.java
  38. 8
      src/main/java/com/dji/sample/manage/model/receiver/DistanceLimitStatusReceiver.java
  39. 2
      src/main/java/com/dji/sample/manage/model/receiver/HeightLimitReceiver.java
  40. 28
      src/main/java/com/dji/sample/manage/model/receiver/NightLightsStateReceiver.java
  41. 14
      src/main/java/com/dji/sample/manage/model/receiver/ObstacleAvoidanceReceiver.java
  42. 43
      src/main/java/com/dji/sample/manage/service/IDeviceFirmwareService.java
  43. 11
      src/main/java/com/dji/sample/manage/service/impl/CapacityCameraServiceImpl.java
  44. 188
      src/main/java/com/dji/sample/manage/service/impl/DeviceFirmwareServiceImpl.java
  45. 11
      src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java
  46. 11
      src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java
  47. 70
      src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
  48. 9
      src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java
  49. 7
      src/main/java/com/dji/sample/manage/service/impl/LogsFileServiceImpl.java
  50. 2
      src/main/java/com/dji/sample/media/controller/FileController.java
  51. 30
      src/main/java/com/dji/sample/media/model/MediaFileCountDTO.java
  52. 2
      src/main/java/com/dji/sample/media/model/MediaFileDTO.java
  53. 20
      src/main/java/com/dji/sample/media/model/MediaMethodEnum.java
  54. 10
      src/main/java/com/dji/sample/media/service/IFileService.java
  55. 8
      src/main/java/com/dji/sample/media/service/IMediaService.java
  56. 19
      src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
  57. 147
      src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java
  58. 13
      src/main/java/com/dji/sample/storage/service/impl/StorageServiceImpl.java
  59. 1
      src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java
  60. 13
      src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
  61. 4
      src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java
  62. 7
      src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java
  63. 24
      src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java
  64. 15
      src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java
  65. 73
      src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java
  66. 4
      src/main/resources/application.yml
  67. 37363
      src/main/resources/hms.json

159
api/Cloud API Demo.postman_collection.json

@ -761,6 +761,125 @@ @@ -761,6 +761,125 @@
}
},
"response": []
},
{
"name": "Get All Firmwares",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/firmwares?page=1&page_size=50",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"firmwares"
],
"query": [
{
"key": "device_name",
"value": null,
"disabled": true
},
{
"key": "product_version",
"value": null,
"disabled": true
},
{
"key": "status",
"value": "true",
"disabled": true
},
{
"key": "page",
"value": "1"
},
{
"key": "page_size",
"value": "50"
}
]
}
},
"response": []
},
{
"name": "Import Firmware File",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": []
},
{
"key": "release_note",
"value": "123",
"type": "text"
},
{
"key": "device_name",
"value": "DJI Dock",
"type": "text"
},
{
"key": "status",
"value": "0",
"type": "text"
}
]
},
"url": {
"raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/firmwares/file/upload",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"firmwares",
"file",
"upload"
]
}
},
"response": []
},
{
"name": "Change Firmware Status",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"status\": false\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/firmwares/{{firmware_id}}",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"firmwares",
"{{firmware_id}}"
]
}
},
"response": []
}
],
"auth": {
@ -768,7 +887,7 @@ @@ -768,7 +887,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Njc0NzcwNTUsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2Njc1NjM0NTUsImlhdCI6MTY2NzQ3NzA1NSwidXNlcm5hbWUiOiJhZG1pblBDIn0.VMJ0ZKn895uvkMDjg2fw3p4trVCUx9ltVFKeP7QmYpo",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NzAzMTU2MDEsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NzA0MDIwMDEsImlhdCI6MTY3MDMxNTYwMSwidXNlcm5hbWUiOiJhZG1pblBDIn0.yh8SkHZVsoIXo_vtlTGNB-ZX92XayalGe_q7mNRVcdI",
"type": "string"
},
{
@ -1539,6 +1658,27 @@ @@ -1539,6 +1658,27 @@
}
},
"response": []
},
{
"name": "Set Media Highest",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{base_url}}{{wayline_version}}/workspaces/{{workspace_id}}/jobs/{{job_id}}/media-highest",
"host": [
"{{base_url}}{{wayline_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"jobs",
"{{job_id}}",
"media-highest"
]
}
},
"response": []
}
],
"auth": {
@ -1585,16 +1725,25 @@ @@ -1585,16 +1725,25 @@
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"action\": 0\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{control_version}}/devices/4TADK7E000000H/jobs/debug_mode_close",
"raw": "{{base_url}}{{control_version}}/devices/{{device_sn}}/jobs/alarm_state_switch",
"host": [
"{{base_url}}{{control_version}}"
],
"path": [
"devices",
"4TADK7E000000H",
"{{device_sn}}",
"jobs",
"debug_mode_close"
"alarm_state_switch"
]
}
},
@ -1606,7 +1755,7 @@ @@ -1606,7 +1755,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Njg0MzE5MzQsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2Njg1MTgzMzQsImlhdCI6MTY2ODQzMTkzNCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QU9xHBeQPHJ2V1vXQcGGWRQ-gYEOWDpaTTXIQga85BU",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Njk2MzMzMzQsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2Njk3MTk3MzQsImlhdCI6MTY2OTYzMzMzNCwidXNlcm5hbWUiOiJhZG1pblBDIn0.OoIfdpyI5eL6bFm8akq8_stzClQU41YpIJkx6_kxVHU",
"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.0</version>
<version>1.3.1</version>
<name>cloud-api-sample</name>
<properties>

13
sql/cloud_sample.sql

@ -148,12 +148,14 @@ CREATE TABLE `manage_device_firmware` ( @@ -148,12 +148,14 @@ CREATE TABLE `manage_device_firmware` (
`firmware_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'uuid',
`file_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined' COMMENT 'The file name of the firmware package, including the file suffix',
`firmware_version` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'It needs to be formatted according to the official firmware version. 00.00.0000',
`file_url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The download address for the firmware package.',
`object_key` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'The object key of the firmware package in the bucket.',
`file_size` int NOT NULL COMMENT 'The size of the firmware package.',
`file_md5` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The md5 of the firmware package.',
`device_name` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'model of the device. This parameter corresponds to the device name in the device dictionary table.',
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`release_note` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The release note of the firmware package.',
`release_date` bigint NOT NULL COMMENT 'The release date of the firmware package.',
`user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'The name of the creator.',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Availability of the firmware package. 1: available; 0: unavailable',
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
@ -161,15 +163,6 @@ CREATE TABLE `manage_device_firmware` ( @@ -161,15 +163,6 @@ CREATE TABLE `manage_device_firmware` (
UNIQUE KEY `UNIQUE_firmware_id` (`firmware_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='Firmware file information';
LOCK TABLES `manage_device_firmware` WRITE;
/*!40000 ALTER TABLE `manage_device_firmware` DISABLE KEYS */;
INSERT INTO `manage_device_firmware` (`id`, `firmware_id`, `file_name`, `firmware_version`, `file_url`, `file_size`, `file_md5`, `device_name`, `release_note`, `release_date`, `status`, `create_time`, `update_time`)
VALUES
(1,'1','Matrice_M30_Series_UAV_V04.01.00.20_Only_For_Pilot.zip','04.01.0020','https://terra-sz-hc1pro-cloudapi.oss-cn-shenzhen.aliyuncs.com/c0af9fe0d7eb4f35a8fe5b695e4d0b96/docker/Matrice_M30_Series_UAV_V04.01.00.20_Only_For_Pilot.zip',605830726,'601630a5c753cd6665974cc8fd791bf5','Matrice 30','release note',1663232356810,1,1663232356810,1663232356810);
/*!40000 ALTER TABLE `manage_device_firmware` ENABLE KEYS */;
UNLOCK TABLES;
# manage_device_hms

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

@ -18,9 +18,6 @@ public class ApplicationBootInitial implements CommandLineRunner { @@ -18,9 +18,6 @@ public class ApplicationBootInitial implements CommandLineRunner {
@Autowired
private IDeviceService deviceService;
@Autowired
private RedisOpsUtils redisOps;
/**
* Subscribe to the devices that exist in the redis when the program starts,
* to prevent the data from being different from the pilot side due to program interruptions.
@ -31,7 +28,7 @@ public class ApplicationBootInitial implements CommandLineRunner { @@ -31,7 +28,7 @@ public class ApplicationBootInitial implements CommandLineRunner {
public void run(String... args) throws Exception {
int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
redisOps.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*")
RedisOpsUtils.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*")
.forEach(key -> deviceService.subscribeTopicOnline(key.substring(start)));
}

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

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package com.dji.sample.component;
import com.dji.sample.common.model.ResponseResult;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ -32,8 +33,9 @@ public class GlobalExceptionHandler { @@ -32,8 +33,9 @@ public class GlobalExceptionHandler {
return ResponseResult.error("A null object appeared.");
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
public ResponseResult methodArgumentNotValidExceptionHandler(BindException e) {
e.printStackTrace();
return ResponseResult.error(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
}

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

@ -6,6 +6,7 @@ import com.dji.sample.component.redis.RedisOpsUtils; @@ -6,6 +6,7 @@ import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.wayline.service.IWaylineJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@ -27,10 +28,10 @@ public class GlobalScheduleService { @@ -27,10 +28,10 @@ public class GlobalScheduleService {
private IDeviceService deviceService;
@Autowired
private RedisOpsUtils redisOps;
private IMqttTopicService topicService;
@Autowired
private IMqttTopicService topicService;
private IWaylineJobService waylineJobService;
/**
* Check the status of the devices every 30 seconds. It is recommended to use cache.
@ -39,17 +40,17 @@ public class GlobalScheduleService { @@ -39,17 +40,17 @@ public class GlobalScheduleService {
private void deviceStatusListen() {
int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
redisOps.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*").forEach(key -> {
long expire = redisOps.getExpire(key);
RedisOpsUtils.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*").forEach(key -> {
long expire = RedisOpsUtils.getExpire(key);
if (expire <= 30) {
DeviceDTO device = (DeviceDTO) redisOps.get(key);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(key);
if (device.getDomain().equals(DeviceDomainEnum.SUB_DEVICE.getDesc())) {
deviceService.subDeviceOffline(key.substring(start));
} else {
deviceService.unsubscribeTopicOffline(key.substring(start));
deviceService.pushDeviceOfflineTopo(device.getWorkspaceId(), device.getDeviceSn());
}
redisOps.del(key);
RedisOpsUtils.del(key);
}
});

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

@ -167,4 +167,9 @@ public class MqttMessageChannel { @@ -167,4 +167,9 @@ public class MqttMessageChannel {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA)
public MessageChannel eventsHighestPriorityUploadFlightTaskMedia() {
return new DirectChannel();
}
}

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

@ -74,4 +74,6 @@ public class ChannelName { @@ -74,4 +74,6 @@ public class ChannelName {
public static final String INBOUND_PROPERTY_SET_REPLY = "inboundPropertySetReply";
public static final String INBOUND_REQUESTS_CONFIG = "inboundRequestsConfig";
public static final String INBOUND_EVENTS_HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA = "inboundEventsHighestPriorityUploadFlightTaskMedia";
}

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

@ -29,7 +29,7 @@ public enum DeviceTopicEnum { @@ -29,7 +29,7 @@ public enum DeviceTopicEnum {
PROPERTY_SET_REPLY(Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + PROPERTY_SUF + SET_SUF + _REPLY_SUF + "$"), ChannelName.INBOUND_PROPERTY_SET_REPLY),
UNKNOWN(null, ChannelName.DEFAULT);
UNKNOWN(Pattern.compile("^.*$"), ChannelName.DEFAULT);
Pattern pattern;

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

@ -43,6 +43,8 @@ public enum EventsMethodEnum { @@ -43,6 +43,8 @@ public enum EventsMethodEnum {
FILE_UPLOAD_PROGRESS("fileupload_progress", ChannelName.INBOUND_EVENTS_FILE_UPLOAD_PROGRESS),
HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA("highest_priority_upload_flighttask_media", ChannelName.INBOUND_EVENTS_HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA),
UNKNOWN("Unknown", ChannelName.DEFAULT);
private String method;

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

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

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

@ -45,4 +45,6 @@ public interface IOssService { @@ -45,4 +45,6 @@ public interface IOssService {
InputStream getObject(String bucket, String objectKey);
void putObject(String bucket, String objectKey, InputStream input);
void createClient();
}

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

@ -3,7 +3,6 @@ package com.dji.sample.component.oss.service.impl; @@ -3,7 +3,6 @@ package com.dji.sample.component.oss.service.impl;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
@ -18,14 +17,12 @@ import com.dji.sample.component.oss.model.enums.OssTypeEnum; @@ -18,14 +17,12 @@ import com.dji.sample.component.oss.model.enums.OssTypeEnum;
import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.Objects;
/**
* @author sean
@ -36,9 +33,8 @@ import java.util.Date; @@ -36,9 +33,8 @@ import java.util.Date;
@Slf4j
public class AliyunOssServiceImpl implements IOssService {
@Autowired
public OssConfiguration configuration;
private OSS ossClient;
@Override
public String getOssType() {
return OssTypeEnum.ALIYUN.getType();
@ -49,16 +45,16 @@ public class AliyunOssServiceImpl implements IOssService { @@ -49,16 +45,16 @@ public class AliyunOssServiceImpl implements IOssService {
try {
DefaultProfile profile = DefaultProfile.getProfile(
configuration.getRegion(), configuration.getAccessKey(), configuration.getSecretKey());
OssConfiguration.region, OssConfiguration.accessKey, OssConfiguration.secretKey);
IAcsClient client = new DefaultAcsClient(profile);
AssumeRoleRequest request = new AssumeRoleRequest();
request.setDurationSeconds(configuration.getExpire());
request.setRoleArn(configuration.getRoleArn());
request.setRoleSessionName(configuration.getRoleSessionName());
request.setDurationSeconds(OssConfiguration.expire);
request.setRoleArn(OssConfiguration.roleArn);
request.setRoleSessionName(OssConfiguration.roleSessionName);
AssumeRoleResponse response = client.getAcsResponse(request);
return new CredentialsDTO(response.getCredentials(), configuration.getExpire());
return new CredentialsDTO(response.getCredentials(), OssConfiguration.expire);
} catch (ClientException e) {
log.debug("Failed to obtain sts.");
@ -69,10 +65,6 @@ public class AliyunOssServiceImpl implements IOssService { @@ -69,10 +65,6 @@ public class AliyunOssServiceImpl implements IOssService {
@Override
public URL getObjectUrl(String bucket, String objectKey) {
if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) {
return null;
}
OSS ossClient = this.createClient();
// First check if the object can be fetched.
boolean isExist = ossClient.doesObjectExist(bucket, objectKey);
if (!isExist) {
@ -80,50 +72,37 @@ public class AliyunOssServiceImpl implements IOssService { @@ -80,50 +72,37 @@ public class AliyunOssServiceImpl implements IOssService {
}
return ossClient.generatePresignedUrl(bucket, objectKey,
new Date(System.currentTimeMillis() + configuration.getExpire() * 1000));
new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000));
}
@Override
public Boolean deleteObject(String bucket, String objectKey) {
OSS ossClient = this.createClient();
if (!ossClient.doesObjectExist(bucket, objectKey)) {
ossClient.shutdown();
return true;
}
ossClient.deleteObject(bucket, objectKey);
ossClient.shutdown();
return true;
}
@Override
public InputStream getObject(String bucket, String objectKey) {
OSS ossClient = this.createClient();
OSSObject object = ossClient.getObject(bucket, objectKey);
try (InputStream input = object.getObjectContent()) {
return input;
} catch (IOException e) {
e.printStackTrace();
} finally {
ossClient.shutdown();
}
return InputStream.nullInputStream();
return ossClient.getObject(bucket, objectKey).getObjectContent();
}
@Override
public void putObject(String bucket, String objectKey, InputStream input) {
OSS ossClient = this.createClient();
if (ossClient.doesObjectExist(bucket, objectKey)) {
ossClient.shutdown();
throw new RuntimeException("The filename already exists.");
}
PutObjectResult objectResult = ossClient.putObject(new PutObjectRequest(bucket, objectKey, input, new ObjectMetadata()));
ossClient.shutdown();
log.info("Upload File: {}", objectResult.getETag());
}
private OSS createClient() {
return new OSSClientBuilder()
.build(configuration.getEndpoint(), configuration.getAccessKey(), configuration.getSecretKey());
public void createClient() {
if (Objects.nonNull(this.ossClient)) {
return;
}
this.ossClient = new OSSClientBuilder()
.build(OssConfiguration.endpoint, OssConfiguration.accessKey, OssConfiguration.secretKey);
}
}

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

@ -17,16 +17,15 @@ import com.dji.sample.component.oss.model.enums.OssTypeEnum; @@ -17,16 +17,15 @@ import com.dji.sample.component.oss.model.enums.OssTypeEnum;
import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* @author sean
@ -37,9 +36,8 @@ import java.util.List; @@ -37,9 +36,8 @@ import java.util.List;
@Service
public class AmazonS3ServiceImpl implements IOssService {
@Autowired
private OssConfiguration configuration;
private AmazonS3 client;
@Override
public String getOssType() {
return OssTypeEnum.AWS.getType();
@ -49,71 +47,55 @@ public class AmazonS3ServiceImpl implements IOssService { @@ -49,71 +47,55 @@ public class AmazonS3ServiceImpl implements IOssService {
public CredentialsDTO getCredentials() {
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(
new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey())))
.withRegion(configuration.getRegion()).build();
new BasicAWSCredentials(OssConfiguration.accessKey, OssConfiguration.secretKey)))
.withRegion(OssConfiguration.region).build();
AssumeRoleRequest request = new AssumeRoleRequest()
.withRoleArn(configuration.getRoleArn())
.withRoleSessionName(configuration.getRoleSessionName())
.withDurationSeconds(Math.toIntExact(configuration.getExpire()));
.withRoleArn(OssConfiguration.roleArn)
.withRoleSessionName(OssConfiguration.roleSessionName)
.withDurationSeconds(Math.toIntExact(OssConfiguration.expire));
AssumeRoleResult result = stsClient.assumeRole(request);
Credentials credentials = result.getCredentials();
stsClient.shutdown();
return new CredentialsDTO(credentials);
}
@Override
public URL getObjectUrl(String bucket, String objectKey) {
AmazonS3 client = this.createClient();
URL url = client.generatePresignedUrl(bucket, objectKey,
new Date(System.currentTimeMillis() + configuration.getExpire() * 1000), HttpMethod.GET);
client.shutdown();
return url;
return client.generatePresignedUrl(bucket, objectKey,
new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000), HttpMethod.GET);
}
@Override
public Boolean deleteObject(String bucket, String objectKey) {
AmazonS3 client = this.createClient();
if (!client.doesObjectExist(bucket, objectKey)) {
client.shutdown();
return true;
}
client.deleteObject(bucket, objectKey);
client.shutdown();
return true;
}
public InputStream getObject(String bucket, String objectKey) {
AmazonS3 client = this.createClient();
S3Object object = client.getObject(bucket, objectKey);
try (InputStream input = object.getObjectContent().getDelegateStream()) {
return input;
} catch (IOException e) {
e.printStackTrace();
} finally {
client.shutdown();
}
return InputStream.nullInputStream();
return client.getObject(bucket, objectKey).getObjectContent().getDelegateStream();
}
@Override
public void putObject(String bucket, String objectKey, InputStream input) {
AmazonS3 client = this.createClient();
if (client.doesObjectExist(bucket, objectKey)) {
client.shutdown();
throw new RuntimeException("The filename already exists.");
}
PutObjectResult objectResult = client.putObject(new PutObjectRequest(bucket, objectKey, input, new ObjectMetadata()));
client.shutdown();
log.info("Upload File: {}", objectResult.toString());
}
private AmazonS3 createClient() {
return AmazonS3ClientBuilder.standard()
public void createClient() {
if (Objects.nonNull(this.client)) {
return;
}
this.client = AmazonS3ClientBuilder.standard()
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey())))
.withRegion(configuration.getRegion())
new BasicAWSCredentials(OssConfiguration.accessKey, OssConfiguration.secretKey)))
.withRegion(OssConfiguration.region)
.build();
}
@ -122,7 +104,7 @@ public class AmazonS3ServiceImpl implements IOssService { @@ -122,7 +104,7 @@ public class AmazonS3ServiceImpl implements IOssService {
*/
@PostConstruct
private void configCORS() {
if (!configuration.isEnable() || !OssTypeEnum.AWS.getType().equals(configuration.getProvider())) {
if (!OssConfiguration.enable || !OssTypeEnum.AWS.getType().equals(OssConfiguration.provider)) {
return;
}
List<CORSRule.AllowedMethods> allowedMethods = new ArrayList<>();
@ -136,10 +118,8 @@ public class AmazonS3ServiceImpl implements IOssService { @@ -136,10 +118,8 @@ public class AmazonS3ServiceImpl implements IOssService {
.withAllowedHeaders(List.of(AuthInterceptor.PARAM_TOKEN))
.withAllowedMethods(allowedMethods);
AmazonS3 client = this.createClient();
client.setBucketCrossOriginConfiguration(this.configuration.getBucket(),
client.setBucketCrossOriginConfiguration(OssConfiguration.bucket,
new BucketCrossOriginConfiguration().withRules(rule));
client.shutdown();
}
}

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

@ -9,7 +9,6 @@ import io.minio.credentials.AssumeRoleProvider; @@ -9,7 +9,6 @@ import io.minio.credentials.AssumeRoleProvider;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
@ -30,10 +29,7 @@ import java.util.Objects; @@ -30,10 +29,7 @@ import java.util.Objects;
public class MinIOServiceImpl implements IOssService {
private MinioClient client;
@Autowired
private OssConfiguration configuration;
@Override
public String getOssType() {
return OssTypeEnum.MINIO.getType();
@ -42,10 +38,10 @@ public class MinIOServiceImpl implements IOssService { @@ -42,10 +38,10 @@ public class MinIOServiceImpl implements IOssService {
@Override
public CredentialsDTO getCredentials() {
try {
AssumeRoleProvider provider = new AssumeRoleProvider(configuration.getEndpoint(), configuration.getAccessKey(),
configuration.getSecretKey(), Math.toIntExact(configuration.getExpire()),
null, configuration.getRegion(), null, null, null, null);
return new CredentialsDTO(provider.fetch(), configuration.getExpire());
AssumeRoleProvider provider = new AssumeRoleProvider(OssConfiguration.endpoint, OssConfiguration.accessKey,
OssConfiguration.secretKey, Math.toIntExact(OssConfiguration.expire),
null, OssConfiguration.region, null, null, null, null);
return new CredentialsDTO(provider.fetch(), OssConfiguration.expire);
} catch (NoSuchAlgorithmException e) {
log.debug("Failed to obtain sts.");
e.printStackTrace();
@ -57,26 +53,22 @@ public class MinIOServiceImpl implements IOssService { @@ -57,26 +53,22 @@ public class MinIOServiceImpl implements IOssService {
public URL getObjectUrl(String bucket, String objectKey) {
try {
return new URL(
this.createClient()
.getPresignedObjectUrl(
client.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(objectKey)
.expiry(Math.toIntExact(configuration.getExpire()))
.expiry(Math.toIntExact(OssConfiguration.expire))
.build()));
} catch (ErrorResponseException | InsufficientDataException | InternalException |
InvalidKeyException | InvalidResponseException | IOException |
NoSuchAlgorithmException | XmlParserException | ServerException e) {
log.error("The file does not exist on the OssConfiguration.");
e.printStackTrace();
throw new RuntimeException("The file does not exist on the OssConfiguration.");
}
return null;
}
@Override
public Boolean deleteObject(String bucket, String objectKey) {
MinioClient client = this.createClient();
try {
client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build());
} catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e) {
@ -90,7 +82,7 @@ public class MinIOServiceImpl implements IOssService { @@ -90,7 +82,7 @@ public class MinIOServiceImpl implements IOssService {
@Override
public InputStream getObject(String bucket, String objectKey) {
try {
GetObjectResponse object = this.createClient().getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build());
GetObjectResponse object = client.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build());
return new ByteArrayInputStream(object.readAllBytes());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
@ -101,7 +93,6 @@ public class MinIOServiceImpl implements IOssService { @@ -101,7 +93,6 @@ public class MinIOServiceImpl implements IOssService {
@Override
public void putObject(String bucket, String objectKey, InputStream input) {
try {
MinioClient client = this.createClient();
client.statObject(StatObjectArgs.builder().bucket(bucket).object(objectKey).build());
throw new RuntimeException("The filename already exists.");
} catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) {
@ -117,15 +108,14 @@ public class MinIOServiceImpl implements IOssService { @@ -117,15 +108,14 @@ public class MinIOServiceImpl implements IOssService {
}
}
private MinioClient createClient() {
public void createClient() {
if (Objects.nonNull(this.client)) {
return this.client;
return;
}
this.client = MinioClient.builder()
.endpoint(configuration.getEndpoint())
.credentials(configuration.getAccessKey(), configuration.getSecretKey())
.region(configuration.getRegion())
.endpoint(OssConfiguration.endpoint)
.credentials(OssConfiguration.accessKey, OssConfiguration.secretKey)
.region(OssConfiguration.region)
.build();
return this.client;
}
}

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

@ -18,16 +18,14 @@ public class OssAspectHandler { @@ -18,16 +18,14 @@ public class OssAspectHandler {
@Autowired
private OssServiceContext ossServiceContext;
@Autowired
private OssConfiguration configuration;
@Before("execution(public * com.dji.sample.component.oss.service.impl.OssServiceContext.*(..))")
public void before() {
if (!this.configuration.isEnable()) {
if (!OssConfiguration.enable) {
throw new IllegalArgumentException("Please enable OssConfiguration.");
}
if (this.ossServiceContext.getOssService() == null) {
throw new IllegalArgumentException("Please check the OssConfiguration configuration.");
}
this.ossServiceContext.createClient();
}
}

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

@ -6,6 +6,7 @@ import com.dji.sample.component.oss.service.IOssService; @@ -6,6 +6,7 @@ import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.InputStream;
import java.net.URL;
@ -22,16 +23,13 @@ public class OssServiceContext { @@ -22,16 +23,13 @@ public class OssServiceContext {
private IOssService ossService;
private OssConfiguration configuration;
@Autowired
public OssServiceContext(List<IOssService> ossServices, OssConfiguration configuration) {
this.configuration = configuration;
if (!configuration.isEnable()) {
if (!OssConfiguration.enable) {
return;
}
this.ossService = ossServices.stream()
.filter(ossService -> ossService.getOssType().equals(configuration.getProvider()))
.filter(ossService -> ossService.getOssType().equals(OssConfiguration.provider))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Oss provider is illegal. Optional: " +
Arrays.toString(Arrays.stream(OssTypeEnum.values()).map(OssTypeEnum::getType).toArray())));
@ -46,6 +44,9 @@ public class OssServiceContext { @@ -46,6 +44,9 @@ public class OssServiceContext {
}
public URL getObjectUrl(String bucket, String objectKey) {
if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) {
throw new IllegalArgumentException();
}
return this.ossService.getObjectUrl(bucket, objectKey);
}
@ -60,4 +61,8 @@ public class OssServiceContext { @@ -60,4 +61,8 @@ public class OssServiceContext {
public void putObject(String bucket, String objectKey, InputStream stream) {
this.ossService.putObject(bucket, objectKey, stream);
}
void createClient() {
this.ossService.createClient();
}
}

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

@ -38,4 +38,8 @@ public final class RedisConst { @@ -38,4 +38,8 @@ public final class RedisConst {
public static final String WAYLINE_JOB = "wayline_job";
public static final String OSD_PREFIX = "osd" + DELIMITER;
public static final String MEDIA_FILE_PREFIX = "media_file" + DELIMITER;
public static final String MEDIA_HIGHEST_PRIORITY_PREFIX = "media_highest_priority" + DELIMITER;
}

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

@ -17,8 +17,12 @@ import java.util.concurrent.TimeUnit; @@ -17,8 +17,12 @@ import java.util.concurrent.TimeUnit;
@Component
public class RedisOpsUtils {
private static RedisTemplate<String, Object> redisTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
RedisOpsUtils.redisTemplate = redisTemplate;
}
/**
* HSET
@ -26,7 +30,7 @@ public class RedisOpsUtils { @@ -26,7 +30,7 @@ public class RedisOpsUtils {
* @param field
* @param value
*/
public void hashSet(String key, String field, Object value) {
public static void hashSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
@ -36,7 +40,7 @@ public class RedisOpsUtils { @@ -36,7 +40,7 @@ public class RedisOpsUtils {
* @param field
* @return
*/
public Object hashGet(String key, String field) {
public static Object hashGet(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
@ -45,7 +49,7 @@ public class RedisOpsUtils { @@ -45,7 +49,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public Set<Object> hashKeys(String key) {
public static Set<Object> hashKeys(String key) {
return redisTemplate.opsForHash().keys(key);
}
@ -55,7 +59,7 @@ public class RedisOpsUtils { @@ -55,7 +59,7 @@ public class RedisOpsUtils {
* @param field
* @return
*/
public boolean hashCheck(String key, String field) {
public static boolean hashCheck(String key, String field) {
return redisTemplate.opsForHash().hasKey(key, field);
}
@ -65,17 +69,26 @@ public class RedisOpsUtils { @@ -65,17 +69,26 @@ public class RedisOpsUtils {
* @param fields
* @return
*/
public boolean hashDel(String key, Object[] fields) {
public static boolean hashDel(String key, Object[] fields) {
return redisTemplate.opsForHash().delete(key, fields) > 0;
}
/**
* HLEN
* @param key
* @return
*/
public static long hashLen(String key) {
return redisTemplate.opsForHash().size(key);
}
/**
* EXPIRE
* @param key
* @param timeout
* @return
*/
public boolean expireKey(String key, long timeout) {
public static boolean expireKey(String key, long timeout) {
return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
@ -84,7 +97,7 @@ public class RedisOpsUtils { @@ -84,7 +97,7 @@ public class RedisOpsUtils {
* @param key
* @param value
*/
public void set(String key, Object value) {
public static void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
@ -93,7 +106,7 @@ public class RedisOpsUtils { @@ -93,7 +106,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public Object get(String key) {
public static Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
@ -103,7 +116,7 @@ public class RedisOpsUtils { @@ -103,7 +116,7 @@ public class RedisOpsUtils {
* @param value
* @param expire
*/
public void setWithExpire(String key, Object value, long expire) {
public static void setWithExpire(String key, Object value, long expire) {
redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
}
@ -112,7 +125,7 @@ public class RedisOpsUtils { @@ -112,7 +125,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public long getExpire(String key) {
public static long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
@ -121,7 +134,7 @@ public class RedisOpsUtils { @@ -121,7 +134,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public boolean checkExist(String key) {
public static boolean checkExist(String key) {
return redisTemplate.hasKey(key);
}
@ -130,8 +143,8 @@ public class RedisOpsUtils { @@ -130,8 +143,8 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public boolean del(String key) {
return this.checkExist(key) && redisTemplate.delete(key);
public static boolean del(String key) {
return RedisOpsUtils.checkExist(key) && redisTemplate.delete(key);
}
/**
@ -139,7 +152,7 @@ public class RedisOpsUtils { @@ -139,7 +152,7 @@ public class RedisOpsUtils {
* @param pattern
* @return
*/
public Set<String> getAllKeys(String pattern) {
public static Set<String> getAllKeys(String pattern) {
return redisTemplate.keys(pattern);
}
@ -148,7 +161,7 @@ public class RedisOpsUtils { @@ -148,7 +161,7 @@ public class RedisOpsUtils {
* @param key
* @param value
*/
public void listRPush(String key, Object... value) {
public static void listRPush(String key, Object... value) {
if (value.length == 0) {
return;
}
@ -164,7 +177,7 @@ public class RedisOpsUtils { @@ -164,7 +177,7 @@ public class RedisOpsUtils {
* @param end
* @return
*/
public List<Object> listGet(String key, long start, long end) {
public static List<Object> listGet(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
@ -173,7 +186,7 @@ public class RedisOpsUtils { @@ -173,7 +186,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public List<Object> listGetAll(String key) {
public static List<Object> listGetAll(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
@ -182,7 +195,7 @@ public class RedisOpsUtils { @@ -182,7 +195,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public Long listLen(String key) {
public static Long listLen(String key) {
return redisTemplate.opsForList().size(key);
}
@ -192,7 +205,7 @@ public class RedisOpsUtils { @@ -192,7 +205,7 @@ public class RedisOpsUtils {
* @param value
* @param score
*/
public Boolean zAdd(String key, Object value, double score) {
public static Boolean zAdd(String key, Object value, double score) {
return redisTemplate.opsForZSet().add(key, value, score);
}
@ -201,7 +214,7 @@ public class RedisOpsUtils { @@ -201,7 +214,7 @@ public class RedisOpsUtils {
* @param key
* @param value
*/
public Boolean zRemove(String key, Object... value) {
public static Boolean zRemove(String key, Object... value) {
return redisTemplate.opsForZSet().remove(key, value) > 0;
}
/**
@ -211,7 +224,7 @@ public class RedisOpsUtils { @@ -211,7 +224,7 @@ public class RedisOpsUtils {
* @param end
* @return
*/
public Set<Object> zRange(String key, long start, long end) {
public static Set<Object> zRange(String key, long start, long end) {
return redisTemplate.opsForZSet().range(key, start, end);
}
@ -220,7 +233,7 @@ public class RedisOpsUtils { @@ -220,7 +233,7 @@ public class RedisOpsUtils {
* @param key
* @return
*/
public Object zGetMin(String key) {
public static Object zGetMin(String key) {
Set<Object> objects = zRange(key, 0, 0);
if (CollectionUtils.isEmpty(objects)) {
return null;
@ -234,7 +247,7 @@ public class RedisOpsUtils { @@ -234,7 +247,7 @@ public class RedisOpsUtils {
* @param value
* @return
*/
public Double zScore(String key, Object value) {
public static Double zScore(String key, Object value) {
return redisTemplate.opsForZSet().score(key, value);
}

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

@ -53,7 +53,11 @@ public enum BizCodeEnum { @@ -53,7 +53,11 @@ public enum BizCodeEnum {
CHARGE_OPEN("charge_open"),
CHARGE_CLOSE("charge_close");
CHARGE_CLOSE("charge_close"),
FILE_UPLOAD_CALLBACK("file_upload_callback"),
HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA("HIGHEST_PRIORITY_UPLOAD_FLIGHTTASK_MEDIA");
private String code;

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

@ -6,7 +6,6 @@ import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession; @@ -6,7 +6,6 @@ import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@ -26,10 +25,7 @@ import java.util.stream.Collectors; @@ -26,10 +25,7 @@ import java.util.stream.Collectors;
public class WebSocketManageServiceImpl implements IWebSocketManageService {
private static final ConcurrentHashMap<String, ConcurrentWebSocketSession> SESSIONS = new ConcurrentHashMap<>(16);
@Autowired
private RedisOpsUtils redisOps;
@Override
public void put(String key, ConcurrentWebSocketSession val) {
String[] name = key.split("/");
@ -40,11 +36,11 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService { @@ -40,11 +36,11 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService {
String sessionId = val.getId();
String workspaceKey = RedisConst.WEBSOCKET_PREFIX + name[0];
String userTypeKey = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc();
redisOps.hashSet(workspaceKey, sessionId, name[2]);
redisOps.hashSet(userTypeKey, sessionId, name[2]);
RedisOpsUtils.hashSet(workspaceKey, sessionId, name[2]);
RedisOpsUtils.hashSet(userTypeKey, sessionId, name[2]);
SESSIONS.put(sessionId, val);
redisOps.expireKey(workspaceKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
redisOps.expireKey(userTypeKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
RedisOpsUtils.expireKey(workspaceKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
RedisOpsUtils.expireKey(userTypeKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
}
@Override
@ -54,8 +50,8 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService { @@ -54,8 +50,8 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService {
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]");
return;
}
redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId});
redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc(), new String[] {sessionId});
RedisOpsUtils.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId});
RedisOpsUtils.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc(), new String[] {sessionId});
SESSIONS.remove(sessionId);
}
@ -66,7 +62,7 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService { @@ -66,7 +62,7 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService {
}
String key = RedisConst.WEBSOCKET_PREFIX + workspaceId;
return redisOps.hashKeys(key)
return RedisOpsUtils.hashKeys(key)
.stream()
.map(SESSIONS::get)
.filter(Objects::nonNull)
@ -76,7 +72,7 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService { @@ -76,7 +72,7 @@ public class WebSocketManageServiceImpl implements IWebSocketManageService {
@Override
public Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType) {
String key = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(userType).getDesc();
return redisOps.hashKeys(key)
return RedisOpsUtils.hashKeys(key)
.stream()
.map(SESSIONS::get)
.filter(Objects::nonNull)

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

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
package com.dji.sample.control.model.dto;
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;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author sean
* @version 1.3
* @date 2022/11/25
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AlarmState extends BasicDeviceProperty {
private Integer action;
@Override
public boolean valid() {
return Objects.nonNull(action) && StateSwitchEnum.find(action).isPresent();
}
}

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

@ -20,10 +20,10 @@ import java.util.Objects; @@ -20,10 +20,10 @@ import java.util.Objects;
@NoArgsConstructor
public class BatteryStoreMode extends BasicDeviceProperty {
private Integer value;
private Integer action;
@Override
public boolean valid() {
return Objects.nonNull(value) && BatteryStoreModeEnum.find(value).isPresent();
return Objects.nonNull(action) && BatteryStoreModeEnum.find(action).isPresent();
}
}

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

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
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.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author sean
* @version 1.3
* @date 2022/11/25
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LinkWorkMode extends BasicDeviceProperty {
@JsonProperty("link_workmode")
private Integer linkWorkMode;
@Override
public boolean valid() {
return Objects.nonNull(linkWorkMode) && LinkWorkModeEnum.find(linkWorkMode).isPresent();
}
}

29
src/main/java/com/dji/sample/control/model/enums/LinkWorkModeEnum.java

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
package com.dji.sample.control.model.enums;
import lombok.Getter;
import java.util.Arrays;
import java.util.Optional;
/**
* @author sean
* @version 1.3
* @date 2022/11/25
*/
@Getter
public enum LinkWorkModeEnum {
SDR_ONLY(0),
SDR_WITH_4G(1);
int mode;
LinkWorkModeEnum(Integer mode) {
this.mode = mode;
}
public static Optional<LinkWorkModeEnum> find(int mode) {
return Arrays.stream(LinkWorkModeEnum.values()).filter(modeEnum -> modeEnum.mode == mode).findAny();
}
}

11
src/main/java/com/dji/sample/control/model/enums/RemoteControlMethodEnum.java

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
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.manage.model.enums.StateSwitchReceiver;
import com.dji.sample.control.model.dto.LinkWorkMode;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import lombok.Getter;
@ -25,8 +26,6 @@ public enum RemoteControlMethodEnum { @@ -25,8 +26,6 @@ public enum RemoteControlMethodEnum {
RETURN_HOME("return_home", false, null),
SDR_WORKMODE_SWITCH("sdr_workmode_switch", false, null),
DEVICE_REBOOT("device_reboot", true, null),
DRONE_OPEN("drone_open", true, null),
@ -51,11 +50,13 @@ public enum RemoteControlMethodEnum { @@ -51,11 +50,13 @@ public enum RemoteControlMethodEnum {
CHARGE_CLOSE("charge_close", true, null),
BATTERY_MAINTENANCE_SWITCH("battery_maintenance_switch", true, StateSwitchReceiver.class),
BATTERY_MAINTENANCE_SWITCH("battery_maintenance_switch", true, AlarmState.class),
ALARM_STATE_SWITCH("alarm_state_switch", true, StateSwitchReceiver.class),
ALARM_STATE_SWITCH("alarm_state_switch", true, AlarmState.class),
BATTERY_STORE_MODE_SWITCH("battery_store_mode_switch", true, BatteryStoreMode.class),
SDR_WORK_MODE_SWITCH("sdr_workmode_switch", false, LinkWorkMode.class),
UNKNOWN("unknown", false, null);

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

@ -37,9 +37,6 @@ import java.util.UUID; @@ -37,9 +37,6 @@ import java.util.UUID;
@Slf4j
public class ControlServiceImpl implements IControlService {
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private IMessageSenderService messageSenderService;
@ -62,6 +59,7 @@ public class ControlServiceImpl implements IControlService { @@ -62,6 +59,7 @@ public class ControlServiceImpl implements IControlService {
return ResponseResult.error("The " + serviceIdentifier + " method does not exist.");
}
Object data = "";
// Add parameter validation.
if (Objects.nonNull(controlMethodEnum.getClazz())) {
if (Objects.isNull(param)) {
@ -71,6 +69,7 @@ public class ControlServiceImpl implements IControlService { @@ -71,6 +69,7 @@ public class ControlServiceImpl implements IControlService {
if (!basicDeviceProperty.valid()) {
return ResponseResult.error(CommonErrorEnum.ILLEGAL_ARGUMENT);
}
data = basicDeviceProperty;
}
boolean isExist = deviceService.checkDeviceOnline(sn);
@ -85,16 +84,17 @@ public class ControlServiceImpl implements IControlService { @@ -85,16 +84,17 @@ public class ControlServiceImpl implements IControlService {
.bid(bid)
.method(serviceIdentifier)
.timestamp(System.currentTimeMillis())
.data(Objects.requireNonNullElse(param, ""))
.data(data)
.build());
ServiceReply<EventsOutputReceiver> serviceReply = mapper.convertValue(
serviceReplyOpt, new TypeReference<ServiceReply<EventsOutputReceiver>>() {});
if (ResponseResult.CODE_SUCCESS != serviceReply.getResult()) {
return ResponseResult.error(serviceReply.getResult(), serviceReply.getOutput().getStatus());
return ResponseResult.error(serviceReply.getResult(),
Objects.nonNull(serviceReply.getOutput()) ? serviceReply.getOutput().getStatus() : "error: " + serviceIdentifier);
}
if (controlMethodEnum.getProgress()) {
redisOps.setWithExpire(serviceIdentifier + RedisConst.DELIMITER + bid, sn,
RedisOpsUtils.setWithExpire(serviceIdentifier + RedisConst.DELIMITER + bid, sn,
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
}
return ResponseResult.success();
@ -104,10 +104,10 @@ public class ControlServiceImpl implements IControlService { @@ -104,10 +104,10 @@ public class ControlServiceImpl implements IControlService {
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS, outputChannel = ChannelName.OUTBOUND)
public void handleControlProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
String key = receiver.getMethod() + RedisConst.DELIMITER + receiver.getBid();
if (redisOps.getExpire(key) <= 0) {
if (RedisOpsUtils.getExpire(key) <= 0) {
return;
}
String sn = redisOps.get(key).toString();
String sn = RedisOpsUtils.get(key).toString();
EventsReceiver<EventsOutputReceiver> eventsReceiver = mapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<EventsOutputReceiver>>(){});
@ -123,10 +123,10 @@ public class ControlServiceImpl implements IControlService { @@ -123,10 +123,10 @@ public class ControlServiceImpl implements IControlService {
if (eventsReceiver.getOutput().getProgress().getPercent() == 100 ||
EventsResultStatusEnum.find(eventsReceiver.getOutput().getStatus()).getEnd()) {
redisOps.del(key);
RedisOpsUtils.del(key);
}
DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
webSocketMessageService.sendBatch(
webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal()),

76
src/main/java/com/dji/sample/manage/controller/DeviceFirmwareController.java

@ -1,18 +1,29 @@ @@ -1,18 +1,29 @@
package com.dji.sample.manage.controller;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.manage.model.dto.DeviceFirmwareDTO;
import com.dji.sample.manage.model.dto.DeviceFirmwareNoteDTO;
import com.dji.sample.manage.model.dto.FirmwareFileProperties;
import com.dji.sample.manage.model.param.DeviceFirmwareQueryParam;
import com.dji.sample.manage.model.param.DeviceFirmwareUpdateParam;
import com.dji.sample.manage.model.param.DeviceFirmwareUploadParam;
import com.dji.sample.manage.service.IDeviceFirmwareService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
/**
* @author sean
* @version 1.2
@ -20,6 +31,7 @@ import java.util.Optional; @@ -20,6 +31,7 @@ import java.util.Optional;
*/
@RestController
@RequestMapping("${url.manage.prefix}${url.manage.version}/workspaces")
@Validated
public class DeviceFirmwareController {
@Autowired
@ -40,4 +52,60 @@ public class DeviceFirmwareController { @@ -40,4 +52,60 @@ public class DeviceFirmwareController {
return ResponseResult.success(releaseNotes);
}
/**
* Query firmware information based on parameters.
* @param workspaceId
* @param param
* @return
*/
@GetMapping("/{workspace_id}/firmwares")
public ResponseResult<PaginationData<DeviceFirmwareDTO>> getAllFirmwarePagination(
@PathVariable("workspace_id") String workspaceId, @Valid DeviceFirmwareQueryParam param) {
PaginationData<DeviceFirmwareDTO> data = service.getAllFirmwarePagination(workspaceId, param);
return ResponseResult.success(data);
}
/**
* Import firmware file for device upgrades.
* @param request
* @param workspaceId
* @param file
* @param param
* @return
*/
@PostMapping("/{workspace_id}/firmwares/file/upload")
public ResponseResult importFirmwareFile(HttpServletRequest request, @PathVariable("workspace_id") String workspaceId,
@NotNull(message = "No file received.") MultipartFile file,
@Valid DeviceFirmwareUploadParam param) {
if (!file.getOriginalFilename().endsWith(FirmwareFileProperties.FIRMWARE_FILE_SUFFIX)) {
return ResponseResult.error("The file format is incorrect.");
}
CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
String creator = customClaim.getUsername();
service.importFirmwareFile(workspaceId, creator, param, file);
return ResponseResult.success();
}
/**
* Change the firmware availability status.
* @param workspaceId
* @param firmwareId
* @param param
* @return
*/
@PutMapping("/{workspace_id}/firmwares/{firmware_id}")
public ResponseResult importFirmwareFile(@PathVariable("workspace_id") String workspaceId,
@PathVariable("firmware_id") String firmwareId,
@Valid @RequestBody DeviceFirmwareUpdateParam param) {
service.updateFirmwareInfo(DeviceFirmwareDTO.builder()
.firmwareId(firmwareId).firmwareStatus(param.getStatus()).build());
return ResponseResult.success();
}
}

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

@ -24,7 +24,7 @@ public class DeviceFirmwareDTO { @@ -24,7 +24,7 @@ public class DeviceFirmwareDTO {
private String productVersion;
private String fileUrl;
private String objectKey;
private Long fileSize;
@ -37,4 +37,8 @@ public class DeviceFirmwareDTO { @@ -37,4 +37,8 @@ public class DeviceFirmwareDTO {
private LocalDate releasedTime;
private Boolean firmwareStatus;
private String workspaceId;
private String username;
}

28
src/main/java/com/dji/sample/manage/model/dto/FirmwareFileProperties.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package com.dji.sample.manage.model.dto;
/**
* @author sean
* @version 1.3
* @date 2022/12/1
*/
public class FirmwareFileProperties {
private FirmwareFileProperties() {
}
public static final String FIRMWARE_FILE_SUFFIX = ".zip";
public static final String FIRMWARE_SIG_FILE_SUFFIX = ".sig";
public static final String FIRMWARE_CONFIG_FILE_SUFFIX = ".cfg";
public static final String FIRMWARE_FILE_DELIMITER = "_";
public static final int FILENAME_VERSION_INDEX = 2;
public static final int FILENAME_RELEASE_DATE_INDEX = 3;
public static final String FILENAME_RELEASE_DATE_FORMAT = "yyyyMMdd";
}

10
src/main/java/com/dji/sample/manage/model/entity/DeviceFirmwareEntity.java

@ -34,8 +34,8 @@ public class DeviceFirmwareEntity implements Serializable { @@ -34,8 +34,8 @@ public class DeviceFirmwareEntity implements Serializable {
@TableField("firmware_version")
private String firmwareVersion;
@TableField("file_url")
private String fileUrl;
@TableField("object_key")
private String objectKey;
@TableField("file_size")
private Long fileSize;
@ -55,6 +55,12 @@ public class DeviceFirmwareEntity implements Serializable { @@ -55,6 +55,12 @@ public class DeviceFirmwareEntity implements Serializable {
@TableField("status")
private Boolean status;
@TableField("workspace_id")
private String workspaceId;
@TableField("user_name")
private String username;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Long createTime;

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

@ -1,9 +1,6 @@ @@ -1,9 +1,6 @@
package com.dji.sample.manage.model.enums;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import com.dji.sample.manage.model.receiver.DistanceLimitStatusReceiver;
import com.dji.sample.manage.model.receiver.HeightLimitReceiver;
import com.dji.sample.manage.model.receiver.ObstacleAvoidanceReceiver;
import com.dji.sample.manage.model.receiver.*;
import lombok.Getter;
import java.util.Arrays;
@ -17,7 +14,7 @@ import java.util.Optional; @@ -17,7 +14,7 @@ import java.util.Optional;
@Getter
public enum DeviceSetPropertyEnum {
NIGHT_LIGHTS_STATE("night_lights_state", StateSwitchReceiver.class),
NIGHT_LIGHTS_STATE("night_lights_state", NightLightsStateReceiver.class),
HEIGHT_LIMIT("height_limit", HeightLimitReceiver.class),

18
src/main/java/com/dji/sample/manage/model/enums/StateSwitchEnum.java

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
package com.dji.sample.manage.model.enums;
import java.util.Arrays;
import java.util.Optional;
/**
* @author sean
* @version 1.3
* @date 2022/10/28
*/
public enum StateSwitchEnum {
DISABLE, ENABLE;
public static Optional<StateSwitchEnum> find(int value) {
return Arrays.stream(StateSwitchEnum.values()).filter(state -> state.ordinal() == value).findAny();
}
}

30
src/main/java/com/dji/sample/manage/model/enums/StateSwitchReceiver.java

@ -1,30 +0,0 @@ @@ -1,30 +0,0 @@
package com.dji.sample.manage.model.enums;
import com.dji.sample.manage.model.receiver.BasicDeviceProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author sean
* @version 1.3
* @date 2022/10/28
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StateSwitchReceiver extends BasicDeviceProperty {
public static final int DISABLE = 0;
public static final int ENABLE = 1;
private Integer value;
@Override
public boolean valid() {
return Objects.nonNull(this.value) && (this.value == DISABLE || this.value == ENABLE);
}
}

32
src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareQueryParam.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package com.dji.sample.manage.model.param;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* @author sean
* @version 1.3
* @date 2022/12/1
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DeviceFirmwareQueryParam {
private String deviceName;
private String productVersion;
private Boolean status;
@NotNull
private Long page;
@NotNull
private Long pageSize;
}

17
src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareUpdateParam.java

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
package com.dji.sample.manage.model.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author sean
* @version 1.3
* @date 2022/12/6
*/
@Data
public class DeviceFirmwareUpdateParam {
@NotNull
private Boolean status;
}

23
src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareUploadParam.java

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
package com.dji.sample.manage.model.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author sean
* @version 1.3
* @date 2022/12/1
*/
@Data
public class DeviceFirmwareUploadParam {
@NotNull
private String releaseNote;
@NotNull
private Boolean status;
@NotNull
private String deviceName;
}

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

@ -1,8 +1,9 @@ @@ -1,8 +1,9 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.StateSwitchReceiver;
import com.dji.sample.manage.model.enums.StateSwitchEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
@ -13,6 +14,7 @@ import java.util.Objects; @@ -13,6 +14,7 @@ import java.util.Objects;
* @version 1.3
* @date 2022/10/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@ -30,10 +32,10 @@ public class DistanceLimitStatusReceiver extends BasicDeviceProperty { @@ -30,10 +32,10 @@ public class DistanceLimitStatusReceiver extends BasicDeviceProperty {
public boolean valid() {
boolean valid = Objects.nonNull(state) || Objects.nonNull(distanceLimit);
if (Objects.nonNull(state)) {
valid = new StateSwitchReceiver(this.state).valid();
valid = StateSwitchEnum.find(state).isPresent();
}
if (Objects.nonNull(distanceLimit)) {
valid &= distanceLimit >= DISTANCE_MIN && distanceLimit <= DISTANCE_MAX;
valid &= StateSwitchEnum.find(distanceLimit).isPresent();
}
return valid;
}

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

@ -2,6 +2,7 @@ package com.dji.sample.manage.model.receiver; @@ -2,6 +2,7 @@ package com.dji.sample.manage.model.receiver;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
@ -11,6 +12,7 @@ import java.util.Objects; @@ -11,6 +12,7 @@ import java.util.Objects;
* @version 1.3
* @date 2022/10/28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor

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

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.StateSwitchEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Objects;
/**
* @author sean
* @version 1.3
* @date 2022/11/25
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NightLightsStateReceiver extends BasicDeviceProperty {
private Integer value;
@Override
public boolean valid() {
return Objects.nonNull(value) && StateSwitchEnum.find(value).isPresent();
}
}

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

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.StateSwitchReceiver;
import com.dji.sample.manage.model.enums.StateSwitchEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Objects;
@ -10,6 +11,7 @@ import java.util.Objects; @@ -10,6 +11,7 @@ import java.util.Objects;
* @version 1.3
* @date 2022/10/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class ObstacleAvoidanceReceiver extends BasicDeviceProperty {
@ -23,18 +25,14 @@ public class ObstacleAvoidanceReceiver extends BasicDeviceProperty { @@ -23,18 +25,14 @@ public class ObstacleAvoidanceReceiver extends BasicDeviceProperty {
public boolean valid() {
boolean valid = Objects.nonNull(this.horizon) || Objects.nonNull(this.upside) || Objects.nonNull(this.downside);
StateSwitchReceiver stateSwitch = new StateSwitchReceiver();
if (Objects.nonNull(this.horizon)) {
stateSwitch.setValue(this.horizon);
valid = stateSwitch.valid();
valid = StateSwitchEnum.find(horizon).isPresent();
}
if (Objects.nonNull(this.upside)) {
stateSwitch.setValue(this.upside);
valid &= stateSwitch.valid();
valid &= StateSwitchEnum.find(upside).isPresent();
}
if (Objects.nonNull(this.downside)) {
stateSwitch.setValue(this.downside);
valid &= stateSwitch.valid();
valid &= StateSwitchEnum.find(downside).isPresent();
}
return valid;
}

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

@ -1,11 +1,15 @@ @@ -1,11 +1,15 @@
package com.dji.sample.manage.service;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.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;
import java.util.Optional;
@ -45,4 +49,43 @@ public interface IDeviceFirmwareService { @@ -45,4 +49,43 @@ public interface IDeviceFirmwareService {
* @param headers
*/
void handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers);
/**
* Query firmware version information by page.
*
* @param workspaceId
* @param param
* @return
*/
PaginationData<DeviceFirmwareDTO> getAllFirmwarePagination(String workspaceId, DeviceFirmwareQueryParam param);
/**
* Checks for file existence based on md5.
*
* @param workspaceId
* @param fileMd5
* @return
*/
Boolean checkFileExist(String workspaceId, String fileMd5);
/**
* Import firmware file for device upgrades.
* @param workspaceId
* @param creator
* @param param
* @param file
*/
void importFirmwareFile(String workspaceId, String creator, DeviceFirmwareUploadParam param, MultipartFile file);
/**
* Save the file information of the firmware.
* @param firmware
*/
void saveFirmwareInfo(DeviceFirmwareDTO firmware);
/**
* Update the file information of the firmware.
* @param firmware
*/
void updateFirmwareInfo(DeviceFirmwareDTO firmware);
}

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

@ -34,25 +34,22 @@ public class CapacityCameraServiceImpl implements ICapacityCameraService { @@ -34,25 +34,22 @@ public class CapacityCameraServiceImpl implements ICapacityCameraService {
@Autowired
private IDeviceDictionaryService dictionaryService;
@Autowired
private RedisOpsUtils redisOps;
@Override
public List<CapacityCameraDTO> getCapacityCameraByDeviceSn(String deviceSn) {
return (List<CapacityCameraDTO>) redisOps.hashGet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn);
return (List<CapacityCameraDTO>) RedisOpsUtils.hashGet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn);
}
@Override
public Boolean deleteCapacityCameraByDeviceSn(String deviceSn) {
return redisOps.hashDel(StateDataEnum.LIVE_CAPACITY.getDesc(), new String[]{deviceSn});
return RedisOpsUtils.hashDel(StateDataEnum.LIVE_CAPACITY.getDesc(), 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());
redisOps.hashSet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn, capacity);
redisOps.setWithExpire(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + deviceSn, timestamp, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.hashSet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn, capacity);
RedisOpsUtils.setWithExpire(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + deviceSn, timestamp, RedisConst.DEVICE_ALIVE_SECOND);
}
@Override

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

@ -1,21 +1,26 @@ @@ -1,21 +1,26 @@
package com.dji.sample.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.common.model.Pagination;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.*;
import com.dji.sample.component.mqtt.service.impl.MessageSenderServiceImpl;
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.model.CustomWebSocketMessage;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.component.websocket.service.impl.SendMessageServiceImpl;
import com.dji.sample.manage.dao.IDeviceFirmwareMapper;
import com.dji.sample.manage.model.dto.DeviceDTO;
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.dto.*;
import com.dji.sample.manage.model.entity.DeviceFirmwareEntity;
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.service.IDeviceFirmwareService;
import com.dji.sample.manage.service.IDeviceService;
@ -27,13 +32,22 @@ import org.springframework.integration.annotation.ServiceActivator; @@ -27,13 +32,22 @@ 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;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* @author sean
@ -47,9 +61,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -47,9 +61,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
@Autowired
private IDeviceFirmwareMapper mapper;
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private MessageSenderServiceImpl messageSenderService;
@ -65,6 +76,9 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -65,6 +76,9 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
@Autowired
private IDeviceService deviceService;
@Autowired
private OssServiceContext ossServiceContext;
@Override
public Optional<DeviceFirmwareDTO> getFirmware(String deviceName, String version) {
return Optional.ofNullable(entity2Dto(mapper.selectOne(
@ -79,7 +93,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -79,7 +93,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
new LambdaQueryWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getDeviceName, deviceName)
.eq(DeviceFirmwareEntity::getStatus, true)
.orderByDesc(DeviceFirmwareEntity::getReleaseDate)
.orderByDesc(DeviceFirmwareEntity::getReleaseDate, DeviceFirmwareEntity::getFirmwareVersion)
.last(" limit 1 "))));
}
@ -127,30 +141,30 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -127,30 +141,30 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
log.error("SN: {}, {} ===> Error code: {}", sn, receiver.getMethod(), eventsReceiver.getResult());
}
DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
String childDeviceSn = device.getChildDeviceSn();
boolean upgrade = redisOps.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn) > 0;
boolean childUpgrade = redisOps.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn) > 0;
boolean upgrade = RedisOpsUtils.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn) > 0;
boolean childUpgrade = RedisOpsUtils.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn) > 0;
// Determine whether it is the ending state, delete the update state key in redis after the job ends.
EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus());
if (upgrade) {
if (statusEnum.getEnd()) {
// Delete the cache after the update is complete.
redisOps.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn);
RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn);
} else {
// Update the update progress of the dock in redis.
redisOps.setWithExpire(
RedisOpsUtils.setWithExpire(
RedisConst.FIRMWARE_UPGRADING_PREFIX + sn, output.getProgress().getPercent(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
}
}
if (childUpgrade) {
if (statusEnum.getEnd()) {
redisOps.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn);
RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn);
} else {
// Update the update progress of the drone in redis.
redisOps.setWithExpire(
RedisOpsUtils.setWithExpire(
RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn, output.getProgress().getPercent(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
}
@ -178,6 +192,137 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -178,6 +192,137 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
}
}
@Override
public Boolean checkFileExist(String workspaceId, String fileMd5) {
return mapper.selectCount(new LambdaQueryWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId)
.eq(DeviceFirmwareEntity::getFileMd5, fileMd5))
> 0;
}
@Override
public PaginationData<DeviceFirmwareDTO> getAllFirmwarePagination(String workspaceId, DeviceFirmwareQueryParam param) {
Page<DeviceFirmwareEntity> page = mapper.selectPage(new Page<>(param.getPage(), param.getPageSize()),
new LambdaQueryWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId)
.eq(Objects.nonNull(param.getStatus()), DeviceFirmwareEntity::getStatus, param.getStatus())
.eq(StringUtils.hasText(param.getDeviceName()), DeviceFirmwareEntity::getDeviceName, param.getDeviceName())
.like(StringUtils.hasText(param.getProductVersion()), DeviceFirmwareEntity::getFirmwareVersion, param.getProductVersion())
.orderByDesc(DeviceFirmwareEntity::getReleaseDate));
List<DeviceFirmwareDTO> data = page.getRecords().stream().map(this::entity2Dto).collect(Collectors.toList());
return new PaginationData<DeviceFirmwareDTO>(data, new Pagination(page));
}
@Override
public void importFirmwareFile(String workspaceId, String creator, DeviceFirmwareUploadParam param, MultipartFile file) {
try (InputStream is = file.getInputStream()) {
long size = is.available();
String md5 = DigestUtils.md5DigestAsHex(is);
boolean exist = checkFileExist(workspaceId, md5);
if (exist) {
throw new RuntimeException("The file already exists.");
}
Optional<DeviceFirmwareDTO> firmwareOpt = verifyFirmwareFile(file);
if (firmwareOpt.isEmpty()) {
throw new RuntimeException("The file format is incorrect.");
}
String firmwareId = UUID.randomUUID().toString();
String objectKey = OssConfiguration.objectDirPrefix + File.separator + firmwareId + FirmwareFileProperties.FIRMWARE_FILE_SUFFIX;
ossServiceContext.putObject(OssConfiguration.bucket, objectKey, file.getInputStream());
log.info("upload success");
DeviceFirmwareDTO firmware = DeviceFirmwareDTO.builder()
.deviceName(param.getDeviceName())
.releaseNote(param.getReleaseNote())
.firmwareStatus(param.getStatus())
.fileMd5(md5)
.objectKey(objectKey)
.fileName(file.getOriginalFilename())
.workspaceId(workspaceId)
.username(creator)
.fileSize(size)
.productVersion(firmwareOpt.get().getProductVersion())
.releasedTime(firmwareOpt.get().getReleasedTime())
.firmwareId(firmwareId)
.build();
saveFirmwareInfo(firmware);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void saveFirmwareInfo(DeviceFirmwareDTO firmware) {
mapper.insert(dto2Entity(firmware));
}
@Override
public void updateFirmwareInfo(DeviceFirmwareDTO firmware) {
mapper.update(dto2Entity(firmware),
new LambdaUpdateWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getFirmwareId, firmware.getFirmwareId()));
}
/**
* Parse firmware file information.
* @param file
* @return
*/
private Optional<DeviceFirmwareDTO> verifyFirmwareFile(MultipartFile file) {
try (ZipInputStream unzipFile = new ZipInputStream(file.getInputStream(), StandardCharsets.UTF_8)) {
ZipEntry nextEntry = unzipFile.getNextEntry();
while (Objects.nonNull(nextEntry)) {
String configName = nextEntry.getName();
if (!configName.contains(File.separator) && configName.endsWith(FirmwareFileProperties.FIRMWARE_CONFIG_FILE_SUFFIX + FirmwareFileProperties.FIRMWARE_SIG_FILE_SUFFIX)) {
String[] filenameArr = configName.split(FirmwareFileProperties.FIRMWARE_FILE_DELIMITER);
String date = filenameArr[FirmwareFileProperties.FILENAME_RELEASE_DATE_INDEX];
int index = date.indexOf(".");
if (index != -1) {
date = date.substring(0, index);
}
return Optional.of(DeviceFirmwareDTO.builder()
.releasedTime(LocalDate.parse(
date,
DateTimeFormatter.ofPattern(FirmwareFileProperties.FILENAME_RELEASE_DATE_FORMAT)))
// delete the string v.
.productVersion(filenameArr[FirmwareFileProperties.FILENAME_VERSION_INDEX].substring(1))
.build());
}
nextEntry = unzipFile.getNextEntry();
}
} catch (IOException e) {
e.printStackTrace();
}
return Optional.empty();
}
private DeviceFirmwareEntity dto2Entity(DeviceFirmwareDTO dto) {
if (dto == null) {
return null;
}
return DeviceFirmwareEntity.builder()
.fileName(dto.getFileName())
.deviceName(dto.getDeviceName())
.fileMd5(dto.getFileMd5())
.fileSize(dto.getFileSize())
.firmwareId(dto.getFirmwareId())
.firmwareVersion(dto.getProductVersion())
.objectKey(dto.getObjectKey())
.releaseDate(Objects.nonNull(dto.getReleasedTime()) ?
dto.getReleasedTime().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
.releaseNote(dto.getReleaseNote())
.status(dto.getFirmwareStatus())
.workspaceId(dto.getWorkspaceId())
.username(dto.getUsername())
.build();
}
private DeviceFirmwareNoteDTO entity2NoteDto (DeviceFirmwareEntity entity) {
if (entity == null) {
return null;
@ -198,12 +343,15 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -198,12 +343,15 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
.deviceName(entity.getDeviceName())
.fileMd5(entity.getFileMd5())
.fileSize(entity.getFileSize())
.fileUrl(entity.getFileUrl())
.objectKey(entity.getObjectKey())
.firmwareId(entity.getFirmwareId())
.fileName(entity.getFileName())
.productVersion(entity.getFirmwareVersion())
.releasedTime(LocalDate.ofInstant(Instant.ofEpochMilli(entity.getReleaseDate()), ZoneId.systemDefault()))
.releaseNote(entity.getReleaseNote())
.firmwareStatus(entity.getStatus())
.workspaceId(entity.getWorkspaceId())
.username(entity.getUsername())
.build();
}
@ -213,7 +361,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -213,7 +361,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
}
return DeviceOtaCreateParam.builder()
.fileSize(dto.getFileSize())
.fileUrl(dto.getFileUrl())
.fileUrl(ossServiceContext.getObjectUrl(OssConfiguration.bucket, dto.getObjectKey()).toString())
.fileName(dto.getFileName())
.md5(dto.getFileMd5())
.productVersion(dto.getProductVersion())

11
src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java

@ -62,9 +62,6 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService { @@ -62,9 +62,6 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private SendMessageServiceImpl sendMessageService;
@ -95,9 +92,9 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService { @@ -95,9 +92,9 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService {
.build();
String key = RedisConst.HMS_PREFIX + sn;
// Query all unread hms messages of the device in redis.
Set<String> hmsMap = redisOps.listGetAll(key).stream().map(String::valueOf).collect(Collectors.toSet());
Set<String> hmsMap = RedisOpsUtils.listGetAll(key).stream().map(String::valueOf).collect(Collectors.toSet());
DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
List<DeviceHmsDTO> unReadList = new ArrayList<>();
objectMapper.convertValue(((Map) (receiver.getData())).get(MapKeyConst.LIST),
@ -117,7 +114,7 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService { @@ -117,7 +114,7 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService {
if (unReadList.isEmpty()) {
return;
}
redisOps.listRPush(key, unReadList.stream().map(DeviceHmsDTO::getKey).toArray(String[]::new));
RedisOpsUtils.listRPush(key, unReadList.stream().map(DeviceHmsDTO::getKey).toArray(String[]::new));
// push to the web
Collection<ConcurrentWebSocketSession> sessions = webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal());
@ -162,7 +159,7 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService { @@ -162,7 +159,7 @@ public class DeviceHmsServiceImpl implements IDeviceHmsService {
.eq(DeviceHmsEntity::getSn, deviceSn)
.eq(DeviceHmsEntity::getUpdateTime, 0L));
// Delete unread messages cached in redis.
redisOps.del(RedisConst.HMS_PREFIX + deviceSn);
RedisOpsUtils.del(RedisConst.HMS_PREFIX + deviceSn);
}
private DeviceHmsDTO entity2Dto(DeviceHmsEntity entity) {

11
src/main/java/com/dji/sample/manage/service/impl/DevicePayloadServiceImpl.java

@ -43,9 +43,6 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService { @@ -43,9 +43,6 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService {
@Autowired
private ICapacityCameraService capacityCameraService;
@Autowired
private RedisOpsUtils redisOps;
@Override
public Integer checkPayloadExist(String payloadSn) {
DevicePayloadEntity devicePayload = mapper.selectOne(
@ -72,7 +69,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService { @@ -72,7 +69,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService {
String deviceSn = payloadReceiverList.get(0).getDeviceSn();
String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
DeviceDTO device = (DeviceDTO) redisOps.get(key);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(key);
List<DevicePayloadDTO> payloads = new ArrayList<>();
for (DevicePayloadReceiver payloadReceiver : payloadReceiverList) {
@ -87,7 +84,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService { @@ -87,7 +84,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService {
payloads = this.getDevicePayloadEntitiesByDeviceSn(deviceSn);
}
device.setPayloadsList(payloads);
redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(), device, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(), device, RedisConst.DEVICE_ALIVE_SECOND);
return true;
}
@ -133,7 +130,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService { @@ -133,7 +130,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService {
String deviceSn = payloadReceiverList.stream().findAny().get().getDeviceSn();
String key = RedisConst.STATE_PAYLOAD_PREFIX + deviceSn;
// Solve timing problems
long last = (long) Objects.requireNonNullElse(redisOps.get(key), 0L);
long last = (long) Objects.requireNonNullElse(RedisOpsUtils.get(key), 0L);
if (last > timestamp) {
return;
}
@ -153,7 +150,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService { @@ -153,7 +150,7 @@ public class DevicePayloadServiceImpl implements IDevicePayloadService {
// Save the new payload information.
boolean isSave = this.savePayloadDTOs(needToSave);
if (isSave) {
redisOps.setWithExpire(key, timestamp, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(key, timestamp, RedisConst.DEVICE_ALIVE_SECOND);
}
log.debug("The result of saving the payloads is {}.", isSave);
}

70
src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java

@ -85,9 +85,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -85,9 +85,6 @@ public class DeviceServiceImpl implements IDeviceService {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private IWebSocketManageService webSocketManageService;
@ -99,7 +96,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -99,7 +96,7 @@ public class DeviceServiceImpl implements IDeviceService {
private ITSAService tsaService;
private static final List<String> INIT_TOPICS_SUFFIX = List.of(
OSD_SUF, STATE_SUF, SERVICES_SUF + _REPLY_SUF, REQUESTS_SUF, EVENTS_SUF, PROPERTY_SUF + SET_SUF + _REPLY_SUF);
OSD_SUF, STATE_SUF, SERVICES_SUF + _REPLY_SUF, EVENTS_SUF, PROPERTY_SUF + SET_SUF + _REPLY_SUF);
@Override
public Boolean deviceOffline(StatusGatewayReceiver gateway) {
@ -109,14 +106,14 @@ public class DeviceServiceImpl implements IDeviceService { @@ -109,14 +106,14 @@ public class DeviceServiceImpl implements IDeviceService {
// Only the remote controller is logged in and the aircraft is not connected.
String key = RedisConst.DEVICE_ONLINE_PREFIX + gatewaySn;
boolean exist = redisOps.checkExist(key);
boolean exist = RedisOpsUtils.checkExist(key);
if (!exist) {
Optional<DeviceDTO> gatewayOpt = this.getDeviceBySn(gatewaySn);
if (gatewayOpt.isPresent()) {
DeviceDTO value = gatewayOpt.get();
value.setBoundTime(null);
value.setLoginTime(null);
redisOps.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
this.pushDeviceOnlineTopo(value.getWorkspaceId(), gatewaySn, gatewaySn);
return true;
}
@ -126,7 +123,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -126,7 +123,7 @@ public class DeviceServiceImpl implements IDeviceService {
return firstSaveDevice(gatewayDevice, null);
}
DeviceDTO deviceDTO = (DeviceDTO) (redisOps.get(key));
DeviceDTO deviceDTO = (DeviceDTO) (RedisOpsUtils.get(key));
String deviceSn = deviceDTO.getChildDeviceSn();
if (!StringUtils.hasText(deviceSn)) {
return true;
@ -140,11 +137,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -140,11 +137,11 @@ public class DeviceServiceImpl implements IDeviceService {
// If no information about this device exists in the cache, the drone is considered to be offline.
String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
if (!redisOps.checkExist(key) || redisOps.getExpire(key) <= 0) {
if (!RedisOpsUtils.checkExist(key) || RedisOpsUtils.getExpire(key) <= 0) {
log.debug("The drone is already offline.");
return true;
}
DeviceDTO device = (DeviceDTO) redisOps.get(key);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(key);
// Cancel drone-related subscriptions.
this.unsubscribeTopicOffline(deviceSn);
@ -152,8 +149,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -152,8 +149,8 @@ public class DeviceServiceImpl implements IDeviceService {
// Publish the latest device topology information in the current workspace.
this.pushDeviceOfflineTopo(device.getWorkspaceId(), deviceSn);
redisOps.del(key);
redisOps.del(RedisConst.OSD_PREFIX + device.getDeviceSn());
RedisOpsUtils.del(key);
RedisOpsUtils.del(RedisConst.OSD_PREFIX + device.getDeviceSn());
log.debug("{} offline.", deviceSn);
return true;
}
@ -163,11 +160,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -163,11 +160,11 @@ public class DeviceServiceImpl implements IDeviceService {
String deviceSn = deviceGateway.getSubDevices().get(0).getSn();
String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
// change log: Use redis instead of
long time = redisOps.getExpire(key);
long gatewayTime = redisOps.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn());
long time = RedisOpsUtils.getExpire(key);
long gatewayTime = RedisOpsUtils.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn());
if (time > 0 && gatewayTime > 0) {
redisOps.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = DeviceDTO.builder().loginTime(LocalDateTime.now()).deviceSn(deviceSn).build();
DeviceDTO gateway = DeviceDTO.builder()
.loginTime(LocalDateTime.now())
@ -175,7 +172,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -175,7 +172,7 @@ public class DeviceServiceImpl implements IDeviceService {
.childDeviceSn(deviceSn).build();
this.updateDevice(gateway);
this.updateDevice(device);
String workspaceId = ((DeviceDTO)(redisOps.get(key))).getWorkspaceId();
String workspaceId = ((DeviceDTO)(RedisOpsUtils.get(key))).getWorkspaceId();
if (StringUtils.hasText(workspaceId)) {
this.subscribeTopicOnline(deviceSn);
this.subscribeTopicOnline(deviceGateway.getSn());
@ -314,7 +311,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -314,7 +311,7 @@ public class DeviceServiceImpl implements IDeviceService {
devicesList.forEach(device -> {
this.spliceDeviceTopo(device);
device.setWorkspaceId(workspaceId);
device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
device.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
});
return devicesList;
}
@ -368,7 +365,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -368,7 +365,7 @@ public class DeviceServiceImpl implements IDeviceService {
this.getDeviceTopoForPilot(sn)
.ifPresent(pilotMessage::setData);
boolean exist = redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn);
boolean exist = RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn);
pilotMessage.getData().setOnlineStatus(exist);
pilotMessage.getData().setGatewaySn(gatewaySn.equals(sn) ? "" : gatewaySn);
@ -393,7 +390,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -393,7 +390,7 @@ public class DeviceServiceImpl implements IDeviceService {
.key(domain + "-" + type + "-" + subType)
.build())
.iconUrls(device.getIconUrl())
.onlineStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
.onlineStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
.boundStatus(device.getBoundStatus())
.model(device.getDeviceName())
.userId(device.getUserId())
@ -438,9 +435,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -438,9 +435,9 @@ public class DeviceServiceImpl implements IDeviceService {
topic.indexOf(OSD_SUF));
// Real-time update of device status in memory
redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + from);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + from);
if (device == null) {
Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(from);
@ -449,9 +446,10 @@ public class DeviceServiceImpl implements IDeviceService { @@ -449,9 +446,10 @@ public class DeviceServiceImpl implements IDeviceService {
}
device = deviceOpt.get();
if (!StringUtils.hasText(device.getWorkspaceId())) {
this.unsubscribeTopicOffline(from);
return;
}
redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + from, device,
RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + from, device,
RedisConst.DEVICE_ALIVE_SECOND);
this.subscribeTopicOnline(from);
}
@ -629,7 +627,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -629,7 +627,7 @@ public class DeviceServiceImpl implements IDeviceService {
return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build();
}
// Query whether the device is updating firmware.
Object progress = redisOps.get(RedisConst.FIRMWARE_UPGRADING_PREFIX + entity.getDeviceSn());
Object progress = RedisOpsUtils.get(RedisConst.FIRMWARE_UPGRADING_PREFIX + entity.getDeviceSn());
if (Objects.nonNull(progress)) {
return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.UPGRADING.getVal()).firmwareProgress((int)progress).build();
}
@ -668,12 +666,12 @@ public class DeviceServiceImpl implements IDeviceService { @@ -668,12 +666,12 @@ public class DeviceServiceImpl implements IDeviceService {
}
String key = RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn();
DeviceDTO redisDevice = (DeviceDTO)redisOps.get(key);
DeviceDTO redisDevice = (DeviceDTO)RedisOpsUtils.get(key);
if (Objects.isNull(redisDevice)) {
return false;
}
redisDevice.setWorkspaceId(device.getWorkspaceId());
redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
if (DeviceDomainEnum.GATEWAY.getDesc().equals(redisDevice.getDomain())) {
this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()),
@ -785,12 +783,12 @@ public class DeviceServiceImpl implements IDeviceService { @@ -785,12 +783,12 @@ public class DeviceServiceImpl implements IDeviceService {
.eq(DeviceEntity::getBoundStatus, true));
List<DeviceDTO> devicesList = pagination.getRecords().stream().map(this::deviceEntityConvertToDTO)
.peek(device -> {
device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
device.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
if (StringUtils.hasText(device.getChildDeviceSn())) {
Optional<DeviceDTO> childOpt = this.getDeviceBySn(device.getChildDeviceSn());
childOpt.ifPresent(child -> {
child.setStatus(
redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn()));
RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn()));
child.setWorkspaceName(device.getWorkspaceName());
device.setChildren(child);
});
@ -803,9 +801,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -803,9 +801,9 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public void unbindDevice(String deviceSn) {
String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
DeviceDTO redisDevice = (DeviceDTO) redisOps.get(key);
DeviceDTO redisDevice = (DeviceDTO) RedisOpsUtils.get(key);
redisDevice.setWorkspaceId("");
redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = DeviceDTO.builder()
.deviceSn(deviceSn)
@ -823,7 +821,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -823,7 +821,7 @@ public class DeviceServiceImpl implements IDeviceService {
return Optional.empty();
}
DeviceDTO device = devicesList.get(0);
device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn));
device.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn));
return Optional.of(device);
}
@ -877,7 +875,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -877,7 +875,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
// Record the device state that needs to be updated.
deviceOtaFirmwares.forEach(deviceOta -> redisOps.setWithExpire(
deviceOtaFirmwares.forEach(deviceOta -> RedisOpsUtils.setWithExpire(
RedisConst.FIRMWARE_UPGRADING_PREFIX + deviceOta.getSn(),
bid,
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND));
@ -890,7 +888,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -890,7 +888,7 @@ public class DeviceServiceImpl implements IDeviceService {
if (!dockOnline) {
throw new RuntimeException("Dock is offline.");
}
DeviceDTO deviceDTO = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn);
DeviceDTO deviceDTO = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn);
boolean deviceOnline = this.checkDeviceOnline(deviceDTO.getChildDeviceSn());
if (!deviceOnline) {
throw new RuntimeException("Device is offline.");
@ -904,7 +902,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -904,7 +902,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
String topic = THING_MODEL_PRE + PRODUCT + dockSn + PROPERTY_SUF + SET_SUF;
OsdSubDeviceReceiver osd = (OsdSubDeviceReceiver) redisOps.get(RedisConst.OSD_PREFIX + deviceDTO.getChildDeviceSn());
// OsdSubDeviceReceiver osd = (OsdSubDeviceReceiver) RedisOpsUtils.get(RedisConst.OSD_PREFIX + deviceDTO.getChildDeviceSn());
if (!param.isObject()) {
this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param));
return;
@ -912,7 +910,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -912,7 +910,7 @@ public class DeviceServiceImpl implements IDeviceService {
// If there are multiple parameters, set them separately.
for (Iterator<Map.Entry<String, JsonNode>> filed = param.fields(); filed.hasNext(); ) {
Map.Entry<String, JsonNode> node = filed.next();
boolean isPublish = basicDeviceProperty.canPublish(node.getKey(), osd);
boolean isPublish = basicDeviceProperty.canPublish(node.getKey(), null);
if (!isPublish) {
continue;
}
@ -954,7 +952,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -954,7 +952,7 @@ public class DeviceServiceImpl implements IDeviceService {
public Boolean checkDeviceOnline(String sn) {
String key = RedisConst.DEVICE_ONLINE_PREFIX + sn;
return redisOps.checkExist(key) && redisOps.getExpire(key) > 0;
return RedisOpsUtils.checkExist(key) && RedisOpsUtils.getExpire(key) > 0;
}
/**
@ -1052,6 +1050,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -1052,6 +1050,8 @@ public class DeviceServiceImpl implements IDeviceService {
// Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module.
device.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl());
}
deviceOpt.ifPresent(oldDevice -> device.setNickname(oldDevice.getNickname()));
device.setChildSn(deviceSn);
device.setLoginTime(System.currentTimeMillis());
@ -1061,7 +1061,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -1061,7 +1061,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
device.setWorkspaceId(saveDeviceOpt.get().getWorkspaceId());
redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(),
RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(),
DeviceDTO.builder()
.deviceSn(device.getDeviceSn())
.workspaceId(device.getWorkspaceId())

9
src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java

@ -53,9 +53,6 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -53,9 +53,6 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
@Autowired
private IMessageSenderService messageSender;
@Autowired
private RedisOpsUtils redisOps;
@Override
public List<CapacityDeviceDTO> getLiveCapacity(String workspaceId) {
@ -68,7 +65,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -68,7 +65,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
// Query the live capability of each drone.
return devicesList.stream()
.filter(device -> redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
.filter(device -> RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
.map(device -> CapacityDeviceDTO.builder()
.name(Objects.requireNonNullElse(device.getNickname(), device.getDeviceName()))
.sn(device.getDeviceSn())
@ -82,7 +79,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -82,7 +79,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
// Solve timing problems
for (CapacityDeviceReceiver capacityDeviceReceiver : liveCapacityReceiver.getDeviceList()) {
long last = (long) Objects.requireNonNullElse(
redisOps.get(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + capacityDeviceReceiver.getSn()), 0L);
RedisOpsUtils.get(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + capacityDeviceReceiver.getSn()), 0L);
if (last > timestamp) {
return;
}
@ -172,7 +169,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -172,7 +169,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
String respTopic = THING_MODEL_PRE + PRODUCT + responseResult.getData().getDeviceSn() + SERVICES_SUF;
ServiceReply receiveReply = this.publishLiveSetQuality(respTopic, liveParam);
if (ResponseResult.CODE_SUCCESS == receiveReply.getResult()) {
if (ResponseResult.CODE_SUCCESS != receiveReply.getResult()) {
return ResponseResult.error(LiveErrorEnum.find(receiveReply.getResult()));
}

7
src/main/java/com/dji/sample/manage/service/impl/LogsFileServiceImpl.java

@ -43,9 +43,6 @@ public class LogsFileServiceImpl implements ILogsFileService { @@ -43,9 +43,6 @@ public class LogsFileServiceImpl implements ILogsFileService {
@Autowired
private OssServiceContext ossService;
@Autowired
private OssConfiguration configuration;
@Autowired
private OssServiceContext ossServiceContext;
@ -114,7 +111,7 @@ public class LogsFileServiceImpl implements ILogsFileService { @@ -114,7 +111,7 @@ public class LogsFileServiceImpl implements ILogsFileService {
List<String> fileIds = new ArrayList<>();
logsFiles.forEach(file -> {
if (file.getStatus()) {
ossService.deleteObject(configuration.getBucket(), file.getObjectKey());
ossService.deleteObject(OssConfiguration.bucket, file.getObjectKey());
}
fileIds.add(file.getFileId());
});
@ -146,7 +143,7 @@ public class LogsFileServiceImpl implements ILogsFileService { @@ -146,7 +143,7 @@ public class LogsFileServiceImpl implements ILogsFileService {
if (Objects.isNull(logsFile)) {
return null;
}
return ossService.getObjectUrl(configuration.getBucket(), logsFile.getObjectKey());
return ossService.getObjectUrl(OssConfiguration.bucket, logsFile.getObjectKey());
}
private LogsFileEntity receiver2Entity(LogsExtFileReceiver receiver) {

2
src/main/java/com/dji/sample/media/controller/FileController.java

@ -32,7 +32,7 @@ public class FileController { @@ -32,7 +32,7 @@ public class FileController {
public ResponseResult<PaginationData<MediaFileDTO>> getFilesList(@RequestParam(defaultValue = "1") Long page,
@RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
@PathVariable(name = "workspace_id") String workspaceId) {
PaginationData<MediaFileDTO> filesList = fileService.getJobsPaginationByWorkspaceId(workspaceId, page, pageSize);
PaginationData<MediaFileDTO> filesList = fileService.getMediaFilesPaginationByWorkspaceId(workspaceId, page, pageSize);
return ResponseResult.success(filesList);
}

30
src/main/java/com/dji/sample/media/model/MediaFileCountDTO.java

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
package com.dji.sample.media.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.3
* @date 2022/11/22
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MediaFileCountDTO {
private String tid;
private String bid;
private String preJobId;
private String jobId;
private Integer mediaCount;
private Integer uploadedCount;
}

2
src/main/java/com/dji/sample/media/model/MediaFileDTO.java

@ -39,4 +39,6 @@ public class MediaFileDTO { @@ -39,4 +39,6 @@ public class MediaFileDTO {
private String fingerprint;
private LocalDateTime createTime;
private String jobId;
}

20
src/main/java/com/dji/sample/media/model/MediaMethodEnum.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package com.dji.sample.media.model;
import lombok.Getter;
/**
* @author sean
* @version 1.3
* @date 2022/11/23
*/
@Getter
public enum MediaMethodEnum {
UPLOAD_FLIGHT_TASK_MEDIA_PRIORITIZE("upload_flighttask_media_prioritize");
private String method;
MediaMethodEnum(String method) {
this.method = method;
}
}

10
src/main/java/com/dji/sample/media/service/IFileService.java

@ -44,7 +44,7 @@ public interface IFileService { @@ -44,7 +44,7 @@ public interface IFileService {
* @param pageSize
* @return
*/
PaginationData<MediaFileDTO> getJobsPaginationByWorkspaceId(String workspaceId, long page, long pageSize);
PaginationData<MediaFileDTO> getMediaFilesPaginationByWorkspaceId(String workspaceId, long page, long pageSize);
/**
* Get the download address of the file.
@ -53,4 +53,12 @@ public interface IFileService { @@ -53,4 +53,12 @@ public interface IFileService {
* @return
*/
URL getObjectUrl(String workspaceId, String fileId);
/**
* Query all media files of a job.
* @param workspaceId
* @param jobId
* @return
*/
List<MediaFileDTO> getFilesByWorkspaceAndJobId(String workspaceId, String jobId);
}

8
src/main/java/com/dji/sample/media/service/IMediaService.java

@ -2,6 +2,7 @@ package com.dji.sample.media.service; @@ -2,6 +2,7 @@ package com.dji.sample.media.service;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.media.model.FileUploadDTO;
import org.springframework.messaging.MessageHeaders;
import java.util.List;
@ -49,4 +50,11 @@ public interface IMediaService { @@ -49,4 +50,11 @@ public interface IMediaService {
* @return
*/
void handleFileUploadCallBack(CommonTopicReceiver receiver);
/**
* Handles the highest priority message about media uploads.
* @param receiver
* @param headers
*/
void handleHighestPriorityUploadFlightTaskMedia(CommonTopicReceiver receiver, MessageHeaders headers);
}

19
src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java

@ -46,9 +46,6 @@ public class FileServiceImpl implements IFileService { @@ -46,9 +46,6 @@ public class FileServiceImpl implements IFileService {
@Autowired
private OssServiceContext ossService;
@Autowired
private OssConfiguration configuration;
private Optional<MediaFileEntity> getMediaByFingerprint(String workspaceId, String fingerprint) {
MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
.eq(MediaFileEntity::getWorkspaceId, workspaceId)
@ -86,7 +83,7 @@ public class FileServiceImpl implements IFileService { @@ -86,7 +83,7 @@ public class FileServiceImpl implements IFileService {
}
@Override
public PaginationData<MediaFileDTO> getJobsPaginationByWorkspaceId(String workspaceId, long page, long pageSize) {
public PaginationData<MediaFileDTO> getMediaFilesPaginationByWorkspaceId(String workspaceId, long page, long pageSize) {
Page<MediaFileEntity> pageData = mapper.selectPage(
new Page<MediaFileEntity>(page, pageSize),
new LambdaQueryWrapper<MediaFileEntity>()
@ -107,7 +104,16 @@ public class FileServiceImpl implements IFileService { @@ -107,7 +104,16 @@ public class FileServiceImpl implements IFileService {
throw new IllegalArgumentException("{} doesn't exist.");
}
return ossService.getObjectUrl(configuration.getBucket(), mediaFileOpt.get().getObjectKey());
return ossService.getObjectUrl(OssConfiguration.bucket, mediaFileOpt.get().getObjectKey());
}
@Override
public List<MediaFileDTO> getFilesByWorkspaceAndJobId(String workspaceId, String jobId) {
return mapper.selectList(new LambdaQueryWrapper<MediaFileEntity>()
.eq(MediaFileEntity::getWorkspaceId, workspaceId)
.eq(MediaFileEntity::getJobId, jobId))
.stream()
.map(this::entityConvertToDto).collect(Collectors.toList());
}
/**
@ -160,7 +166,8 @@ public class FileServiceImpl implements IFileService { @@ -160,7 +166,8 @@ public class FileServiceImpl implements IFileService {
.payload(entity.getPayload())
.createTime(LocalDateTime.ofInstant(
Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
.drone(entity.getDrone());
.drone(entity.getDrone())
.jobId(entity.getJobId());
}

147
src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java

@ -1,12 +1,21 @@ @@ -1,12 +1,21 @@
package com.dji.sample.media.service.impl;
import com.dji.sample.common.error.CommonErrorEnum;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.*;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
import com.dji.sample.component.websocket.service.ISendMessageService;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.media.model.FileUploadCallback;
import com.dji.sample.media.model.FileUploadDTO;
import com.dji.sample.media.model.MediaFileCountDTO;
import com.dji.sample.media.model.MediaFileDTO;
import com.dji.sample.media.service.IFileService;
import com.dji.sample.media.service.IMediaService;
@ -15,9 +24,13 @@ import com.dji.sample.wayline.service.IWaylineJobService; @@ -15,9 +24,13 @@ import com.dji.sample.wayline.service.IWaylineJobService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@ -44,6 +57,12 @@ public class MediaServiceImpl implements IMediaService { @@ -44,6 +57,12 @@ public class MediaServiceImpl implements IMediaService {
@Autowired
private IDeviceService deviceService;
@Autowired
private ISendMessageService sendMessageService;
@Autowired
private IWebSocketManageService webSocketManageService;
@Override
public Boolean fastUpload(String workspaceId, String fingerprint) {
return fileService.checkExist(workspaceId, fingerprint);
@ -79,32 +98,126 @@ public class MediaServiceImpl implements IMediaService { @@ -79,32 +98,126 @@ public class MediaServiceImpl implements IMediaService {
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + receiver.getGateway()
+ TopicConst.EVENTS_SUF + TopicConst._REPLY_SUF;
CommonTopicResponse<Object> data = CommonTopicResponse.builder()
CommonTopicResponse<RequestsReply> data = CommonTopicResponse.<RequestsReply>builder()
.timestamp(System.currentTimeMillis())
.method(EventsMethodEnum.FILE_UPLOAD_CALLBACK.getMethod())
.data(RequestsReply.success())
.tid(receiver.getTid())
.bid(receiver.getBid())
.build();
if (callback.getResult() == ResponseResult.CODE_SUCCESS) {
String jobId = callback.getFile().getExt().getFlightId();
Optional<WaylineJobDTO> jobOpt = waylineJobService.getJobByJobId(jobId);
if (jobOpt.isPresent()) {
// Set the drone sn that shoots the media
Optional<DeviceDTO> dockDTO = deviceService.getDeviceBySn(jobOpt.get().getDockSn());
dockDTO.ifPresent(dock -> callback.getFile().getExt().setSn(dock.getChildDeviceSn()));
// set path
String objectKey = callback.getFile().getObjectKey();
callback.getFile().setPath(objectKey.substring(objectKey.indexOf("/") + 1, objectKey.lastIndexOf("/")));
int id = fileService.saveFile(jobOpt.get().getWorkspaceId(), callback.getFile());
if (id <= 0) {
data.setData(ResponseResult.error());
}
if (callback.getResult() != ResponseResult.CODE_SUCCESS) {
messageSenderService.publish(topic, data);
return;
}
String jobId = callback.getFile().getExt().getFlightId();
MediaFileCountDTO mediaFileCount = (MediaFileCountDTO) RedisOpsUtils.hashGet(RedisConst.MEDIA_FILE_PREFIX + receiver.getGateway(), jobId);
// duplicate data
if (receiver.getBid().equals(mediaFileCount.getBid()) && receiver.getTid().equals(mediaFileCount.getTid())) {
System.out.println("相同" + receiver.getBid() + "\t tid:" + receiver.getTid());
messageSenderService.publish(topic, data);
return;
}
Optional<WaylineJobDTO> jobOpt = waylineJobService.getJobByJobId(jobId);
if (jobOpt.isPresent()) {
boolean isSave = parseMediaFile(callback, jobOpt.get());
if (!isSave) {
data.setData(RequestsReply.error(CommonErrorEnum.ILLEGAL_ARGUMENT));
}
}
messageSenderService.publish(topic, data);
notifyUploadedCount(mediaFileCount, receiver, jobId);
}
/**
* update the uploaded count and notify web side
* @param mediaFileCount
* @param receiver
* @param jobId
*/
private void notifyUploadedCount(MediaFileCountDTO mediaFileCount, CommonTopicReceiver receiver, String jobId) {
mediaFileCount.setBid(receiver.getBid());
mediaFileCount.setTid(receiver.getTid());
mediaFileCount.setUploadedCount(mediaFileCount.getUploadedCount() + 1);
String key = RedisConst.MEDIA_FILE_PREFIX + receiver.getGateway();
// After all the files of the job are uploaded, delete the media file key.
if (mediaFileCount.getUploadedCount() >= mediaFileCount.getMediaCount()) {
RedisOpsUtils.hashDel(key, new String[]{jobId});
// After uploading, delete the key with the highest priority.
String highestKey = RedisConst.MEDIA_HIGHEST_PRIORITY_PREFIX + receiver.getGateway();
if (jobId.equals(Objects.requireNonNullElse(RedisOpsUtils.get(highestKey), ""))) {
RedisOpsUtils.del(highestKey);
}
if (RedisOpsUtils.hashLen(key) == 0) {
RedisOpsUtils.del(key);
}
} else {
RedisOpsUtils.hashSet(key, jobId, mediaFileCount);
}
DeviceDTO dock = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
sendMessageService.sendBatch(webSocketManageService.getValueWithWorkspaceAndUserType(dock.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
CustomWebSocketMessage.builder()
.bizCode(BizCodeEnum.FILE_UPLOAD_CALLBACK.getCode())
.timestamp(System.currentTimeMillis())
.data(mediaFileCount)
.build());
}
private Boolean parseMediaFile(FileUploadCallback callback, WaylineJobDTO job) {
// Set the drone sn that shoots the media
Optional<DeviceDTO> dockDTO = deviceService.getDeviceBySn(job.getDockSn());
dockDTO.ifPresent(dock -> callback.getFile().getExt().setSn(dock.getChildDeviceSn()));
// set path
String objectKey = callback.getFile().getObjectKey();
callback.getFile().setPath(objectKey.substring(objectKey.indexOf("/") + 1, objectKey.lastIndexOf("/")));
return fileService.saveFile(job.getWorkspaceId(), callback.getFile()) > 0;
}
@Override
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA, outputChannel = ChannelName.OUTBOUND)
public void handleHighestPriorityUploadFlightTaskMedia(CommonTopicReceiver receiver, MessageHeaders headers) {
Map map = objectMapper.convertValue(receiver.getData(), Map.class);
if (map.isEmpty() || !map.containsKey(MapKeyConst.FLIGHT_ID)) {
return;
}
String dockSn = receiver.getGateway();
String jobId = map.get(MapKeyConst.FLIGHT_ID).toString();
String key = RedisConst.MEDIA_HIGHEST_PRIORITY_PREFIX + dockSn;
Object preJobId = RedisOpsUtils.get(key);
RedisOpsUtils.setWithExpire(key, jobId,
RedisConst.DEVICE_ALIVE_SECOND * 5);
DeviceDTO dock = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn);
sendMessageService.sendBatch(webSocketManageService.getValueWithWorkspaceAndUserType(dock.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
CustomWebSocketMessage.builder()
.timestamp(System.currentTimeMillis())
.bizCode(BizCodeEnum.HIGHEST_PRIORITY_UPLOAD_FLIGHT_TASK_MEDIA.getCode())
.data(MediaFileCountDTO.builder()
.preJobId(Objects.nonNull(preJobId) ? preJobId.toString() : null)
.jobId(jobId).build())
.build());
messageSenderService.publish(headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF,
CommonTopicResponse.builder()
.data(RequestsReply.success())
.method(receiver.getMethod())
.timestamp(System.currentTimeMillis())
.bid(receiver.getBid())
.tid(receiver.getTid())
.build());
}
}

13
src/main/java/com/dji/sample/storage/service/impl/StorageServiceImpl.java

@ -26,18 +26,15 @@ public class StorageServiceImpl implements IStorageService { @@ -26,18 +26,15 @@ public class StorageServiceImpl implements IStorageService {
@Autowired
private OssServiceContext ossService;
@Autowired
private OssConfiguration configuration;
@Override
public StsCredentialsDTO getSTSCredentials() {
return StsCredentialsDTO.builder()
.endpoint(configuration.getEndpoint())
.bucket(configuration.getBucket())
.endpoint(OssConfiguration.endpoint)
.bucket(OssConfiguration.bucket)
.credentials(ossService.getCredentials())
.provider(configuration.getProvider())
.objectKeyPrefix(configuration.getObjectDirPrefix())
.region(configuration.getRegion())
.provider(OssConfiguration.provider)
.objectKeyPrefix(OssConfiguration.objectDirPrefix)
.region(OssConfiguration.region)
.build();
}

1
src/main/java/com/dji/sample/wayline/controller/WaylineFileController.java

@ -75,6 +75,7 @@ public class WaylineFileController { @@ -75,6 +75,7 @@ public class WaylineFileController {
try {
URL url = waylineFileService.getObjectUrl(workspaceId, waylineId);
response.sendRedirect(url.toString());
} catch (IOException | SQLException e) {
e.printStackTrace();
}

13
src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java

@ -73,4 +73,17 @@ public class WaylineJobController { @@ -73,4 +73,17 @@ public class WaylineJobController {
waylineJobService.cancelFlightTask(workspaceId, jobIds);
return ResponseResult.success();
}
/**
* Set the media files for this job to upload immediately.
* @param workspaceId
* @param jobId
* @return
*/
@PostMapping("/{workspace_id}/jobs/{job_id}/media-highest")
public ResponseResult uploadMediaHighestPriority(@PathVariable(name = "workspace_id") String workspaceId,
@PathVariable(name = "job_id") String jobId) {
waylineJobService.uploadMediaHighestPriority(workspaceId, jobId);
return ResponseResult.success();
}
}

4
src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java

@ -53,4 +53,8 @@ public class WaylineJobDTO { @@ -53,4 +53,8 @@ public class WaylineJobDTO {
private Integer outOfControlAction;
private Integer mediaCount;
private Integer uploadedCount;
private Boolean uploading;
}

7
src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java

@ -80,4 +80,11 @@ public interface IWaylineJobService { @@ -80,4 +80,11 @@ public interface IWaylineJobService {
* @param headers
*/
void flightTaskResourceGet(CommonTopicReceiver receiver, MessageHeaders headers);
/**
* Set the media files for this job to upload immediately.
* @param workspaceId
* @param jobId
*/
void uploadMediaHighestPriority(String workspaceId, String jobId);
}

24
src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java

@ -11,6 +11,7 @@ import com.dji.sample.component.websocket.service.ISendMessageService; @@ -11,6 +11,7 @@ import com.dji.sample.component.websocket.service.ISendMessageService;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.media.model.MediaFileCountDTO;
import com.dji.sample.wayline.model.dto.FlightTaskProgressReceiver;
import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
@ -52,9 +53,6 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -52,9 +53,6 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
@Autowired
private IWebSocketManageService webSocketManageService;
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private IWaylineJobService waylineJobService;
@ -83,17 +81,23 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -83,17 +81,23 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
.mediaCount(output.getExt().getMediaCount())
.build();
// record the update of the media count.
if (Objects.nonNull(job.getMediaCount())) {
RedisOpsUtils.hashSet(RedisConst.MEDIA_FILE_PREFIX + receiver.getGateway(), job.getJobId(),
MediaFileCountDTO.builder().jobId(receiver.getBid()).mediaCount(job.getMediaCount()).uploadedCount(0).build());
}
if (EventsResultStatusEnum.OK != statusEnum) {
job.setCode(eventsReceiver.getResult());
job.setStatus(WaylineJobStatusEnum.FAILED.getVal());
}
waylineJobService.updateJob(job);
redisOps.del(receiver.getBid());
RedisOpsUtils.del(receiver.getBid());
}
redisOps.setWithExpire(receiver.getBid(), eventsReceiver, RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(receiver.getBid(), eventsReceiver, RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
websocketMessageService.sendBatch(
webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
@ -118,19 +122,19 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -118,19 +122,19 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
@Scheduled(initialDelay = 10, fixedRate = 5, timeUnit = TimeUnit.SECONDS)
private void checkScheduledJob() {
Object jobIdValue = redisOps.zGetMin(RedisConst.WAYLINE_JOB);
Object jobIdValue = RedisOpsUtils.zGetMin(RedisConst.WAYLINE_JOB);
log.info("Check the timed jobs of the wayline. {}", jobIdValue);
if (Objects.isNull(jobIdValue)) {
return;
}
String jobId = String.valueOf(jobIdValue);
double time = redisOps.zScore(RedisConst.WAYLINE_JOB, jobIdValue);
double time = RedisOpsUtils.zScore(RedisConst.WAYLINE_JOB, jobIdValue);
long now = System.currentTimeMillis();
int offset = 30_000;
// Expired tasks are deleted directly.
if (time < now - offset) {
redisOps.zRemove(RedisConst.WAYLINE_JOB, jobId);
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB, jobId);
waylineJobService.updateJob(WaylineJobDTO.builder()
.jobId(jobId)
.status(WaylineJobStatusEnum.FAILED.getVal())
@ -150,7 +154,7 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -150,7 +154,7 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
.endTime(LocalDateTime.now())
.code(HttpStatus.SC_INTERNAL_SERVER_ERROR).build());
} finally {
redisOps.zRemove(RedisConst.WAYLINE_JOB, jobId);
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB, jobId);
}
}
}

15
src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java

@ -53,9 +53,6 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -53,9 +53,6 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
@Autowired
private OssServiceContext ossService;
@Autowired
private OssConfiguration configuration;
@Override
public PaginationData<WaylineFileDTO> getWaylinesByParam(String workspaceId, WaylineQueryParam param) {
// Paging Query
@ -97,7 +94,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -97,7 +94,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
if (waylineOpt.isEmpty()) {
throw new SQLException(waylineId + " does not exist.");
}
return ossService.getObjectUrl(configuration.getBucket(), waylineOpt.get().getObjectKey());
return ossService.getObjectUrl(OssConfiguration.bucket, waylineOpt.get().getObjectKey());
}
@Override
@ -107,10 +104,10 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -107,10 +104,10 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
file.setWorkspaceId(workspaceId);
if (!StringUtils.hasText(file.getSign())) {
try (InputStream object = ossService.getObject(configuration.getBucket(), metadata.getObjectKey())) {
try (InputStream object = ossService.getObject(OssConfiguration.bucket, metadata.getObjectKey())) {
if (object.available() == 0) {
throw new RuntimeException("The file " + metadata.getObjectKey() +
" does not exist in the bucket[" + configuration.getBucket() + "].");
" does not exist in the bucket[" + OssConfiguration.bucket + "].");
}
file.setSign(DigestUtils.md5DigestAsHex(object));
} catch (IOException e) {
@ -159,7 +156,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -159,7 +156,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
if (!isDel) {
return false;
}
return ossService.deleteObject(configuration.getBucket(), wayline.getObjectKey());
return ossService.deleteObject(OssConfiguration.bucket, wayline.getObjectKey());
}
@Override
@ -174,7 +171,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -174,7 +171,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
waylineFile.setWaylineId(workspaceId);
waylineFile.setUsername(creator);
ossService.putObject(configuration.getBucket(), waylineFile.getObjectKey(), file.getInputStream());
ossService.putObject(OssConfiguration.bucket, waylineFile.getObjectKey(), file.getInputStream());
this.saveWaylineFile(workspaceId, waylineFile);
} catch (IOException e) {
e.printStackTrace();
@ -222,7 +219,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -222,7 +219,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
return Optional.of(WaylineFileDTO.builder()
.droneModelKey(String.format("%s-%s-%s", DeviceDomainEnum.SUB_DEVICE.getVal(), type, subType))
.payloadModelKeys(List.of(String.format("%s-%s-%s",DeviceDomainEnum.PAYLOAD.getVal(), payloadType, payloadSubType)))
.objectKey(configuration.getObjectDirPrefix() + File.separator + filename)
.objectKey(OssConfiguration.objectDirPrefix + File.separator + filename)
.name(filename.substring(0, filename.lastIndexOf(WAYLINE_FILE_SUFFIX)))
.sign(DigestUtils.md5DigestAsHex(file.getInputStream()))
.templateTypes(List.of(Integer.parseInt(templateId)))

73
src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java

@ -14,6 +14,9 @@ import com.dji.sample.component.redis.RedisConst; @@ -14,6 +14,9 @@ import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.media.model.MediaFileCountDTO;
import com.dji.sample.media.model.MediaMethodEnum;
import com.dji.sample.media.service.IFileService;
import com.dji.sample.wayline.dao.IWaylineJobMapper;
import com.dji.sample.wayline.model.dto.*;
import com.dji.sample.wayline.model.entity.WaylineJobEntity;
@ -65,12 +68,11 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -65,12 +68,11 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
@Autowired
private IMessageSenderService messageSender;
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private IFileService fileService;
@Override
public Optional<WaylineJobDTO> createWaylineJob(CreateJobParam param, CustomClaim customClaim) {
@ -94,6 +96,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -94,6 +96,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.waylineType(param.getWaylineType())
.outOfControlAction(param.getOutOfControlAction())
.rthAltitude(param.getRthAltitude())
.mediaCount(0)
.build();
int id = mapper.insert(jobEntity);
if (id <= 0) {
@ -167,7 +170,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -167,7 +170,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
}
if (WaylineTaskTypeEnum.TIMED.getVal() == waylineJob.getTaskType()) {
boolean isAdd = redisOps.zAdd(RedisConst.WAYLINE_JOB, waylineJob.getJobId(),
boolean isAdd = RedisOpsUtils.zAdd(RedisConst.WAYLINE_JOB, waylineJob.getJobId(),
waylineJob.getExecuteTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
if (!isAdd) {
return ResponseResult.error("Failed to create scheduled job.");
@ -218,7 +221,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -218,7 +221,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.jobId(jobId)
.status(WaylineJobStatusEnum.IN_PROGRESS.getVal())
.build());
redisOps.setWithExpire(jobId,
RedisOpsUtils.setWithExpire(jobId,
EventsReceiver.<FlightTaskProgressReceiver>builder().bid(jobId).sn(job.getDockSn()).build(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
return true;
@ -256,7 +259,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -256,7 +259,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
private void publishCancelTask(String workspaceId, String dockSn, List<String> jobIds) {
boolean isOnline = deviceService.checkDeviceOnline(dockSn);
if (isOnline) {
if (!isOnline) {
throw new RuntimeException("Dock is offline.");
}
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + dockSn + TopicConst.SERVICES_SUF;
@ -282,7 +285,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -282,7 +285,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.status(WaylineJobStatusEnum.CANCEL.getVal())
.endTime(LocalDateTime.now())
.build());
redisOps.zRemove(RedisConst.WAYLINE_JOB, jobId);
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB, jobId);
}
}
@ -372,6 +375,33 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -372,6 +375,33 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
}
@Override
public void uploadMediaHighestPriority(String workspaceId, String jobId) {
Optional<WaylineJobDTO> jobOpt = getJobByJobId(jobId);
if (jobOpt.isEmpty()) {
throw new RuntimeException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg());
}
String dockSn = jobOpt.get().getDockSn();
String key = RedisConst.MEDIA_HIGHEST_PRIORITY_PREFIX + dockSn;
if (RedisOpsUtils.checkExist(key) && jobId.equals(RedisOpsUtils.get(key).toString())) {
return;
}
ServiceReply reply = messageSender.publishWithReply(TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + dockSn + TopicConst.SERVICES_SUF,
CommonTopicResponse.builder()
.tid(UUID.randomUUID().toString())
.bid(UUID.randomUUID().toString())
.timestamp(System.currentTimeMillis())
.method(MediaMethodEnum.UPLOAD_FLIGHT_TASK_MEDIA_PRIORITIZE.getMethod())
.data(Map.of(MapKeyConst.FLIGHT_ID, jobId))
.build());
if (ResponseResult.CODE_SUCCESS != reply.getResult()) {
throw new RuntimeException("Failed to set media job upload priority. Error Code: " + reply.getResult());
}
RedisOpsUtils.setWithExpire(key, jobId, RedisConst.DEVICE_ALIVE_SECOND * 5);
}
private WaylineJobEntity dto2Entity(WaylineJobDTO dto) {
WaylineJobEntity.WaylineJobEntityBuilder builder = WaylineJobEntity.builder();
if (dto == null) {
@ -418,12 +448,37 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -418,12 +448,37 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
if (Objects.nonNull(entity.getEndTime())) {
builder.endTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()));
}
if (WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && redisOps.getExpire(entity.getJobId()) > 0) {
EventsReceiver<FlightTaskProgressReceiver> taskProgress = (EventsReceiver<FlightTaskProgressReceiver>) redisOps.get(entity.getJobId());
if (WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && RedisOpsUtils.getExpire(entity.getJobId()) > 0) {
EventsReceiver<FlightTaskProgressReceiver> taskProgress = (EventsReceiver<FlightTaskProgressReceiver>) RedisOpsUtils.get(entity.getJobId());
if (Objects.nonNull(taskProgress.getOutput()) && Objects.nonNull(taskProgress.getOutput().getProgress())) {
builder.progress(taskProgress.getOutput().getProgress().getPercent());
}
}
if (entity.getMediaCount() == 0) {
return builder.build();
}
// sync the number of media files
String key = RedisConst.MEDIA_HIGHEST_PRIORITY_PREFIX + entity.getDockSn();
String countKey = RedisConst.MEDIA_FILE_PREFIX + entity.getDockSn();
Object mediaFileCount = RedisOpsUtils.hashGet(countKey, entity.getJobId());
if (Objects.nonNull(mediaFileCount)) {
builder.uploadedCount(((MediaFileCountDTO) mediaFileCount).getUploadedCount())
.uploading(RedisOpsUtils.checkExist(key) && entity.getJobId().equals(RedisOpsUtils.get(key)));
return builder.build();
}
int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getWorkspaceId(), entity.getJobId()).size();
// All media for this job have been uploaded.
if (uploadedSize >= entity.getMediaCount()) {
return builder.uploadedCount(uploadedSize).build();
}
RedisOpsUtils.hashSet(countKey, entity.getJobId(),
MediaFileCountDTO.builder()
.jobId(entity.getJobId())
.mediaCount(entity.getMediaCount())
.uploadedCount(uploadedSize).build());
return builder.build();
}
}

4
src/main/resources/application.yml

@ -27,6 +27,10 @@ spring: @@ -27,6 +27,10 @@ spring:
max-idle: 8
min-idle: 0
servlet:
multipart:
max-file-size: 2GB
max-request-size: 2GB
jwt:
issuer: DJI

37363
src/main/resources/hms.json

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save