Browse Source

What's new?

1. Add license for dock.
2. Modify the logic corresponding to the firmware file and device type.
3. Add multiple mqtt clients options.
4. Modify the structure of the interface for obtaining the device list.
5. Fixed some issues.
v1.3.1
sean.zhou 2 years ago
parent
commit
a7aaeabc78
  1. 30
      sql/cloud_sample.sql
  2. 6
      src/main/java/com/dji/sample/common/error/CommonErrorEnum.java
  3. 38
      src/main/java/com/dji/sample/common/error/StorageErrorEnum.java
  4. 57
      src/main/java/com/dji/sample/common/util/JwtUtil.java
  5. 4
      src/main/java/com/dji/sample/component/GlobalScheduleService.java
  6. 71
      src/main/java/com/dji/sample/component/mqtt/config/MqttConfiguration.java
  7. 9
      src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java
  8. 2
      src/main/java/com/dji/sample/component/mqtt/config/MqttOutboundConfiguration.java
  9. 2
      src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java
  10. 31
      src/main/java/com/dji/sample/component/mqtt/model/MqttClientOptions.java
  11. 30
      src/main/java/com/dji/sample/component/mqtt/model/MqttProtocolEnum.java
  12. 19
      src/main/java/com/dji/sample/component/mqtt/model/MqttUseEnum.java
  13. 3
      src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java
  14. 16
      src/main/java/com/dji/sample/component/redis/RedisConst.java
  15. 9
      src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
  16. 3
      src/main/java/com/dji/sample/control/service/impl/ControlServiceImpl.java
  17. 2
      src/main/java/com/dji/sample/manage/controller/DeviceController.java
  18. 16
      src/main/java/com/dji/sample/manage/controller/DeviceFirmwareController.java
  19. 27
      src/main/java/com/dji/sample/manage/dao/IDeviceFirmwareMapper.java
  20. 12
      src/main/java/com/dji/sample/manage/dao/IFirmwareModelMapper.java
  21. 32
      src/main/java/com/dji/sample/manage/model/common/AppLicenseProperties.java
  22. 4
      src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java
  23. 3
      src/main/java/com/dji/sample/manage/model/dto/DeviceFirmwareDTO.java
  24. 24
      src/main/java/com/dji/sample/manage/model/dto/FirmwareModelDTO.java
  25. 5
      src/main/java/com/dji/sample/manage/model/dto/LogsUploadCredentialsDTO.java
  26. 8
      src/main/java/com/dji/sample/manage/model/dto/ProductConfigDTO.java
  27. 2
      src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java
  28. 2
      src/main/java/com/dji/sample/manage/model/entity/DeviceFirmwareEntity.java
  29. 37
      src/main/java/com/dji/sample/manage/model/entity/FirmwareModelEntity.java
  30. 68
      src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java
  31. 3
      src/main/java/com/dji/sample/manage/model/param/DeviceFirmwareUploadParam.java
  32. 2
      src/main/java/com/dji/sample/manage/model/receiver/DistanceLimitStatusReceiver.java
  33. 11
      src/main/java/com/dji/sample/manage/service/IDeviceFirmwareService.java
  34. 2
      src/main/java/com/dji/sample/manage/service/IDeviceService.java
  35. 18
      src/main/java/com/dji/sample/manage/service/IFirmwareModelService.java
  36. 4
      src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java
  37. 5
      src/main/java/com/dji/sample/manage/service/impl/ConfigProductServiceImpl.java
  38. 85
      src/main/java/com/dji/sample/manage/service/impl/DeviceFirmwareServiceImpl.java
  39. 5
      src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java
  40. 135
      src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
  41. 2
      src/main/java/com/dji/sample/manage/service/impl/DockOSDServiceImpl.java
  42. 44
      src/main/java/com/dji/sample/manage/service/impl/FirmwareModelServiceImpl.java
  43. 2
      src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java
  44. 11
      src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java
  45. 16
      src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
  46. 45
      src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java
  47. 4
      src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
  48. 6
      src/main/java/com/dji/sample/wayline/model/dto/WaylineJobDTO.java
  49. 5
      src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskCreateDTO.java
  50. 2
      src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskFileDTO.java
  51. 2
      src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskProgress.java
  52. 6
      src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskProgressExt.java
  53. 6
      src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskProgressReceiver.java
  54. 8
      src/main/java/com/dji/sample/wayline/model/entity/WaylineJobEntity.java
  55. 4
      src/main/java/com/dji/sample/wayline/model/enums/WaylineJobStatusEnum.java
  56. 39
      src/main/java/com/dji/sample/wayline/service/IWaylineJobService.java
  57. 52
      src/main/java/com/dji/sample/wayline/service/impl/FlightTaskServiceImpl.java
  58. 2
      src/main/java/com/dji/sample/wayline/service/impl/WaylineFileServiceImpl.java
  59. 175
      src/main/java/com/dji/sample/wayline/service/impl/WaylineJobServiceImpl.java
  60. 32
      src/main/resources/application.yml

30
sql/cloud_sample.sql

@ -46,7 +46,7 @@ CREATE TABLE `logs_file_index` ( @@ -46,7 +46,7 @@ CREATE TABLE `logs_file_index` (
`file_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The file_id in the logs_file table.',
`start_time` bigint NOT NULL COMMENT 'The file start time reported by the dock.',
`end_time` bigint NOT NULL COMMENT 'The file end time reported by the dock.',
`size` int NOT NULL COMMENT 'The file size reported by the dock.',
`size` bigint NOT NULL COMMENT 'The file size reported by the dock.',
`device_sn` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The sn of the device.',
`domain` int NOT NULL COMMENT 'This parameter corresponds to the domain in the device dictionary table.',
`create_time` bigint NOT NULL,
@ -132,7 +132,9 @@ VALUES @@ -132,7 +132,9 @@ VALUES
(20,0,77,1,'Mavic 3T',NULL),
(21,1,66,0,'Mavic 3E Camera',NULL),
(22,1,67,0,'Mavic 3T Camera',NULL),
(23,2,144,0,'DJI RC Pro','Remote control for Mavic 3E/T');
(23,2,144,0,'DJI RC Pro','Remote control for Mavic 3E/T and Mavic 3M'),
(24,0,77,2,'Mavic 3M',NULL),
(25,1,68,0,'Mavic 3M Camera',NULL);
/*!40000 ALTER TABLE `manage_device_dictionary` ENABLE KEYS */;
UNLOCK TABLES;
@ -151,7 +153,6 @@ CREATE TABLE `manage_device_firmware` ( @@ -151,7 +153,6 @@ CREATE TABLE `manage_device_firmware` (
`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.',
@ -233,6 +234,22 @@ CREATE TABLE `manage_device_payload` ( @@ -233,6 +234,22 @@ CREATE TABLE `manage_device_payload` (
# manage_firmware_model
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_firmware_model`;
CREATE TABLE `manage_firmware_model` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`firmware_id` varchar(64) NOT NULL,
`device_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'model of the device. This parameter corresponds to the device name in the device dictionary table.',
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# manage_user
# ------------------------------------------------------------
@ -431,9 +448,11 @@ CREATE TABLE `wayline_job` ( @@ -431,9 +448,11 @@ CREATE TABLE `wayline_job` (
`workspace_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'Which workspace the current job belongs to.',
`task_type` int NOT NULL,
`wayline_type` int NOT NULL COMMENT 'The template type of the wayline.',
`execute_time` bigint NOT NULL,
`execute_time` bigint DEFAULT NULL COMMENT 'actual begin time',
`completed_time` bigint DEFAULT NULL COMMENT 'actual end time',
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'The name of the creator.',
`end_time` bigint DEFAULT NULL COMMENT 'end time of the job.',
`begin_time` bigint NOT NULL COMMENT 'planned begin time',
`end_time` bigint NOT NULL COMMENT 'planned end time',
`error_code` int DEFAULT NULL,
`status` int NOT NULL COMMENT '1: pending; 2: in progress; 3: success; 4: cancel; 5: failed',
`rth_altitude` int NOT NULL COMMENT 'return to home altitude. min: 20m; max: 500m',
@ -441,6 +460,7 @@ CREATE TABLE `wayline_job` ( @@ -441,6 +460,7 @@ CREATE TABLE `wayline_job` (
`media_count` int NOT NULL DEFAULT '0',
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
`parent_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `job_id_UNIQUE` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='Wayline mission information of the dock.';

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

@ -9,6 +9,10 @@ public enum CommonErrorEnum implements IErrorInfo { @@ -9,6 +9,10 @@ public enum CommonErrorEnum implements IErrorInfo {
ILLEGAL_ARGUMENT(200001, "illegal argument"),
REDIS_DATA_NOT_FOUND(201404, "Redis data does not exist."),
DEVICE_OFFLINE(212015, "Device is offline."),
GET_ORGANIZATION_FAILED(210230, "Failed to get organization."),
DEVICE_BINDING_FAILED(210231, "Failed to bind device."),
@ -21,7 +25,7 @@ public enum CommonErrorEnum implements IErrorInfo { @@ -21,7 +25,7 @@ public enum CommonErrorEnum implements IErrorInfo {
SECRET_INVALID(600100, "secret invalid"),
NO_TOKEN(600101, "accss_token is null"),
NO_TOKEN(600101, "token is null"),
TOKEN_EXPIRED(600102, "token is expired"),

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

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

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

@ -9,10 +9,9 @@ import com.dji.sample.common.model.CustomClaim; @@ -9,10 +9,9 @@ import com.dji.sample.common.model.CustomClaim;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
import java.util.*;
@Slf4j
@Component
@ -26,7 +25,7 @@ public class JwtUtil { @@ -26,7 +25,7 @@ public class JwtUtil {
private static String secret;
private static Algorithm algorithm;
public static Algorithm algorithm;
@Value("${jwt.issuer: DJI}")
private void setIssuer(String issuer) {
@ -62,15 +61,55 @@ public class JwtUtil { @@ -62,15 +61,55 @@ public class JwtUtil {
* @param claims custom information
* @return token
*/
public static String createToken(Map<String, String> claims) {
public static String createToken(Map<String, ?> claims) {
return JwtUtil.createToken(claims, age, algorithm, subject, issuer);
}
/**
*
* @param claims
* @param age unit: s
* @param algorithm
* @param subject
* @param issuer
* @return
*/
public static String createToken(Map<String, ?> claims, Long age, Algorithm algorithm, String subject, String issuer) {
if (Objects.isNull(algorithm)) {
throw new IllegalArgumentException();
}
Date now = new Date();
JWTCreator.Builder builder = JWT.create();
// Add custom information to the token's payload segment.
claims.forEach(builder::withClaim);
String token = builder.withIssuer(issuer)
.withSubject(subject)
claims.forEach((k, v) -> {
if (Objects.nonNull(v.getClass().getClassLoader())) {
log.error("claim can't be set to a custom object.");
return;
}
if (v instanceof Map) {
builder.withClaim(k, (Map) v);
} else if (v instanceof List) {
builder.withClaim(k, (List) v);
} else {
builder.withClaim(k, String.valueOf(v));
}
});
if (StringUtils.hasText(subject)) {
builder.withSubject(subject);
}
if (StringUtils.hasText(issuer)) {
builder.withIssuer(issuer);
}
if (Objects.nonNull(age)) {
builder.withExpiresAt(new Date(now.getTime() + age * 1000));
}
String token = builder
.withIssuedAt(now)
.withExpiresAt(new Date(now.getTime() + age))
.withNotBefore(now)
.sign(algorithm);
log.debug("token created. " + token);

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

@ -44,11 +44,13 @@ public class GlobalScheduleService { @@ -44,11 +44,13 @@ public class GlobalScheduleService {
long expire = RedisOpsUtils.getExpire(key);
if (expire <= 30) {
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(key);
if (device.getDomain().equals(DeviceDomainEnum.SUB_DEVICE.getDesc())) {
if (DeviceDomainEnum.SUB_DEVICE.getVal() == device.getDomain()) {
deviceService.subDeviceOffline(key.substring(start));
} else {
deviceService.unsubscribeTopicOffline(key.substring(start));
deviceService.pushDeviceOfflineTopo(device.getWorkspaceId(), device.getDeviceSn());
RedisOpsUtils.hashDel(RedisConst.LIVE_CAPACITY, new String[]{key});
RedisOpsUtils.del(RedisConst.HMS_PREFIX + key);
}
RedisOpsUtils.del(key);
}

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

@ -1,5 +1,10 @@ @@ -1,5 +1,10 @@
package com.dji.sample.component.mqtt.config;
import com.auth0.jwt.algorithms.Algorithm;
import com.dji.sample.common.util.JwtUtil;
import com.dji.sample.component.mqtt.model.MqttClientOptions;
import com.dji.sample.component.mqtt.model.MqttProtocolEnum;
import com.dji.sample.component.mqtt.model.MqttUseEnum;
import lombok.Data;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -7,6 +12,9 @@ import org.springframework.context.annotation.Bean; @@ -7,6 +12,9 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.util.StringUtils;
import java.util.Map;
/**
*
@ -16,39 +24,60 @@ import org.springframework.integration.mqtt.core.MqttPahoClientFactory; @@ -16,39 +24,60 @@ import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
*/
@Configuration
@Data
@ConfigurationProperties(prefix = "mqtt")
@ConfigurationProperties
public class MqttConfiguration {
private String protocol;
private String host;
private Integer port;
private static Map<MqttUseEnum, MqttClientOptions> mqtt;
private String username;
public void setMqtt(Map<MqttUseEnum, MqttClientOptions> mqtt) {
MqttConfiguration.mqtt = mqtt;
}
private String password;
/**
* Get the configuration options of the basic link of the mqtt client.
* @return
*/
static MqttClientOptions getBasicClientOptions() {
if (!mqtt.containsKey(MqttUseEnum.BASIC)) {
throw new Error("Please configure the basic mqtt connection parameters first, otherwise application cannot be started.");
}
return mqtt.get(MqttUseEnum.BASIC);
}
private String clientId;
/**
* Get the mqtt address of the basic link.
* @return
*/
public static String getBasicMqttAddress() {
return getMqttAddress(getBasicClientOptions());
}
/**
* The topic to subscribe to immediately when client connects.
* Splice the mqtt address according to the parameters of different clients.
* @param options
* @return
*/
private String inboundTopic;
private static String getMqttAddress(MqttClientOptions options) {
StringBuilder addr = new StringBuilder()
.append(options.getProtocol().getProtocolAddr())
.append(options.getHost().trim())
.append(":")
.append(options.getPort());
if ((options.getProtocol() == MqttProtocolEnum.WS || options.getProtocol() == MqttProtocolEnum.WSS)
&& StringUtils.hasText(options.getPath())) {
addr.append(options.getPath());
}
return addr.toString();
}
@Bean
public MqttConnectOptions mqttConnectOptions() {
MqttClientOptions customizeOptions = getBasicClientOptions();
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setServerURIs(new String[]{
new StringBuilder()
.append(protocol.trim())
.append("://")
.append(host.trim())
.append(":")
.append(port)
.toString()});
mqttConnectOptions.setUserName(username);
mqttConnectOptions.setPassword(password.toCharArray());
mqttConnectOptions.setServerURIs(new String[]{ getBasicMqttAddress() });
mqttConnectOptions.setUserName(customizeOptions.getUsername());
mqttConnectOptions.setPassword(StringUtils.hasText(customizeOptions.getPassword()) ?
customizeOptions.getPassword().toCharArray() : new char[0]);
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setKeepAliveInterval(10);
return mqttConnectOptions;

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

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package com.dji.sample.component.mqtt.config;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.MqttClientOptions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@ -28,9 +29,6 @@ import javax.annotation.Resource; @@ -28,9 +29,6 @@ import javax.annotation.Resource;
@IntegrationComponentScan
public class MqttInboundConfiguration {
@Autowired
private MqttConfiguration mqttConfiguration;
@Autowired
private MqttPahoClientFactory mqttClientFactory;
@ -43,9 +41,10 @@ public class MqttInboundConfiguration { @@ -43,9 +41,10 @@ public class MqttInboundConfiguration {
*/
@Bean(name = "adapter")
public MessageProducerSupport mqttInbound() {
MqttClientOptions options = MqttConfiguration.getBasicClientOptions();
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
mqttConfiguration.getClientId() + "_consumer_" + System.currentTimeMillis(),
mqttClientFactory, mqttConfiguration.getInboundTopic().split(","));
options.getClientId() + "_consumer_" + System.currentTimeMillis(),
mqttClientFactory, options.getInboundTopic().split(","));
DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
// use byte types uniformly
converter.setPayloadAsBytes(true);

2
src/main/java/com/dji/sample/component/mqtt/config/MqttOutboundConfiguration.java

@ -33,7 +33,7 @@ public class MqttOutboundConfiguration { @@ -33,7 +33,7 @@ public class MqttOutboundConfiguration {
@ServiceActivator(inputChannel = ChannelName.OUTBOUND)
public MessageHandler mqttOutbound() {
MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(
mqttConfiguration.getClientId() + "_producer_" + System.currentTimeMillis(),
MqttConfiguration.getBasicClientOptions().getClientId() + "_producer_" + System.currentTimeMillis(),
mqttClientFactory);
DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
// use byte types uniformly

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

@ -33,4 +33,6 @@ public final class MapKeyConst { @@ -33,4 +33,6 @@ public final class MapKeyConst {
public static final String FLIGHT_IDS = "flight_ids";
public static final String ACL = "acl";
}

31
src/main/java/com/dji/sample/component/mqtt/model/MqttClientOptions.java

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
package com.dji.sample.component.mqtt.model;
import lombok.Data;
/**
* @author sean
* @version 1.3
* @date 2023/1/18
*/
@Data
public class MqttClientOptions {
private MqttProtocolEnum protocol;
private String host;
private Integer port;
private String username;
private String password;
private String clientId;
private String path;
/**
* The topic to subscribe to immediately when client connects. Only required for basic link.
*/
private String inboundTopic;
}

30
src/main/java/com/dji/sample/component/mqtt/model/MqttProtocolEnum.java

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
package com.dji.sample.component.mqtt.model;
import lombok.Getter;
/**
* @author sean
* @version 1.3
* @date 2023/1/18
*/
@Getter
public enum MqttProtocolEnum {
MQTT("tcp"),
MQTTS("tcp"),
WS("ws"),
WSS("wss");
String protocol;
MqttProtocolEnum(String protocol) {
this.protocol = protocol;
}
public String getProtocolAddr() {
return protocol + "://";
}
}

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

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
package com.dji.sample.component.mqtt.model;
/**
* @author sean
* @version 1.3
* @date 2023/1/18
*/
public enum MqttUseEnum {
/**
* The broker is used for basic link.
*/
BASIC,
/**
* This broker is used for the drc link.
*/
DRC
}

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

@ -31,7 +31,7 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -31,7 +31,7 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
public void publish(String topic, CommonTopicResponse response) {
try {
log.info("send topic: {}, payload: {}", topic, response.toString());
messageGateway.publish(topic, mapper.writeValueAsBytes(response));
} catch (JsonProcessingException e) {
log.info("Failed to publish the message. {}", response.toString());
@ -53,6 +53,7 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -53,6 +53,7 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
}
public <T> T publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response, int retryTime) {
log.info("send topic: {}, payload: {}", topic, response.toString());
AtomicInteger time = new AtomicInteger(0);
// Retry three times
while (time.getAndIncrement() <= retryTime) {

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

@ -9,6 +9,8 @@ import com.dji.sample.manage.model.enums.DeviceDomainEnum; @@ -9,6 +9,8 @@ import com.dji.sample.manage.model.enums.DeviceDomainEnum;
*/
public final class RedisConst {
public static final int WAYLINE_JOB_BLOCK_TIME = 600;
private RedisConst() {
}
@ -35,11 +37,23 @@ public final class RedisConst { @@ -35,11 +37,23 @@ public final class RedisConst {
public static final String LOGS_FILE_PREFIX = "logs_file" + DELIMITER;
public static final String WAYLINE_JOB = "wayline_job";
public static final String WAYLINE_JOB_TIMED_EXECUTE = "wayline_job_timed_execute";
public static final String WAYLINE_JOB_BLOCK_PREFIX = "wayline_job_block" + DELIMITER;
public static final String WAYLINE_JOB_RUNNING_PREFIX = "wayline_job_running" + DELIMITER;
public static final String WAYLINE_JOB_PAUSED_PREFIX = "wayline_job_paused" + DELIMITER;
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;
public static final String LIVE_CAPACITY = "live_capacity";
public static final String MQTT_ACL_PREFIX = "mqtt_acl" + DELIMITER;
public static final String FILE_UPLOADING_PREFIX = "file_uploading" + DELIMITER;
}

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

@ -251,4 +251,13 @@ public class RedisOpsUtils { @@ -251,4 +251,13 @@ public class RedisOpsUtils {
return redisTemplate.opsForZSet().score(key, value);
}
/**
* ZINCRBY
* @param key
* @param value
* @param delta
*/
public static Double zIncrement(String key, Object value, double delta) {
return redisTemplate.opsForZSet().incrementScore(key, value, delta);
}
}

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

@ -91,7 +91,8 @@ public class ControlServiceImpl implements IControlService { @@ -91,7 +91,8 @@ public class ControlServiceImpl implements IControlService {
serviceReplyOpt, new TypeReference<ServiceReply<EventsOutputReceiver>>() {});
if (ResponseResult.CODE_SUCCESS != serviceReply.getResult()) {
return ResponseResult.error(serviceReply.getResult(),
Objects.nonNull(serviceReply.getOutput()) ? serviceReply.getOutput().getStatus() : "error: " + serviceIdentifier);
Objects.nonNull(serviceReply.getOutput()) ? serviceReply.getOutput().getStatus()
: "error: " + serviceIdentifier + serviceReply.getResult());
}
if (controlMethodEnum.getProgress()) {
RedisOpsUtils.setWithExpire(serviceIdentifier + RedisConst.DELIMITER + bid, sn,

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

@ -120,7 +120,7 @@ public class DeviceController { @@ -120,7 +120,7 @@ public class DeviceController {
*/
@GetMapping("/{workspace_id}/devices/bound")
public ResponseResult<PaginationData<DeviceDTO>> getBoundDevicesWithDomain(
@PathVariable("workspace_id") String workspaceId, String domain,
@PathVariable("workspace_id") String workspaceId, Integer domain,
@RequestParam(defaultValue = "1") Long page,
@RequestParam(value = "page_size", defaultValue = "50") Long pageSize) {
PaginationData<DeviceDTO> devices = deviceService.getBoundDevicesWithDomain(workspaceId, page, pageSize, domain);

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

@ -18,9 +18,9 @@ import org.springframework.web.multipart.MultipartFile; @@ -18,9 +18,9 @@ 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 java.util.stream.Collectors;
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
@ -44,11 +44,13 @@ public class DeviceFirmwareController { @@ -44,11 +44,13 @@ public class DeviceFirmwareController {
*/
@GetMapping("/firmware-release-notes/latest")
public ResponseResult<List<DeviceFirmwareNoteDTO>> getLatestFirmwareNote(@RequestParam("device_name") List<String> deviceNames) {
List<DeviceFirmwareNoteDTO> releaseNotes = new ArrayList<>();
deviceNames.forEach(deviceName -> {
Optional<DeviceFirmwareNoteDTO> latestFirmware = service.getLatestFirmwareReleaseNote(deviceName);
latestFirmware.ifPresent(releaseNotes::add);
});
List<DeviceFirmwareNoteDTO> releaseNotes = deviceNames.stream()
.map(deviceName -> service.getLatestFirmwareReleaseNote(deviceName))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
return ResponseResult.success(releaseNotes);
}
@ -98,7 +100,7 @@ public class DeviceFirmwareController { @@ -98,7 +100,7 @@ public class DeviceFirmwareController {
* @return
*/
@PutMapping("/{workspace_id}/firmwares/{firmware_id}")
public ResponseResult importFirmwareFile(@PathVariable("workspace_id") String workspaceId,
public ResponseResult changeFirmwareStatus(@PathVariable("workspace_id") String workspaceId,
@PathVariable("firmware_id") String firmwareId,
@Valid @RequestBody DeviceFirmwareUpdateParam param) {

27
src/main/java/com/dji/sample/manage/dao/IDeviceFirmwareMapper.java

@ -1,7 +1,12 @@ @@ -1,7 +1,12 @@
package com.dji.sample.manage.dao;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.manage.model.entity.DeviceFirmwareEntity;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* @author sean
@ -9,4 +14,26 @@ import com.dji.sample.manage.model.entity.DeviceFirmwareEntity; @@ -9,4 +14,26 @@ import com.dji.sample.manage.model.entity.DeviceFirmwareEntity;
* @date 2022/8/16
*/
public interface IDeviceFirmwareMapper extends BaseMapper<DeviceFirmwareEntity> {
String sql = "<script> \n" +
"SELECT \n" +
" * \n" +
"from \n" +
" (\n" +
" select \n" +
" a.*, \n" +
" group_concat(b.device_name) device_name \n" +
" from \n" +
" manage_device_firmware a \n" +
" join manage_firmware_model b on a.firmware_id = b.firmware_id \n" +
" <if test='device_name != null and device_name != \"\"'> \n" +
" and b.device_name = #{device_name} \n" +
" </if> \n" +
" group by firmware_id \n" +
" ) c ${ew.customSqlSegment} \n";
@Select(sql + "</script>")
Page<DeviceFirmwareEntity> selectPage(Page page, @Param(Constants.WRAPPER)Wrapper<DeviceFirmwareEntity> wrapper, @Param("device_name") String deviceName);
@Select(sql + " limit 1 </script>")
DeviceFirmwareEntity selectOne(@Param(Constants.WRAPPER)Wrapper<DeviceFirmwareEntity> wrapper, @Param("device_name") String deviceName);
}

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

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

32
src/main/java/com/dji/sample/manage/model/common/AppLicenseProperties.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package com.dji.sample.manage.model.common;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author sean
* @version 1.3.1
* @date 2023/1/5
*/
@Component
@ConfigurationProperties("cloud-api.app")
public class AppLicenseProperties {
public static String id;
public static String key;
public static String license;
public void setId(String id) {
AppLicenseProperties.id = id;
}
public void setKey(String key) {
AppLicenseProperties.key = key;
}
public void setLicense(String license) {
AppLicenseProperties.license = license;
}
}

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

@ -31,14 +31,12 @@ public class DeviceDTO { @@ -31,14 +31,12 @@ public class DeviceDTO {
private String childDeviceSn;
private String domain;
private Integer domain;
private Integer type;
private Integer subType;
private List<DeviceDTO> gatewaysList;
private List<DevicePayloadDTO> payloadsList;
private IconUrlDTO iconUrl;

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

@ -6,6 +6,7 @@ import lombok.Data; @@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.util.List;
/**
* @author sean
@ -30,7 +31,7 @@ public class DeviceFirmwareDTO { @@ -30,7 +31,7 @@ public class DeviceFirmwareDTO {
private String fileMd5;
private String deviceName;
private List<String> deviceName;
private String releaseNote;

24
src/main/java/com/dji/sample/manage/model/dto/FirmwareModelDTO.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package com.dji.sample.manage.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author sean
* @version 1.3
* @date 2022/12/21
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FirmwareModelDTO {
private String firmwareId;
private List<String> deviceNames;
}

5
src/main/java/com/dji/sample/manage/model/dto/LogsUploadCredentialsDTO.java

@ -35,13 +35,16 @@ public class LogsUploadCredentialsDTO { @@ -35,13 +35,16 @@ public class LogsUploadCredentialsDTO {
private LogsFileUploadList params;
private String region;
public LogsUploadCredentialsDTO(StsCredentialsDTO sts) {
this.bucket = sts.getBucket();
Long expire = sts.getCredentials().getExpire();
long expire = sts.getCredentials().getExpire();
sts.getCredentials().setExpire(System.currentTimeMillis() + (expire - 60) * 1000);
this.credentials = sts.getCredentials();
this.endpoint = sts.getEndpoint();
this.objectKeyPrefix = sts.getObjectKeyPrefix();
this.provider = sts.getProvider();
this.region = sts.getRegion();
}
}

8
src/main/java/com/dji/sample/manage/model/dto/NtpServerDTO.java → src/main/java/com/dji/sample/manage/model/dto/ProductConfigDTO.java

@ -12,7 +12,13 @@ import lombok.NoArgsConstructor; @@ -12,7 +12,13 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NtpServerDTO {
public class ProductConfigDTO {
private String ntpServerHost;
private String appId;
private String appKey;
private String appLicense;
}

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

@ -38,5 +38,5 @@ public class TopologyDeviceDTO { @@ -38,5 +38,5 @@ public class TopologyDeviceDTO {
private String gatewaySn;
private String domain;
private Integer domain;
}

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

@ -43,7 +43,7 @@ public class DeviceFirmwareEntity implements Serializable { @@ -43,7 +43,7 @@ public class DeviceFirmwareEntity implements Serializable {
@TableField("file_md5")
private String fileMd5;
@TableField("device_name")
@TableField(exist = false)
private String deviceName;
@TableField("release_note")

37
src/main/java/com/dji/sample/manage/model/entity/FirmwareModelEntity.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
package com.dji.sample.manage.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author sean
* @version 1.3
* @date 2022/12/21
*/
@Data
@TableName("manage_firmware_model")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FirmwareModelEntity implements Serializable {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("firmware_id")
private String firmwareId;
@TableField("device_name")
private String deviceName;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Long createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Long updateTime;
}

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

@ -1,77 +1,27 @@ @@ -1,77 +1,27 @@
package com.dji.sample.manage.model.enums;
import lombok.Getter;
/**
*
* @author sean.zhou
* @date 2021/11/15
* @version 0.1
*/
@Getter
public enum DeviceDomainEnum {
SUB_DEVICE(0, "sub-device"),
GATEWAY(2, "gateway"),
PAYLOAD(1, "payload"),
SUB_DEVICE(0),
DOCK (3, "dock"),
GATEWAY(2),
UNKNOWN(-1, "unknown");
PAYLOAD(1),
private int val;
DOCK (3);
private String desc;
int val;
DeviceDomainEnum(int val, String desc) {
DeviceDomainEnum(int val) {
this.val = val;
this.desc = desc;
}
public int getVal() {
return val;
}
public String getDesc() {
return desc;
}
public static String getDesc(int val) {
if (SUB_DEVICE.val == val) {
return SUB_DEVICE.desc;
}
if (GATEWAY.val == val) {
return GATEWAY.desc;
}
if (PAYLOAD.val == val) {
return PAYLOAD.desc;
}
if (DOCK.val == val) {
return DOCK.desc;
}
return UNKNOWN.desc;
}
public static int getVal(String desc) {
if (SUB_DEVICE.desc.equals(desc)) {
return SUB_DEVICE.val;
}
if (GATEWAY.desc.equals(desc)) {
return GATEWAY.val;
}
if (PAYLOAD.desc.equals(desc)) {
return PAYLOAD.val;
}
if (DOCK.desc.equals(desc)) {
return DOCK.val;
}
return UNKNOWN.val;
}
}

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

@ -3,6 +3,7 @@ package com.dji.sample.manage.model.param; @@ -3,6 +3,7 @@ package com.dji.sample.manage.model.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author sean
@ -19,5 +20,5 @@ public class DeviceFirmwareUploadParam { @@ -19,5 +20,5 @@ public class DeviceFirmwareUploadParam {
private Boolean status;
@NotNull
private String deviceName;
private List<String> deviceName;
}

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

@ -35,7 +35,7 @@ public class DistanceLimitStatusReceiver extends BasicDeviceProperty { @@ -35,7 +35,7 @@ public class DistanceLimitStatusReceiver extends BasicDeviceProperty {
valid = StateSwitchEnum.find(state).isPresent();
}
if (Objects.nonNull(distanceLimit)) {
valid &= StateSwitchEnum.find(distanceLimit).isPresent();
valid &= distanceLimit >= DISTANCE_MIN && distanceLimit <= DISTANCE_MAX;
}
return valid;
}

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

@ -23,11 +23,13 @@ public interface IDeviceFirmwareService { @@ -23,11 +23,13 @@ public interface IDeviceFirmwareService {
/**
* Query specific firmware information based on the device model and firmware version.
*
* @param workspaceId
* @param deviceName
* @param version
* @return
*/
Optional<DeviceFirmwareDTO> getFirmware(String deviceName, String version);
Optional<DeviceFirmwareDTO> getFirmware(String workspaceId, String deviceName, String version);
/**
* Get the latest firmware release note for this device model.
@ -38,10 +40,12 @@ public interface IDeviceFirmwareService { @@ -38,10 +40,12 @@ public interface IDeviceFirmwareService {
/**
* Get the firmware information that the device needs to update.
*
* @param workspaceId
* @param upgradeDTOS
* @return
*/
List<DeviceOtaCreateParam> getDeviceOtaFirmware(List<DeviceFirmwareUpgradeDTO> upgradeDTOS);
List<DeviceOtaCreateParam> getDeviceOtaFirmware(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS);
/**
* Interface to handle device firmware update progress.
@ -80,8 +84,9 @@ public interface IDeviceFirmwareService { @@ -80,8 +84,9 @@ public interface IDeviceFirmwareService {
/**
* Save the file information of the firmware.
* @param firmware
* @param deviceNames
*/
void saveFirmwareInfo(DeviceFirmwareDTO firmware);
void saveFirmwareInfo(DeviceFirmwareDTO firmware, List<String> deviceNames);
/**
* Update the file information of the firmware.

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

@ -180,7 +180,7 @@ public interface IDeviceService { @@ -180,7 +180,7 @@ public interface IDeviceService {
* @param domain
* @return
*/
PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page, Long pageSize, String domain);
PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page, Long pageSize, Integer domain);
/**
* Unbind device base on device's sn.

18
src/main/java/com/dji/sample/manage/service/IFirmwareModelService.java

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
package com.dji.sample.manage.service;
import com.dji.sample.manage.model.dto.FirmwareModelDTO;
/**
* @author sean
* @version 1.3
* @date 2022/12/21
*/
public interface IFirmwareModelService {
/**
* Save the relationship between firmware files and device models.
* @param firmwareModel
*/
void saveFirmwareDeviceName(FirmwareModelDTO firmwareModel);
}

4
src/main/java/com/dji/sample/manage/service/impl/AbstractTSAService.java

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
package com.dji.sample.manage.service.impl;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
@ -28,9 +27,6 @@ public abstract class AbstractTSAService implements ITSAService { @@ -28,9 +27,6 @@ public abstract class AbstractTSAService implements ITSAService {
@Autowired
protected ObjectMapper mapper;
@Autowired
protected RedisOpsUtils redisOps;
@Autowired
private IWebSocketManageService webSocketManageService;

5
src/main/java/com/dji/sample/manage/service/impl/ConfigProductServiceImpl.java

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
package com.dji.sample.manage.service.impl;
import com.dji.sample.manage.model.common.AppLicenseProperties;
import com.dji.sample.manage.model.common.NtpServerProperties;
import com.dji.sample.manage.model.dto.NtpServerDTO;
import com.dji.sample.manage.model.dto.ProductConfigDTO;
import com.dji.sample.manage.service.IRequestsConfigService;
import org.springframework.stereotype.Service;
@ -15,6 +16,6 @@ public class ConfigProductServiceImpl implements IRequestsConfigService { @@ -15,6 +16,6 @@ public class ConfigProductServiceImpl implements IRequestsConfigService {
@Override
public Object getConfig() {
return new NtpServerDTO(NtpServerProperties.host);
return new ProductConfigDTO(NtpServerProperties.host, AppLicenseProperties.id, AppLicenseProperties.key, AppLicenseProperties.license);
}
}

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

@ -2,6 +2,7 @@ package com.dji.sample.manage.service.impl; @@ -2,6 +2,7 @@ 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.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.common.model.Pagination;
import com.dji.sample.common.model.PaginationData;
@ -12,6 +13,7 @@ import com.dji.sample.component.oss.model.OssConfiguration; @@ -12,6 +13,7 @@ import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.service.impl.OssServiceContext;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.component.websocket.service.impl.SendMessageServiceImpl;
@ -24,6 +26,7 @@ import com.dji.sample.manage.model.param.DeviceFirmwareUploadParam; @@ -24,6 +26,7 @@ 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;
import com.dji.sample.manage.service.IFirmwareModelService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@ -79,26 +82,30 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -79,26 +82,30 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
@Autowired
private OssServiceContext ossServiceContext;
@Autowired
private IFirmwareModelService firmwareModelService;
@Override
public Optional<DeviceFirmwareDTO> getFirmware(String deviceName, String version) {
public Optional<DeviceFirmwareDTO> getFirmware(String workspaceId, String deviceName, String version) {
return Optional.ofNullable(entity2Dto(mapper.selectOne(
new LambdaQueryWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getDeviceName, deviceName)
.eq(DeviceFirmwareEntity::getFirmwareVersion, version))));
.eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId)
.eq(DeviceFirmwareEntity::getFirmwareVersion, version)
.eq(DeviceFirmwareEntity::getStatus, true),
deviceName)));
}
@Override
public Optional<DeviceFirmwareNoteDTO> getLatestFirmwareReleaseNote(String deviceName) {
return Optional.ofNullable(entity2NoteDto(mapper.selectOne(
new LambdaQueryWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getDeviceName, deviceName)
Wrappers.lambdaQuery(DeviceFirmwareEntity.class)
.eq(DeviceFirmwareEntity::getStatus, true)
.orderByDesc(DeviceFirmwareEntity::getReleaseDate, DeviceFirmwareEntity::getFirmwareVersion)
.last(" limit 1 "))));
.orderByDesc(DeviceFirmwareEntity::getReleaseDate, DeviceFirmwareEntity::getFirmwareVersion),
deviceName)));
}
@Override
public List<DeviceOtaCreateParam> getDeviceOtaFirmware(List<DeviceFirmwareUpgradeDTO> upgradeDTOS) {
public List<DeviceOtaCreateParam> getDeviceOtaFirmware(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) {
List<DeviceOtaCreateParam> deviceOtaList = new ArrayList<>();
upgradeDTOS.forEach(upgradeDevice -> {
boolean exist = deviceService.checkDeviceOnline(upgradeDevice.getSn());
@ -106,12 +113,9 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -106,12 +113,9 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
throw new IllegalArgumentException("Device is offline.");
}
Optional<DeviceFirmwareDTO> firmwareOpt = this.getFirmware(
upgradeDevice.getDeviceName(), upgradeDevice.getProductVersion());
workspaceId, upgradeDevice.getDeviceName(), upgradeDevice.getProductVersion());
if (firmwareOpt.isEmpty()) {
throw new IllegalArgumentException("This firmware version does not exist.");
}
if (!firmwareOpt.get().getFirmwareStatus()) {
throw new IllegalArgumentException("This firmware version is not available.");
throw new IllegalArgumentException("This firmware version does not exist or is not available.");
}
DeviceOtaCreateParam ota = dto2OtaCreateDto(firmwareOpt.get());
ota.setSn(upgradeDevice.getSn());
@ -131,7 +135,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -131,7 +135,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
EventsReceiver<EventsOutputReceiver> eventsReceiver = objectMapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<EventsOutputReceiver>>(){});
eventsReceiver.setBid(receiver.getBid());
eventsReceiver.setSn(sn);
EventsOutputReceiver output = eventsReceiver.getOutput();
log.info("SN: {}, {} ===> Upgrading progress: {}",
@ -148,6 +151,13 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -148,6 +151,13 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
// Determine whether it is the ending state, delete the update state key in redis after the job ends.
EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus());
Collection<ConcurrentWebSocketSession> sessions = webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal());
CustomWebSocketMessage<Object> build = CustomWebSocketMessage.builder()
.data(eventsReceiver)
.timestamp(System.currentTimeMillis())
.bizCode(receiver.getMethod())
.build();
if (upgrade) {
if (statusEnum.getEnd()) {
// Delete the cache after the update is complete.
@ -158,8 +168,14 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -158,8 +168,14 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
RedisConst.FIRMWARE_UPGRADING_PREFIX + sn, output.getProgress().getPercent(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
}
eventsReceiver.setSn(sn);
webSocketMessageService.sendBatch(sessions, build);
}
if (childUpgrade) {
if (!StringUtils.hasText(eventsReceiver.getSn())) {
eventsReceiver.setSn(childDeviceSn);
webSocketMessageService.sendBatch(sessions, build);
}
if (statusEnum.getEnd()) {
RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn);
} else {
@ -170,15 +186,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -170,15 +186,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
}
}
webSocketMessageService.sendBatch(
webSocketManageService.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
CustomWebSocketMessage.builder()
.data(eventsReceiver)
.timestamp(System.currentTimeMillis())
.bizCode(receiver.getMethod())
.build());
if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) {
String replyTopic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF;
messageSenderService.publish(replyTopic,
@ -194,7 +201,8 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -194,7 +201,8 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
@Override
public Boolean checkFileExist(String workspaceId, String fileMd5) {
return mapper.selectCount(new LambdaQueryWrapper<DeviceFirmwareEntity>()
return RedisOpsUtils.checkExist(RedisConst.FILE_UPLOADING_PREFIX + workspaceId + fileMd5) ||
mapper.selectCount(new LambdaQueryWrapper<DeviceFirmwareEntity>()
.eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId)
.eq(DeviceFirmwareEntity::getFileMd5, fileMd5))
> 0;
@ -206,9 +214,8 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -206,9 +214,8 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
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));
.orderByDesc(DeviceFirmwareEntity::getReleaseDate), param.getDeviceName());
List<DeviceFirmwareDTO> data = page.getRecords().stream().map(this::entity2Dto).collect(Collectors.toList());
return new PaginationData<DeviceFirmwareDTO>(data, new Pagination(page));
@ -217,14 +224,21 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -217,14 +224,21 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
@Override
public void importFirmwareFile(String workspaceId, String creator, DeviceFirmwareUploadParam param, MultipartFile file) {
String key = RedisConst.FILE_UPLOADING_PREFIX + workspaceId;
String existKey = key + file.getOriginalFilename();
if (RedisOpsUtils.getExpire(existKey) > 0) {
throw new RuntimeException("Please try again later.");
}
RedisOpsUtils.setWithExpire(existKey, true, RedisConst.DEVICE_ALIVE_SECOND);
try (InputStream is = file.getInputStream()) {
long size = is.available();
String md5 = DigestUtils.md5DigestAsHex(is);
key += md5;
boolean exist = checkFileExist(workspaceId, md5);
if (exist) {
throw new RuntimeException("The file already exists.");
}
RedisOpsUtils.set(key, System.currentTimeMillis());
Optional<DeviceFirmwareDTO> firmwareOpt = verifyFirmwareFile(file);
if (firmwareOpt.isEmpty()) {
throw new RuntimeException("The file format is incorrect.");
@ -234,9 +248,8 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -234,9 +248,8 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
String objectKey = OssConfiguration.objectDirPrefix + File.separator + firmwareId + FirmwareFileProperties.FIRMWARE_FILE_SUFFIX;
ossServiceContext.putObject(OssConfiguration.bucket, objectKey, file.getInputStream());
log.info("upload success");
log.info("upload success. {}", file.getOriginalFilename());
DeviceFirmwareDTO firmware = DeviceFirmwareDTO.builder()
.deviceName(param.getDeviceName())
.releaseNote(param.getReleaseNote())
.firmwareStatus(param.getStatus())
.fileMd5(md5)
@ -250,15 +263,20 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -250,15 +263,20 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
.firmwareId(firmwareId)
.build();
saveFirmwareInfo(firmware);
saveFirmwareInfo(firmware, param.getDeviceName());
} catch (IOException e) {
e.printStackTrace();
} finally {
RedisOpsUtils.del(key);
}
}
@Override
public void saveFirmwareInfo(DeviceFirmwareDTO firmware) {
mapper.insert(dto2Entity(firmware));
public void saveFirmwareInfo(DeviceFirmwareDTO firmware, List<String> deviceNames) {
DeviceFirmwareEntity entity = dto2Entity(firmware);
mapper.insert(entity);
firmwareModelService.saveFirmwareDeviceName(
FirmwareModelDTO.builder().firmwareId(entity.getFirmwareId()).deviceNames(deviceNames).build());
}
@Override
@ -308,7 +326,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -308,7 +326,6 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
}
return DeviceFirmwareEntity.builder()
.fileName(dto.getFileName())
.deviceName(dto.getDeviceName())
.fileMd5(dto.getFileMd5())
.fileSize(dto.getFileSize())
.firmwareId(dto.getFirmwareId())
@ -340,7 +357,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { @@ -340,7 +357,7 @@ public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService {
return null;
}
return DeviceFirmwareDTO.builder()
.deviceName(entity.getDeviceName())
.deviceName(Arrays.asList(entity.getDeviceName().split(",")))
.fileMd5(entity.getFileMd5())
.fileSize(entity.getFileSize())
.objectKey(entity.getObjectKey())

5
src/main/java/com/dji/sample/manage/service/impl/DeviceOSDServiceImpl.java

@ -2,6 +2,7 @@ package com.dji.sample.manage.service.impl; @@ -2,6 +2,7 @@ package com.dji.sample.manage.service.impl;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
@ -58,7 +59,7 @@ public class DeviceOSDServiceImpl extends AbstractTSAService { @@ -58,7 +59,7 @@ public class DeviceOSDServiceImpl extends AbstractTSAService {
public void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
Collection<ConcurrentWebSocketSession> webSessions,
CustomWebSocketMessage<TelemetryDTO> wsMessage) {
if (DeviceDomainEnum.SUB_DEVICE.getDesc().equals(device.getDomain())) {
if (DeviceDomainEnum.SUB_DEVICE.getVal() == device.getDomain()) {
wsMessage.setBizCode(BizCodeEnum.DEVICE_OSD.getCode());
OsdSubDeviceReceiver data = mapper.convertValue(receiver.getData(), OsdSubDeviceReceiver.class);
@ -75,7 +76,7 @@ public class DeviceOSDServiceImpl extends AbstractTSAService { @@ -75,7 +76,7 @@ public class DeviceOSDServiceImpl extends AbstractTSAService {
log.warn("Please remount the payload, or restart the drone. Otherwise the data of the payload will not be received.");
}
redisOps.setWithExpire(RedisConst.OSD_PREFIX + device.getDeviceSn(), data, RedisConst.DEVICE_ALIVE_SECOND);
RedisOpsUtils.setWithExpire(RedisConst.OSD_PREFIX + device.getDeviceSn(), data, RedisConst.DEVICE_ALIVE_SECOND);
wsMessage.getData().setHost(data);
sendMessageService.sendBatch(webSessions, wsMessage);

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

@ -111,8 +111,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -111,8 +111,6 @@ public class DeviceServiceImpl implements IDeviceService {
Optional<DeviceDTO> gatewayOpt = this.getDeviceBySn(gatewaySn);
if (gatewayOpt.isPresent()) {
DeviceDTO value = gatewayOpt.get();
value.setBoundTime(null);
value.setLoginTime(null);
RedisOpsUtils.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
this.pushDeviceOnlineTopo(value.getWorkspaceId(), gatewaySn, gatewaySn);
return true;
@ -120,7 +118,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -120,7 +118,7 @@ public class DeviceServiceImpl implements IDeviceService {
// When connecting for the first time
DeviceEntity gatewayDevice = deviceGatewayConvertToDeviceEntity(gateway);
return firstSaveDevice(gatewayDevice, null);
return onlineSaveDevice(gatewayDevice, null).isPresent();
}
DeviceDTO deviceDTO = (DeviceDTO) (RedisOpsUtils.get(key));
@ -151,6 +149,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -151,6 +149,7 @@ public class DeviceServiceImpl implements IDeviceService {
RedisOpsUtils.del(key);
RedisOpsUtils.del(RedisConst.OSD_PREFIX + device.getDeviceSn());
RedisOpsUtils.del(RedisConst.HMS_PREFIX + device.getDeviceSn());
log.debug("{} offline.", deviceSn);
return true;
}
@ -185,8 +184,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -185,8 +184,8 @@ public class DeviceServiceImpl implements IDeviceService {
DeviceQueryParam.builder()
.childSn(deviceSn)
.build());
gatewaysList.stream().filter(
gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn()))
gatewaysList.stream()
.filter(gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn()))
.findAny()
.ifPresent(gateway -> {
gateway.setChildDeviceSn("");
@ -194,34 +193,33 @@ public class DeviceServiceImpl implements IDeviceService { @@ -194,34 +193,33 @@ public class DeviceServiceImpl implements IDeviceService {
});
DeviceEntity gateway = deviceGatewayConvertToDeviceEntity(deviceGateway);
DeviceEntity subDevice = subDeviceConvertToDeviceEntity(deviceGateway.getSubDevices().get(0));
boolean isSave = firstSaveDevice(gateway, deviceSn) && firstSaveDevice(subDevice, null);
if (!isSave) {
Optional<DeviceEntity> gatewayEntityOpt = onlineSaveDevice(gateway, deviceSn);
if (gatewayEntityOpt.isEmpty()) {
log.error("Failed to go online, please check the status data or code logic.");
return false;
}
// dock go online
if (deviceGateway.getDomain() != null && DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain()) {
Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(deviceGateway.getSn());
if (deviceOpt.isEmpty()) {
log.info("The dock is not bound and cannot go online. Please refer to the Cloud API document video for binding.");
return false;
}
gateway.setNickname(null);
subDevice.setNickname(null);
DeviceEntity subDevice = subDeviceConvertToDeviceEntity(deviceGateway.getSubDevices().get(0));
Optional<DeviceEntity> subDeviceEntityOpt = onlineSaveDevice(subDevice, null);
if (subDeviceEntityOpt.isEmpty()) {
log.error("Failed to go online, please check the status data or code logic.");
return false;
}
String workspaceId = subDevice.getWorkspaceId();
subDevice = subDeviceEntityOpt.get();
gateway = gatewayEntityOpt.get();
this.subscribeTopicOnline(deviceGateway.getSn());
if (!StringUtils.hasText(workspaceId)) {
log.info("The drone is not bound and cannot go online. Please refer to the Cloud API document video for binding.");
return true;
// dock go online
if (DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain() && !subDevice.getBoundStatus()) {
// Directly bind the drone of the dock to the same workspace as the dock.
bindDevice(DeviceDTO.builder().deviceSn(deviceSn).workspaceId(gateway.getWorkspaceId()).build());
subDevice.setWorkspaceId(gateway.getWorkspaceId());
}
// Subscribe to topic related to drone devices.
this.subscribeTopicOnline(deviceGateway.getSn());
this.subscribeTopicOnline(deviceSn);
this.pushDeviceOnlineTopo(workspaceId, deviceGateway.getSn(), deviceSn);
this.pushDeviceOnlineTopo(subDevice.getWorkspaceId(), deviceGateway.getSn(), deviceSn);
log.debug("{} online.", subDevice.getDeviceSn());
return true;
@ -305,34 +303,33 @@ public class DeviceServiceImpl implements IDeviceService { @@ -305,34 +303,33 @@ public class DeviceServiceImpl implements IDeviceService {
List<DeviceDTO> devicesList = this.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
.domains(List.of(DeviceDomainEnum.SUB_DEVICE.getVal()))
.domains(List.of(DeviceDomainEnum.GATEWAY.getVal(), DeviceDomainEnum.DOCK.getVal()))
.build());
devicesList.forEach(device -> {
this.spliceDeviceTopo(device);
device.setWorkspaceId(workspaceId);
device.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
});
devicesList.stream()
.filter(gateway -> DeviceDomainEnum.DOCK.getVal() == gateway.getDomain() ||
RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn()))
.forEach(this::spliceDeviceTopo);
return devicesList;
}
@Override
public void spliceDeviceTopo(DeviceDTO device) {
public void spliceDeviceTopo(DeviceDTO gateway) {
// remote controller
List<DeviceDTO> gatewaysList = getDevicesByParams(
DeviceQueryParam.builder()
.childSn(device.getDeviceSn())
.build());
// payloads
List<DevicePayloadDTO> payloadsList = payloadService
.getDevicePayloadEntitiesByDeviceSn(device.getDeviceSn());
gateway.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn()));
// sub device
if (!StringUtils.hasText(gateway.getChildDeviceSn())) {
return;
}
device.setGatewaysList(gatewaysList);
device.setPayloadsList(payloadsList);
DeviceDTO subDevice = getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()).get(0);
subDevice.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + subDevice.getDeviceSn()));
gateway.setChildren(subDevice);
// payloads
subDevice.setPayloadsList(payloadService.getDevicePayloadEntitiesByDeviceSn(gateway.getChildDeviceSn()));
}
@Override
@ -377,24 +374,20 @@ public class DeviceServiceImpl implements IDeviceService { @@ -377,24 +374,20 @@ public class DeviceServiceImpl implements IDeviceService {
TopologyDeviceDTO.TopologyDeviceDTOBuilder builder = TopologyDeviceDTO.builder();
if (device != null) {
int domain = DeviceDomainEnum.getVal(device.getDomain());
String subType = String.valueOf(device.getSubType());
String type = String.valueOf(device.getType());
builder.sn(device.getDeviceSn())
.deviceCallsign(device.getNickname())
.deviceModel(DeviceModelDTO.builder()
.domain(String.valueOf(domain))
.subType(subType)
.type(type)
.key(domain + "-" + type + "-" + subType)
.domain(String.valueOf(device.getDomain()))
.subType(String.valueOf(device.getSubType()))
.type(String.valueOf(device.getType()))
.key(device.getDomain() + "-" + device.getType() + "-" + device.getSubType())
.build())
.iconUrls(device.getIconUrl())
.onlineStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
.boundStatus(device.getBoundStatus())
.model(device.getDeviceName())
.userId(device.getUserId())
.domain(DeviceDomainEnum.getDesc(domain))
.domain(device.getDomain())
.build();
}
return builder.build();
@ -518,6 +511,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -518,6 +511,9 @@ public class DeviceServiceImpl implements IDeviceService {
.eq(DeviceEntity::getDeviceSn, entity.getDeviceSn()));
// Update the information directly if the device already exists.
if (deviceEntity != null) {
if (deviceEntity.getDeviceName().equals(entity.getNickname())) {
entity.setNickname(null);
}
entity.setId(deviceEntity.getId());
mapper.updateById(entity);
return Optional.of(deviceEntity);
@ -605,7 +601,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -605,7 +601,7 @@ public class DeviceServiceImpl implements IDeviceService {
.workspaceId(entity.getWorkspaceId())
.type(entity.getDeviceType())
.subType(entity.getSubType())
.domain(DeviceDomainEnum.getDesc(entity.getDomain()))
.domain(entity.getDomain())
.iconUrl(IconUrlDTO.builder()
.normalUrl(entity.getUrlNormal())
.selectUrl(entity.getUrlSelect())
@ -666,18 +662,19 @@ public class DeviceServiceImpl implements IDeviceService { @@ -666,18 +662,19 @@ public class DeviceServiceImpl implements IDeviceService {
}
String key = RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn();
DeviceDTO redisDevice = (DeviceDTO)RedisOpsUtils.get(key);
if (Objects.isNull(redisDevice)) {
if (!RedisOpsUtils.checkExist(key)) {
return false;
}
DeviceDTO redisDevice = (DeviceDTO)RedisOpsUtils.get(key);
redisDevice.setWorkspaceId(device.getWorkspaceId());
RedisOpsUtils.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
if (DeviceDomainEnum.GATEWAY.getDesc().equals(redisDevice.getDomain())) {
if (DeviceDomainEnum.GATEWAY.getVal() == redisDevice.getDomain()) {
this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()),
device.getDeviceSn(), device.getDeviceSn());
}
if (DeviceDomainEnum.SUB_DEVICE.getDesc().equals(redisDevice.getDomain())) {
if (DeviceDomainEnum.SUB_DEVICE.getVal() == redisDevice.getDomain()) {
DeviceDTO subDevice = this.getDevicesByParams(DeviceQueryParam.builder()
.childSn(device.getChildDeviceSn())
.build()).get(0);
@ -774,11 +771,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -774,11 +771,11 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page,
Long pageSize, String domain) {
Long pageSize, Integer domain) {
Page<DeviceEntity> pagination = mapper.selectPage(new Page<>(page, pageSize),
new LambdaQueryWrapper<DeviceEntity>()
.eq(DeviceEntity::getDomain, DeviceDomainEnum.getVal(domain))
.eq(DeviceEntity::getDomain, domain)
.eq(DeviceEntity::getWorkspaceId, workspaceId)
.eq(DeviceEntity::getBoundStatus, true));
List<DeviceDTO> devicesList = pagination.getRecords().stream().map(this::deviceEntityConvertToDTO)
@ -849,7 +846,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -849,7 +846,7 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public ResponseResult createDeviceOtaJob(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) {
List<DeviceOtaCreateParam> deviceOtaFirmwares = deviceFirmwareService.getDeviceOtaFirmware(upgradeDTOS);
List<DeviceOtaCreateParam> deviceOtaFirmwares = deviceFirmwareService.getDeviceOtaFirmware(workspaceId, upgradeDTOS);
if (deviceOtaFirmwares.isEmpty()) {
return ResponseResult.error();
}
@ -976,7 +973,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -976,7 +973,7 @@ public class DeviceServiceImpl implements IDeviceService {
.boundTime(dto.getBoundTime() != null ?
dto.getBoundTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
.childSn(dto.getChildDeviceSn())
.domain(StringUtils.hasText(dto.getDomain()) ? DeviceDomainEnum.getVal(dto.getDomain()) : null)
.domain(dto.getDomain())
.firmwareVersion(dto.getFirmwareVersion())
.compatibleStatus(dto.getFirmwareStatus() == null ? null :
DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE != DeviceFirmwareStatusEnum.find(dto.getFirmwareStatus()))
@ -1041,7 +1038,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -1041,7 +1038,7 @@ public class DeviceServiceImpl implements IDeviceService {
.build();
}
private Boolean firstSaveDevice(DeviceEntity device, String deviceSn) {
private Optional<DeviceEntity> onlineSaveDevice(DeviceEntity device, String childSn) {
Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(device.getDeviceSn());
if (deviceOpt.isEmpty()) {
@ -1049,15 +1046,19 @@ public class DeviceServiceImpl implements IDeviceService { @@ -1049,15 +1046,19 @@ public class DeviceServiceImpl implements IDeviceService {
device.setUrlNormal(IconUrlEnum.NORMAL_PERSON.getUrl());
// Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module.
device.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl());
device.setBoundStatus(false);
} else {
DeviceDTO oldDevice = deviceOpt.get();
device.setNickname(oldDevice.getNickname());
device.setBoundStatus(oldDevice.getBoundStatus());
}
deviceOpt.ifPresent(oldDevice -> device.setNickname(oldDevice.getNickname()));
device.setChildSn(deviceSn);
device.setChildSn(childSn);
device.setLoginTime(System.currentTimeMillis());
Optional<DeviceEntity> saveDeviceOpt = this.saveDevice(device);
if (saveDeviceOpt.isEmpty()) {
return false;
return saveDeviceOpt;
}
device.setWorkspaceId(saveDeviceOpt.get().getWorkspaceId());
@ -1065,13 +1066,13 @@ public class DeviceServiceImpl implements IDeviceService { @@ -1065,13 +1066,13 @@ public class DeviceServiceImpl implements IDeviceService {
DeviceDTO.builder()
.deviceSn(device.getDeviceSn())
.workspaceId(device.getWorkspaceId())
.childDeviceSn(deviceSn)
.domain(DeviceDomainEnum.getDesc(device.getDomain()))
.childDeviceSn(childSn)
.domain(device.getDomain())
.type(device.getDeviceType())
.subType(device.getSubType())
.build(),
RedisConst.DEVICE_ALIVE_SECOND);
return true;
return saveDeviceOpt;
}
}
}

2
src/main/java/com/dji/sample/manage/service/impl/DockOSDServiceImpl.java

@ -35,7 +35,7 @@ public class DockOSDServiceImpl extends AbstractTSAService { @@ -35,7 +35,7 @@ public class DockOSDServiceImpl extends AbstractTSAService {
Collection<ConcurrentWebSocketSession> webSessions,
CustomWebSocketMessage<TelemetryDTO> wsMessage) {
if (DeviceDomainEnum.DOCK.getDesc().equals(device.getDomain())) {
if (DeviceDomainEnum.DOCK.getVal() == device.getDomain()) {
wsMessage.setBizCode(BizCodeEnum.DOCK_OSD.getCode());
OsdDockReceiver data = mapper.convertValue(receiver.getData(), OsdDockReceiver.class);
wsMessage.getData().setHost(data);

44
src/main/java/com/dji/sample/manage/service/impl/FirmwareModelServiceImpl.java

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
package com.dji.sample.manage.service.impl;
import com.dji.sample.manage.dao.IFirmwareModelMapper;
import com.dji.sample.manage.model.dto.FirmwareModelDTO;
import com.dji.sample.manage.model.entity.FirmwareModelEntity;
import com.dji.sample.manage.service.IFirmwareModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author sean
* @version 1.3
* @date 2022/12/21
*/
@Service
@Transactional
public class FirmwareModelServiceImpl implements IFirmwareModelService {
@Autowired
private IFirmwareModelMapper mapper;
@Override
public void saveFirmwareDeviceName(FirmwareModelDTO firmwareModel) {
dto2Entity(firmwareModel).forEach(entity -> mapper.insert(entity));
}
private List<FirmwareModelEntity> dto2Entity(FirmwareModelDTO dto) {
if (Objects.isNull(dto) || CollectionUtils.isEmpty(dto.getDeviceNames())) {
return Collections.EMPTY_LIST;
}
return dto.getDeviceNames().stream()
.map(deviceName -> FirmwareModelEntity.builder()
.firmwareId(dto.getFirmwareId())
.deviceName(deviceName).build())
.collect(Collectors.toList());
}
}

2
src/main/java/com/dji/sample/manage/service/impl/GatewayOSDServiceImpl.java

@ -47,7 +47,7 @@ public class GatewayOSDServiceImpl extends AbstractTSAService { @@ -47,7 +47,7 @@ public class GatewayOSDServiceImpl extends AbstractTSAService {
public void handleOSD(CommonTopicReceiver receiver, DeviceDTO device,
Collection<ConcurrentWebSocketSession> webSessions,
CustomWebSocketMessage<TelemetryDTO> wsMessage) {
if (DeviceDomainEnum.GATEWAY.getDesc().equals(device.getDomain())) {
if (DeviceDomainEnum.GATEWAY.getVal() == device.getDomain()) {
wsMessage.setBizCode(BizCodeEnum.GATEWAY_OSD.getCode());
OsdGatewayReceiver data = mapper.convertValue(receiver.getData(), OsdGatewayReceiver.class);

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

@ -4,7 +4,6 @@ import com.dji.sample.common.error.LiveErrorEnum; @@ -4,7 +4,6 @@ import com.dji.sample.common.error.LiveErrorEnum;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.mqtt.model.ServiceReply;
import com.dji.sample.component.mqtt.model.StateDataEnum;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
@ -79,7 +78,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -79,7 +78,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
// Solve timing problems
for (CapacityDeviceReceiver capacityDeviceReceiver : liveCapacityReceiver.getDeviceList()) {
long last = (long) Objects.requireNonNullElse(
RedisOpsUtils.get(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + capacityDeviceReceiver.getSn()), 0L);
RedisOpsUtils.get(RedisConst.LIVE_CAPACITY + capacityDeviceReceiver.getSn()), 0L);
if (last > timestamp) {
return;
}
@ -126,8 +125,8 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -126,8 +125,8 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
.toString());
break;
case RTSP:
String url = receiveReply.getInfo().toString();
this.resolveUrlUser(url, live);
Object url = Objects.requireNonNullElse(receiveReply.getOutput(), receiveReply.getInfo());
this.resolveUrlUser(String.valueOf(url), live);
break;
case UNKNOWN:
return ResponseResult.error(LiveErrorEnum.URL_TYPE_NOT_SUPPORTED);
@ -186,7 +185,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -186,7 +185,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
if (ResponseResult.CODE_SUCCESS != responseResult.getCode()) {
return responseResult;
}
if (DeviceDomainEnum.GATEWAY.getDesc().equals(responseResult.getData().getDomain())) {
if (DeviceDomainEnum.GATEWAY.getVal() == responseResult.getData().getDomain()) {
return ResponseResult.error(LiveErrorEnum.FUNCTION_NOT_SUPPORT);
}
@ -232,7 +231,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService { @@ -232,7 +231,7 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
return ResponseResult.error(LiveErrorEnum.NO_AIRCRAFT);
}
if (deviceOpt.get().getDomain().equals(DeviceDomainEnum.DOCK.getDesc())) {
if (DeviceDomainEnum.DOCK.getVal() == deviceOpt.get().getDomain()) {
return ResponseResult.success(deviceOpt.get());
}
List<DeviceDTO> gatewayList = deviceService.getDevicesByParams(

16
src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java

@ -101,13 +101,7 @@ public class UserServiceImpl implements IUserService { @@ -101,13 +101,7 @@ public class UserServiceImpl implements IUserService {
String token = JwtUtil.createToken(customClaim.convertToMap());
UserDTO userDTO = entityConvertToDTO(userEntity);
userDTO.setMqttAddr(new StringBuilder()
.append(mqttConfiguration.getProtocol().trim())
.append("://")
.append(mqttConfiguration.getHost().trim())
.append(":")
.append(mqttConfiguration.getPort())
.toString());
userDTO.setMqttAddr(MqttConfiguration.getBasicMqttAddress());
userDTO.setAccessToken(token);
userDTO.setWorkspaceId(workspaceOpt.get().getWorkspaceId());
return ResponseResult.success(userDTO);
@ -218,13 +212,7 @@ public class UserServiceImpl implements IUserService { @@ -218,13 +212,7 @@ public class UserServiceImpl implements IUserService {
.userType(entity.getUserType())
.mqttUsername(entity.getMqttUsername())
.mqttPassword(entity.getMqttPassword())
.mqttAddr(new StringBuilder()
.append(mqttConfiguration.getProtocol().trim())
.append("://")
.append(mqttConfiguration.getHost().trim())
.append(":")
.append(mqttConfiguration.getPort())
.toString())
.mqttAddr(MqttConfiguration.getBasicMqttAddress())
.build();
}
}

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

@ -30,7 +30,6 @@ import org.springframework.stereotype.Service; @@ -30,7 +30,6 @@ 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;
@ -116,12 +115,12 @@ public class MediaServiceImpl implements IMediaService { @@ -116,12 +115,12 @@ public class MediaServiceImpl implements IMediaService {
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);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
Optional<WaylineJobDTO> jobOpt = waylineJobService.getJobByJobId(device.getWorkspaceId(), jobId);
if (jobOpt.isPresent()) {
boolean isSave = parseMediaFile(callback, jobOpt.get());
if (!isSave) {
@ -152,7 +151,8 @@ public class MediaServiceImpl implements IMediaService { @@ -152,7 +151,8 @@ public class MediaServiceImpl implements IMediaService {
// 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), ""))) {
if (RedisOpsUtils.checkExist(highestKey) &&
jobId.equals(((MediaFileCountDTO) RedisOpsUtils.get(highestKey)).getJobId())) {
RedisOpsUtils.del(highestKey);
}
@ -192,32 +192,39 @@ public class MediaServiceImpl implements IMediaService { @@ -192,32 +192,39 @@ public class MediaServiceImpl implements IMediaService {
return;
}
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());
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);
MediaFileCountDTO countDTO = new MediaFileCountDTO();
if (RedisOpsUtils.checkExist(key)) {
countDTO = (MediaFileCountDTO) RedisOpsUtils.get(key);
if (jobId.equals(countDTO.getJobId())) {
RedisOpsUtils.setWithExpire(key, countDTO, RedisConst.DEVICE_ALIVE_SECOND * 5);
return;
}
RedisOpsUtils.setWithExpire(key, jobId,
RedisConst.DEVICE_ALIVE_SECOND * 5);
countDTO.setPreJobId(countDTO.getJobId());
}
countDTO.setJobId(jobId);
DeviceDTO dock = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn);
RedisOpsUtils.setWithExpire(key, countDTO, 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())
.data(countDTO)
.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());
}
}

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

@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.*; @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
@ -68,7 +68,7 @@ public class WaylineJobController { @@ -68,7 +68,7 @@ public class WaylineJobController {
* @throws SQLException
*/
@DeleteMapping("/{workspace_id}/jobs")
public ResponseResult publishCancelJob(@RequestParam(name = "job_id") List<String> jobIds,
public ResponseResult publishCancelJob(@RequestParam(name = "job_id") Set<String> jobIds,
@PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
waylineJobService.cancelFlightTask(workspaceId, jobIds);
return ResponseResult.success();

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

@ -38,8 +38,12 @@ public class WaylineJobDTO { @@ -38,8 +38,12 @@ public class WaylineJobDTO {
private LocalDateTime executeTime;
private LocalDateTime beginTime;
private LocalDateTime endTime;
private LocalDateTime completedTime;
private Integer status;
private Integer progress;
@ -57,4 +61,6 @@ public class WaylineJobDTO { @@ -57,4 +61,6 @@ public class WaylineJobDTO {
private Integer uploadedCount;
private Boolean uploading;
private String parentId;
}

5
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskCreateDTO.java → src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskCreateDTO.java

@ -14,7 +14,7 @@ import lombok.NoArgsConstructor; @@ -14,7 +14,7 @@ import lombok.NoArgsConstructor;
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FlightTaskCreateDTO {
public class WaylineTaskCreateDTO {
private String flightId;
@ -24,9 +24,10 @@ public class FlightTaskCreateDTO { @@ -24,9 +24,10 @@ public class FlightTaskCreateDTO {
private Long executeTime;
private FlightTaskFileDTO file;
private WaylineTaskFileDTO file;
private Integer rthAltitude;
private Integer outOfControlAction;
}

2
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskFileDTO.java → src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskFileDTO.java

@ -14,7 +14,7 @@ import lombok.NoArgsConstructor; @@ -14,7 +14,7 @@ import lombok.NoArgsConstructor;
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FlightTaskFileDTO {
public class WaylineTaskFileDTO {
private String url;

2
src/main/java/com/dji/sample/wayline/model/dto/FLightTaskProgress.java → src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskProgress.java

@ -8,7 +8,7 @@ import lombok.Data; @@ -8,7 +8,7 @@ import lombok.Data;
* @date 2022/6/9
*/
@Data
public class FLightTaskProgress {
public class WaylineTaskProgress {
private Integer currentStep;

6
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressExt.java → src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskProgressExt.java

@ -8,9 +8,13 @@ import lombok.Data; @@ -8,9 +8,13 @@ import lombok.Data;
* @date 2022/6/9
*/
@Data
public class FlightTaskProgressExt {
public class WaylineTaskProgressExt {
private Integer currentWaypointIndex;
private Integer mediaCount;
private String flightId;
private String trackId;
}

6
src/main/java/com/dji/sample/wayline/model/dto/FlightTaskProgressReceiver.java → src/main/java/com/dji/sample/wayline/model/dto/WaylineTaskProgressReceiver.java

@ -8,11 +8,11 @@ import lombok.Data; @@ -8,11 +8,11 @@ import lombok.Data;
* @date 2022/6/9
*/
@Data
public class FlightTaskProgressReceiver {
public class WaylineTaskProgressReceiver {
private FlightTaskProgressExt ext;
private WaylineTaskProgressExt ext;
private FLightTaskProgress progress;
private WaylineTaskProgress progress;
private String status;

8
src/main/java/com/dji/sample/wayline/model/entity/WaylineJobEntity.java

@ -74,4 +74,12 @@ public class WaylineJobEntity implements Serializable { @@ -74,4 +74,12 @@ public class WaylineJobEntity implements Serializable {
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Long updateTime;
@TableField("begin_time")
private Long beginTime;
@TableField("completed_time")
private Long completedTime;
@TableField("parent_id")
private String parentId;
}

4
src/main/java/com/dji/sample/wayline/model/enums/WaylineJobStatusEnum.java

@ -22,7 +22,9 @@ public enum WaylineJobStatusEnum { @@ -22,7 +22,9 @@ public enum WaylineJobStatusEnum {
FAILED(5, true),
UNKNOWN(6, true);
PAUSED(6, false),
UNKNOWN(-1, true);
int val;

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

@ -5,11 +5,13 @@ import com.dji.sample.common.model.PaginationData; @@ -5,11 +5,13 @@ import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.dji.sample.wayline.model.param.CreateJobParam;
import org.springframework.messaging.MessageHeaders;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/**
@ -22,10 +24,21 @@ public interface IWaylineJobService { @@ -22,10 +24,21 @@ public interface IWaylineJobService {
/**
* Create wayline job in the database.
* @param param
* @param customClaim user info
* @param workspaceId user info
* @param username user info
* @param beginTime The time the job started.
* @param endTime The time the job ended.
* @return
*/
Optional<WaylineJobDTO> createWaylineJob(CreateJobParam param, CustomClaim customClaim);
Optional<WaylineJobDTO> createWaylineJob(CreateJobParam param, String workspaceId, String username, Long beginTime, Long endTime);
/**
* Create a sub-task based on the information of the parent task.
* @param workspaceId
* @param parentId
* @return
*/
Optional<WaylineJobDTO> createWaylineJobByParent(String workspaceId, String parentId);
/**
* Issue wayline mission to the dock.
@ -41,7 +54,7 @@ public interface IWaylineJobService { @@ -41,7 +54,7 @@ public interface IWaylineJobService {
* @throws SQLException
* @return
*/
Boolean executeFlightTask(String jobId);
Boolean executeFlightTask(String workspaceId, String jobId);
/**
* Cancel the task Base on job Ids.
@ -51,12 +64,30 @@ public interface IWaylineJobService { @@ -51,12 +64,30 @@ public interface IWaylineJobService {
*/
void cancelFlightTask(String workspaceId, Collection<String> jobIds);
/**
* Cancel the dock tasks that have been issued but have not yet been executed.
* @param workspaceId
* @param dockSn
* @param jobIds
*/
void publishCancelTask(String workspaceId, String dockSn, List<String> jobIds);
/**
* Query wayline jobs based on conditions.
* @param workspaceId
* @param jobIds
* @param status
* @return
*/
List<WaylineJobDTO> getJobsByConditions(String workspaceId, Collection<String> jobIds, WaylineJobStatusEnum status);
/**
* Query job information based on job id.
* @param workspaceId
* @param jobId
* @return job information
*/
Optional<WaylineJobDTO> getJobByJobId(String jobId);
Optional<WaylineJobDTO> getJobByJobId(String workspaceId, String jobId);
/**
* Update job data.

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

@ -12,8 +12,8 @@ import com.dji.sample.component.websocket.service.IWebSocketManageService; @@ -12,8 +12,8 @@ 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.dto.WaylineTaskProgressReceiver;
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum;
import com.dji.sample.wayline.service.IFlightTaskService;
import com.dji.sample.wayline.service.IWaylineJobService;
@ -29,7 +29,7 @@ import org.springframework.scheduling.annotation.Scheduled; @@ -29,7 +29,7 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@ -59,12 +59,15 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -59,12 +59,15 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
@Override
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS, outputChannel = ChannelName.OUTBOUND)
public void handleProgress(CommonTopicReceiver receiver, MessageHeaders headers) {
EventsReceiver<FlightTaskProgressReceiver> eventsReceiver = mapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<FlightTaskProgressReceiver>>(){});
String receivedTopic = String.valueOf(headers.get(MqttHeaders.RECEIVED_TOPIC));
String dockSn = receivedTopic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(),
receivedTopic.indexOf(TopicConst.EVENTS_SUF));
EventsReceiver<WaylineTaskProgressReceiver> eventsReceiver = mapper.convertValue(receiver.getData(),
new TypeReference<EventsReceiver<WaylineTaskProgressReceiver>>(){});
eventsReceiver.setBid(receiver.getBid());
eventsReceiver.setSn(receiver.getGateway());
FlightTaskProgressReceiver output = eventsReceiver.getOutput();
WaylineTaskProgressReceiver output = eventsReceiver.getOutput();
log.info("Task progress: {}", output.getProgress().toString());
@ -73,16 +76,19 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -73,16 +76,19 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
}
EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus());
String key = RedisConst.WAYLINE_JOB_RUNNING_PREFIX + dockSn;
RedisOpsUtils.setWithExpire(key, eventsReceiver, RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
if (statusEnum.getEnd()) {
WaylineJobDTO job = WaylineJobDTO.builder()
.jobId(receiver.getBid())
.status(WaylineJobStatusEnum.SUCCESS.getVal())
.endTime(LocalDateTime.now())
.completedTime(LocalDateTime.now())
.mediaCount(output.getExt().getMediaCount())
.build();
// record the update of the media count.
if (Objects.nonNull(job.getMediaCount())) {
if (Objects.nonNull(job.getMediaCount()) && job.getMediaCount() != 0) {
RedisOpsUtils.hashSet(RedisConst.MEDIA_FILE_PREFIX + receiver.getGateway(), job.getJobId(),
MediaFileCountDTO.builder().jobId(receiver.getBid()).mediaCount(job.getMediaCount()).uploadedCount(0).build());
}
@ -93,9 +99,9 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -93,9 +99,9 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
}
waylineJobService.updateJob(job);
RedisOpsUtils.del(receiver.getBid());
RedisOpsUtils.del(key);
RedisOpsUtils.del(RedisConst.WAYLINE_JOB_PAUSED_PREFIX + receiver.getBid());
}
RedisOpsUtils.setWithExpire(receiver.getBid(), eventsReceiver, RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
websocketMessageService.sendBatch(
@ -108,8 +114,7 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -108,8 +114,7 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
.build());
if (receiver.getNeedReply() == 1) {
String topic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF;
messageSender.publish(topic,
messageSender.publish(receivedTopic + TopicConst._REPLY_SUF,
CommonTopicResponse.builder()
.tid(receiver.getTid())
.bid(receiver.getBid())
@ -122,39 +127,42 @@ public class FlightTaskServiceImpl implements IFlightTaskService { @@ -122,39 +127,42 @@ public class FlightTaskServiceImpl implements IFlightTaskService {
@Scheduled(initialDelay = 10, fixedRate = 5, timeUnit = TimeUnit.SECONDS)
private void checkScheduledJob() {
Object jobIdValue = RedisOpsUtils.zGetMin(RedisConst.WAYLINE_JOB);
log.info("Check the timed jobs of the wayline. {}", jobIdValue);
Object jobIdValue = RedisOpsUtils.zGetMin(RedisConst.WAYLINE_JOB_TIMED_EXECUTE);
if (Objects.isNull(jobIdValue)) {
return;
}
String jobId = String.valueOf(jobIdValue);
double time = RedisOpsUtils.zScore(RedisConst.WAYLINE_JOB, jobIdValue);
log.info("Check the timed tasks of the wayline. {}", jobIdValue);
// format: {workspace_id}:{dock_sn}:{job_id}
String[] jobArr = String.valueOf(jobIdValue).split(RedisConst.DELIMITER);
double time = RedisOpsUtils.zScore(RedisConst.WAYLINE_JOB_TIMED_EXECUTE, jobIdValue);
long now = System.currentTimeMillis();
int offset = 30_000;
// Expired tasks are deleted directly.
if (time < now - offset) {
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB, jobId);
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB_TIMED_EXECUTE, jobIdValue);
waylineJobService.updateJob(WaylineJobDTO.builder()
.jobId(jobId)
.jobId(jobArr[2])
.status(WaylineJobStatusEnum.FAILED.getVal())
.endTime(LocalDateTime.now())
.executeTime(LocalDateTime.now())
.completedTime(LocalDateTime.now())
.code(HttpStatus.SC_REQUEST_TIMEOUT).build());
return;
}
if (now <= time && time <= now + offset) {
try {
waylineJobService.executeFlightTask(jobId);
waylineJobService.executeFlightTask(jobArr[0], jobArr[2]);
} catch (Exception e) {
log.info("The scheduled task delivery failed.");
waylineJobService.updateJob(WaylineJobDTO.builder()
.jobId(jobId)
.jobId(jobArr[2])
.status(WaylineJobStatusEnum.FAILED.getVal())
.endTime(LocalDateTime.now())
.executeTime(LocalDateTime.now())
.completedTime(LocalDateTime.now())
.code(HttpStatus.SC_INTERNAL_SERVER_ERROR).build());
} finally {
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB, jobId);
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB_TIMED_EXECUTE, jobIdValue);
}
}
}

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

@ -187,7 +187,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @@ -187,7 +187,7 @@ public class WaylineFileServiceImpl implements IWaylineFileService {
ZipEntry nextEntry = unzipFile.getNextEntry();
while (Objects.nonNull(nextEntry)) {
boolean isWaylines = (KmzFileProperties.FILE_DIR_FIRST + File.separator + KmzFileProperties.FILE_DIR_SECOND_WAYLINES).equals(nextEntry.getName());
boolean isWaylines = (KmzFileProperties.FILE_DIR_FIRST + "/" + KmzFileProperties.FILE_DIR_SECOND_WAYLINES).equals(nextEntry.getName());
if (!isWaylines) {
nextEntry = unzipFile.getNextEntry();
continue;

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

@ -40,9 +40,7 @@ import org.springframework.util.CollectionUtils; @@ -40,9 +40,7 @@ import org.springframework.util.CollectionUtils;
import java.net.URL;
import java.sql.SQLException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;
@ -74,23 +72,29 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -74,23 +72,29 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
@Autowired
private IFileService fileService;
private Optional<WaylineJobDTO> insertWaylineJob(WaylineJobEntity jobEntity) {
int id = mapper.insert(jobEntity);
if (id <= 0) {
return Optional.empty();
}
return Optional.ofNullable(this.entity2Dto(jobEntity));
}
@Override
public Optional<WaylineJobDTO> createWaylineJob(CreateJobParam param, CustomClaim customClaim) {
public Optional<WaylineJobDTO> createWaylineJob(CreateJobParam param, String workspaceId, String username, Long beginTime, Long endTime) {
if (Objects.isNull(param)) {
return Optional.empty();
}
// Immediate tasks, allocating time on the backend.
if (Objects.isNull(param.getExecuteTime())) {
param.setExecuteTime(System.currentTimeMillis());
}
WaylineJobEntity jobEntity = WaylineJobEntity.builder()
.name(param.getName())
.dockSn(param.getDockSn())
.fileId(param.getFileId())
.username(customClaim.getUsername())
.workspaceId(customClaim.getWorkspaceId())
.username(username)
.workspaceId(workspaceId)
.jobId(UUID.randomUUID().toString())
.executeTime(param.getExecuteTime())
.beginTime(beginTime)
.endTime(endTime)
.status(WaylineJobStatusEnum.PENDING.getVal())
.taskType(param.getTaskType())
.waylineType(param.getWaylineType())
@ -98,16 +102,35 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -98,16 +102,35 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.rthAltitude(param.getRthAltitude())
.mediaCount(0)
.build();
int id = mapper.insert(jobEntity);
if (id <= 0) {
return insertWaylineJob(jobEntity);
}
@Override
public Optional<WaylineJobDTO> createWaylineJobByParent(String workspaceId, String parentId) {
Optional<WaylineJobDTO> parentJobOpt = this.getJobByJobId(workspaceId, parentId);
if (parentJobOpt.isEmpty()) {
return Optional.empty();
}
return Optional.ofNullable(this.entity2Dto(jobEntity));
WaylineJobEntity jobEntity = this.dto2Entity(parentJobOpt.get());
jobEntity.setJobId(UUID.randomUUID().toString());
jobEntity.setErrorCode(null);
jobEntity.setCompletedTime(null);
jobEntity.setExecuteTime(null);
jobEntity.setStatus(WaylineJobStatusEnum.PENDING.getVal());
jobEntity.setParentId(parentId);
return this.insertWaylineJob(jobEntity);
}
@Override
public ResponseResult publishFlightTask(CreateJobParam param, CustomClaim customClaim) throws SQLException {
Optional<WaylineJobDTO> waylineJobOpt = this.createWaylineJob(param, customClaim);
if (WaylineTaskTypeEnum.IMMEDIATE.getVal() == param.getTaskType()) {
param.setExecuteTime(System.currentTimeMillis());
}
Optional<WaylineJobDTO> waylineJobOpt = this.createWaylineJob(param,
customClaim.getWorkspaceId(), customClaim.getUsername(),
param.getExecuteTime(), param.getExecuteTime());
if (waylineJobOpt.isEmpty()) {
throw new SQLException("Failed to create wayline job.");
}
@ -127,14 +150,14 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -127,14 +150,14 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
// get file url
URL url = waylineFileService.getObjectUrl(waylineJob.getWorkspaceId(), waylineFile.get().getWaylineId());
FlightTaskCreateDTO flightTask = FlightTaskCreateDTO.builder()
WaylineTaskCreateDTO flightTask = WaylineTaskCreateDTO.builder()
.flightId(waylineJob.getJobId())
.executeTime(waylineJob.getExecuteTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli())
.executeTime(waylineJob.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli())
.taskType(waylineJob.getTaskType())
.waylineType(waylineJob.getWaylineType())
.rthAltitude(waylineJob.getRthAltitude())
.outOfControlAction(waylineJob.getOutOfControlAction())
.file(FlightTaskFileDTO.builder()
.file(WaylineTaskFileDTO.builder()
.url(url.toString())
.fingerprint(waylineFile.get().getSign())
.build())
@ -156,22 +179,24 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -156,22 +179,24 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
this.updateJob(WaylineJobDTO.builder()
.workspaceId(waylineJob.getWorkspaceId())
.jobId(waylineJob.getJobId())
.executeTime(LocalDateTime.now())
.status(WaylineJobStatusEnum.FAILED.getVal())
.endTime(LocalDateTime.now())
.completedTime(LocalDateTime.now())
.code(serviceReply.getResult()).build());
return ResponseResult.error("Prepare task ====> Error code: " + serviceReply.getResult());
}
// Issue an immediate task execution command.
if (WaylineTaskTypeEnum.IMMEDIATE.getVal() == waylineJob.getTaskType()) {
if (!executeFlightTask(waylineJob.getJobId())) {
if (!executeFlightTask(waylineJob.getWorkspaceId(), waylineJob.getJobId())) {
return ResponseResult.error("Failed to execute job.");
}
}
if (WaylineTaskTypeEnum.TIMED.getVal() == waylineJob.getTaskType()) {
boolean isAdd = RedisOpsUtils.zAdd(RedisConst.WAYLINE_JOB, waylineJob.getJobId(),
waylineJob.getExecuteTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
boolean isAdd = RedisOpsUtils.zAdd(RedisConst.WAYLINE_JOB_TIMED_EXECUTE,
waylineJob.getWorkspaceId() + RedisConst.DELIMITER + waylineJob.getDockSn() + RedisConst.DELIMITER + waylineJob.getJobId(),
waylineJob.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
if (!isAdd) {
return ResponseResult.error("Failed to create scheduled job.");
}
@ -181,9 +206,9 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -181,9 +206,9 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
}
@Override
public Boolean executeFlightTask(String jobId) {
public Boolean executeFlightTask(String workspaceId, String jobId) {
// get job
Optional<WaylineJobDTO> waylineJob = this.getJobByJobId(jobId);
Optional<WaylineJobDTO> waylineJob = this.getJobByJobId(workspaceId, jobId);
if (waylineJob.isEmpty()) {
throw new IllegalArgumentException("Job doesn't exist.");
}
@ -194,7 +219,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -194,7 +219,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
}
WaylineJobDTO job = waylineJob.get();
FlightTaskCreateDTO flightTask = FlightTaskCreateDTO.builder().flightId(jobId).build();
WaylineTaskCreateDTO flightTask = WaylineTaskCreateDTO.builder().flightId(jobId).build();
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT +
job.getDockSn() + TopicConst.SERVICES_SUF;
@ -211,53 +236,45 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -211,53 +236,45 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
log.info("Execute job ====> Error code: {}", serviceReply.getResult());
this.updateJob(WaylineJobDTO.builder()
.jobId(jobId)
.executeTime(LocalDateTime.now())
.status(WaylineJobStatusEnum.FAILED.getVal())
.endTime(LocalDateTime.now())
.completedTime(LocalDateTime.now())
.code(serviceReply.getResult()).build());
return false;
}
this.updateJob(WaylineJobDTO.builder()
.jobId(jobId)
.executeTime(LocalDateTime.now())
.status(WaylineJobStatusEnum.IN_PROGRESS.getVal())
.build());
RedisOpsUtils.setWithExpire(jobId,
EventsReceiver.<FlightTaskProgressReceiver>builder().bid(jobId).sn(job.getDockSn()).build(),
RedisOpsUtils.setWithExpire(RedisConst.WAYLINE_JOB_RUNNING_PREFIX + job.getDockSn(),
EventsReceiver.<WaylineTaskProgressReceiver>builder().bid(jobId).sn(job.getDockSn()).build(),
RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND);
return true;
}
@Override
public void cancelFlightTask(String workspaceId, Collection<String> jobIds) {
List<WaylineJobEntity> waylineJobs = mapper.selectList(
new LambdaQueryWrapper<WaylineJobEntity>()
.or(wrapper -> jobIds.forEach(id -> wrapper.eq(WaylineJobEntity::getJobId, id))));
List<WaylineJobDTO> waylineJobs = getJobsByConditions(workspaceId, jobIds, WaylineJobStatusEnum.PENDING);
// Check if the job have ended.
List<String> endJobs = waylineJobs.stream()
.filter(job -> WaylineJobStatusEnum.find(job.getStatus()).getEnd())
.map(WaylineJobEntity::getName)
.collect(Collectors.toList());
if (!CollectionUtils.isEmpty(endJobs)) {
throw new IllegalArgumentException("There are jobs that have ended." + Arrays.toString(endJobs.toArray()));
}
Set<String> ids = waylineJobs.stream().map(WaylineJobEntity::getJobId).collect(Collectors.toSet());
for (String id : jobIds) {
if (!ids.contains(id)) {
throw new IllegalArgumentException("Job id " + id + " doesn't exist.");
}
Set<String> waylineJobIds = waylineJobs.stream().map(WaylineJobDTO::getJobId).collect(Collectors.toSet());
// Check if the task status is correct.
boolean isErr = !jobIds.removeAll(waylineJobIds) || !jobIds.isEmpty() ;
if (isErr) {
throw new IllegalArgumentException("These tasks have an incorrect status and cannot be canceled. "
+ Arrays.toString(jobIds.toArray()));
}
// Group job id by dock sn.
Map<String, List<String>> dockJobs = waylineJobs.stream()
.collect(Collectors.groupingBy(WaylineJobEntity::getDockSn,
Collectors.mapping(WaylineJobEntity::getJobId, Collectors.toList())));
.collect(Collectors.groupingBy(WaylineJobDTO::getDockSn,
Collectors.mapping(WaylineJobDTO::getJobId, Collectors.toList())));
dockJobs.forEach((dockSn, idList) -> this.publishCancelTask(workspaceId, dockSn, idList));
}
private void publishCancelTask(String workspaceId, String dockSn, List<String> jobIds) {
public void publishCancelTask(String workspaceId, String dockSn, List<String> jobIds) {
boolean isOnline = deviceService.checkDeviceOnline(dockSn);
if (!isOnline) {
throw new RuntimeException("Dock is offline.");
@ -283,17 +300,30 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -283,17 +300,30 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.workspaceId(workspaceId)
.jobId(jobId)
.status(WaylineJobStatusEnum.CANCEL.getVal())
.endTime(LocalDateTime.now())
.completedTime(LocalDateTime.now())
.build());
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB, jobId);
RedisOpsUtils.zRemove(RedisConst.WAYLINE_JOB_TIMED_EXECUTE, workspaceId + RedisConst.DELIMITER + dockSn + RedisConst.DELIMITER + jobId);
}
}
public List<WaylineJobDTO> getJobsByConditions(String workspaceId, Collection<String> jobIds, WaylineJobStatusEnum status) {
return mapper.selectList(
new LambdaQueryWrapper<WaylineJobEntity>()
.eq(WaylineJobEntity::getWorkspaceId, workspaceId)
.eq(Objects.nonNull(status), WaylineJobEntity::getStatus, status.getVal())
.and(!CollectionUtils.isEmpty(jobIds),
wrapper -> jobIds.forEach(id -> wrapper.eq(WaylineJobEntity::getJobId, id).or())))
.stream()
.map(this::entity2Dto)
.collect(Collectors.toList());
}
@Override
public Optional<WaylineJobDTO> getJobByJobId(String jobId) {
public Optional<WaylineJobDTO> getJobByJobId(String workspaceId, String jobId) {
WaylineJobEntity jobEntity = mapper.selectOne(
new LambdaQueryWrapper<WaylineJobEntity>()
.eq(WaylineJobEntity::getWorkspaceId, workspaceId)
.eq(WaylineJobEntity::getJobId, jobId));
return Optional.ofNullable(entity2Dto(jobEntity));
}
@ -336,7 +366,8 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -336,7 +366,8 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString() + TopicConst._REPLY_SUF;
Optional<WaylineJobDTO> waylineJobOpt = this.getJobByJobId(jobId);
DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + receiver.getGateway());
Optional<WaylineJobDTO> waylineJobOpt = this.getJobByJobId(device.getWorkspaceId(), jobId);
if (waylineJobOpt.isEmpty()) {
builder.data(RequestsReply.error(CommonErrorEnum.ILLEGAL_ARGUMENT));
messageSender.publish(topic, builder.build());
@ -357,8 +388,8 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -357,8 +388,8 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
URL url = null;
try {
url = waylineFileService.getObjectUrl(waylineJob.getWorkspaceId(), waylineFile.get().getWaylineId());
builder.data(RequestsReply.success(FlightTaskCreateDTO.builder()
.file(FlightTaskFileDTO.builder()
builder.data(RequestsReply.success(WaylineTaskCreateDTO.builder()
.file(WaylineTaskFileDTO.builder()
.url(url.toString())
.fingerprint(waylineFile.get().getSign())
.build())
@ -377,14 +408,15 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -377,14 +408,15 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
@Override
public void uploadMediaHighestPriority(String workspaceId, String jobId) {
Optional<WaylineJobDTO> jobOpt = getJobByJobId(jobId);
Optional<WaylineJobDTO> jobOpt = getJobByJobId(workspaceId, 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())) {
if (RedisOpsUtils.checkExist(key) &&
jobId.equals(((MediaFileCountDTO) RedisOpsUtils.get(key)).getJobId())) {
return;
}
@ -399,7 +431,6 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -399,7 +431,6 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
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) {
@ -407,16 +438,32 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -407,16 +438,32 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
if (dto == null) {
return builder.build();
}
if (Objects.nonNull(dto.getBeginTime())) {
builder.beginTime(dto.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
if (Objects.nonNull(dto.getEndTime())) {
builder.endTime(dto.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
if (Objects.nonNull(dto.getExecuteTime())) {
builder.executeTime(dto.getExecuteTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
if (Objects.nonNull(dto.getCompletedTime())) {
builder.completedTime(dto.getCompletedTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
return builder.status(dto.getStatus())
.mediaCount(dto.getMediaCount())
.name(dto.getJobName())
.errorCode(dto.getCode())
.jobId(dto.getJobId())
.fileId(dto.getFileId())
.dockSn(dto.getDockSn())
.workspaceId(dto.getWorkspaceId())
.taskType(dto.getTaskType())
.waylineType(dto.getWaylineType())
.username(dto.getUsername())
.rthAltitude(dto.getRthAltitude())
.outOfControlAction(dto.getOutOfControlAction())
.parentId(dto.getParentId())
.build();
}
@ -436,9 +483,17 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -436,9 +483,17 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.orElse(DeviceDTO.builder().build()).getNickname())
.username(entity.getUsername())
.workspaceId(entity.getWorkspaceId())
.status(entity.getStatus())
.status(WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() &&
RedisOpsUtils.checkExist(RedisConst.WAYLINE_JOB_PAUSED_PREFIX + entity.getJobId()) ?
WaylineJobStatusEnum.PAUSED.getVal() : entity.getStatus())
.code(entity.getErrorCode())
.executeTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getExecuteTime()), ZoneId.systemDefault()))
.beginTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBeginTime()), ZoneId.systemDefault()))
.endTime(Objects.nonNull(entity.getEndTime()) ?
LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()) : null)
.executeTime(Objects.nonNull(entity.getExecuteTime()) ?
LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getExecuteTime()), ZoneId.systemDefault()) : null)
.completedTime(WaylineJobStatusEnum.find(entity.getStatus()).getEnd() ?
LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getUpdateTime()), ZoneId.systemDefault()) : null)
.taskType(entity.getTaskType())
.waylineType(entity.getWaylineType())
.rthAltitude(entity.getRthAltitude())
@ -449,7 +504,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -449,7 +504,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
builder.endTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()));
}
if (WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && RedisOpsUtils.getExpire(entity.getJobId()) > 0) {
EventsReceiver<FlightTaskProgressReceiver> taskProgress = (EventsReceiver<FlightTaskProgressReceiver>) RedisOpsUtils.get(entity.getJobId());
EventsReceiver<WaylineTaskProgressReceiver> taskProgress = (EventsReceiver<WaylineTaskProgressReceiver>) RedisOpsUtils.get(RedisConst.WAYLINE_JOB_RUNNING_PREFIX + entity.getDockSn());
if (Objects.nonNull(taskProgress.getOutput()) && Objects.nonNull(taskProgress.getOutput().getProgress())) {
builder.progress(taskProgress.getOutput().getProgress().getPercent());
}
@ -465,7 +520,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @@ -465,7 +520,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
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)));
.uploading(RedisOpsUtils.checkExist(key) && entity.getJobId().equals(((MediaFileCountDTO)RedisOpsUtils.get(key)).getJobId()));
return builder.build();
}

32
src/main/resources/application.yml

@ -39,14 +39,19 @@ jwt: @@ -39,14 +39,19 @@ jwt:
age: 86400
mqtt:
protocol: tcp
host: Please enter your ip. # 192.168.1.1
port: 1883
username: JavaServer
password: 123456
client-id: 123456
# Topics that need to be subscribed when initially connecting to mqtt, multiple topics are divided by ",".
inbound-topic: sys/product/+/status,thing/product/+/requests
# @see com.dji.sample.component.mqtt.model.MqttUseEnum
# BASIC parameters are required.
BASIC:
protocol: MQTT # @see com.dji.sample.component.mqtt.model.MqttProtocolEnum
host: Please enter your ip.
port: 1883
username: JavaServer
password: 123456
client-id: 123456
# If the protocol is ws/wss, this value is required.
path:
# Topics that need to be subscribed when initially connecting to mqtt, multiple topics are divided by ",".
inbound-topic: sys/product/+/status,thing/product/+/requests
url:
manage:
@ -68,7 +73,7 @@ url: @@ -68,7 +73,7 @@ url:
prefix: /control
version: /api/v1
# Tutorial: https://help.aliyun.com/document_detail/100624.htm?spm=a2c4g.11186623.0.0.74075e34eIhK7T#concept-xzh-nzk-2gb
# Tutorial: https://www.alibabacloud.com/help/en/object-storage-service/latest/use-a-temporary-credential-provided-by-sts-to-access-oss
oss:
enable: true
provider: ali # @see com.dji.sample.component.OssConfiguration.model.enums.OssTypeEnum
@ -114,4 +119,11 @@ logging: @@ -114,4 +119,11 @@ logging:
ntp:
server:
host: Google.mzr.me
host: Google.mzr.me
# To create a license for an application: https://developer.dji.com/user/apps/#all
cloud-api:
app:
id: Please enter the app id.
key: Please enter the app key.
license: Please enter the app license.
Loading…
Cancel
Save