Browse Source
1. Wayline management: added `pause wayline task` and `recover wayline task`. 2. Added command flight function. 3. Fixed some issues.v1.4.0
sean.zhou
2 years ago
134 changed files with 4601 additions and 821 deletions
@ -0,0 +1,55 @@ |
|||||||
|
package com.dji.sample.control.controller; |
||||||
|
|
||||||
|
import com.dji.sample.common.model.CustomClaim; |
||||||
|
import com.dji.sample.common.model.ResponseResult; |
||||||
|
import com.dji.sample.control.model.dto.JwtAclDTO; |
||||||
|
import com.dji.sample.control.model.dto.MqttBrokerDTO; |
||||||
|
import com.dji.sample.control.model.param.DrcConnectParam; |
||||||
|
import com.dji.sample.control.model.param.DrcModeParam; |
||||||
|
import com.dji.sample.control.service.IDrcService; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.*; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.validation.Valid; |
||||||
|
|
||||||
|
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
@RestController |
||||||
|
@Slf4j |
||||||
|
@RequestMapping("${url.control.prefix}${url.control.version}") |
||||||
|
public class DrcController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IDrcService drcService; |
||||||
|
|
||||||
|
@PostMapping("/workspaces/{workspace_id}/drc/connect") |
||||||
|
public ResponseResult drcConnect(@PathVariable("workspace_id") String workspaceId, HttpServletRequest request, @Valid @RequestBody DrcConnectParam param) { |
||||||
|
CustomClaim claims = (CustomClaim) request.getAttribute(TOKEN_CLAIM); |
||||||
|
|
||||||
|
MqttBrokerDTO brokerDTO = drcService.userDrcAuth(workspaceId, claims.getId(), claims.getUsername(), param); |
||||||
|
return ResponseResult.success(brokerDTO); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("/workspaces/{workspace_id}/drc/enter") |
||||||
|
public ResponseResult drcEnter(@PathVariable("workspace_id") String workspaceId, @Valid @RequestBody DrcModeParam param) { |
||||||
|
JwtAclDTO acl = drcService.deviceDrcEnter(workspaceId, param); |
||||||
|
|
||||||
|
return ResponseResult.success(acl); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("/workspaces/{workspace_id}/drc/exit") |
||||||
|
public ResponseResult drcExit(@PathVariable("workspace_id") String workspaceId, @Valid @RequestBody DrcModeParam param) { |
||||||
|
drcService.deviceDrcExit(workspaceId, param); |
||||||
|
|
||||||
|
return ResponseResult.success(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/12 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class DrcModeDTO { |
||||||
|
|
||||||
|
private MqttBrokerDTO mqttBroker; |
||||||
|
|
||||||
|
/** |
||||||
|
* range: 1 - 30 |
||||||
|
*/ |
||||||
|
@Builder.Default |
||||||
|
private Integer osdFrequency = 10; |
||||||
|
|
||||||
|
/** |
||||||
|
* range: 1 - 30 |
||||||
|
*/ |
||||||
|
@Builder.Default |
||||||
|
private Integer hsiFrequency = 1; |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.DrcModeReasonEnum; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/14 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class DrcModeReasonReceiver { |
||||||
|
|
||||||
|
private DrcModeReasonEnum reason; |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.DrcStatusErrorEnum; |
||||||
|
import com.dji.sample.manage.model.enums.DockDrcStateEnum; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/17 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class DrcStatusNotifyReceiver { |
||||||
|
|
||||||
|
private DrcStatusErrorEnum result; |
||||||
|
|
||||||
|
private DockDrcStateEnum drcState; |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.FlyToStatusEnum; |
||||||
|
import com.dji.sample.wayline.model.enums.WaylineErrorCodeEnum; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/14 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class FlyToProgressReceiver { |
||||||
|
|
||||||
|
private WaylineErrorCodeEnum result; |
||||||
|
|
||||||
|
private FlyToStatusEnum status; |
||||||
|
|
||||||
|
private String flyToId; |
||||||
|
|
||||||
|
private Integer wayPointIndex; |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/12 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class JwtAclDTO { |
||||||
|
|
||||||
|
private List<String> sub; |
||||||
|
|
||||||
|
private List<String> pub; |
||||||
|
|
||||||
|
private List<String> all; |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class MqttBrokerDTO { |
||||||
|
|
||||||
|
private String address; |
||||||
|
|
||||||
|
private String username; |
||||||
|
|
||||||
|
private String password; |
||||||
|
|
||||||
|
private String clientId; |
||||||
|
|
||||||
|
private Long expireTime; |
||||||
|
|
||||||
|
@Builder.Default |
||||||
|
private Boolean enableTls = false; |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/2/14 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class PointDTO { |
||||||
|
|
||||||
|
@Range(min = -90, max = 90) |
||||||
|
@NotNull |
||||||
|
private Double latitude; |
||||||
|
|
||||||
|
@NotNull |
||||||
|
@Range(min = -180, max = 180) |
||||||
|
private Double longitude; |
||||||
|
|
||||||
|
/** |
||||||
|
* WGS84 |
||||||
|
* The M30 series are ellipsoidal heights. |
||||||
|
*/ |
||||||
|
@NotNull |
||||||
|
@Range(min = 2, max = 1500) |
||||||
|
private Double height; |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.common.util.SpringBeanUtils; |
||||||
|
import com.dji.sample.control.service.impl.RemoteDebugHandler; |
||||||
|
import com.dji.sample.manage.model.enums.DockModeCodeEnum; |
||||||
|
import com.dji.sample.manage.service.IDeviceService; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.EqualsAndHashCode; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/14 |
||||||
|
*/ |
||||||
|
@EqualsAndHashCode(callSuper = true) |
||||||
|
@Data |
||||||
|
public class RemoteDebugOpenState extends RemoteDebugHandler { |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String sn) { |
||||||
|
IDeviceService deviceService = SpringBeanUtils.getBean(IDeviceService.class); |
||||||
|
DockModeCodeEnum dockMode = deviceService.getDockMode(sn); |
||||||
|
return DockModeCodeEnum.IDLE == dockMode; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/1 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class ResultNotifyDTO { |
||||||
|
|
||||||
|
private Integer result; |
||||||
|
|
||||||
|
private String message; |
||||||
|
|
||||||
|
private String sn; |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.common.util.SpringBeanUtils; |
||||||
|
import com.dji.sample.control.service.impl.RemoteDebugHandler; |
||||||
|
import com.dji.sample.manage.model.dto.DeviceDTO; |
||||||
|
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver; |
||||||
|
import com.dji.sample.manage.service.IDeviceRedisService; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/19 |
||||||
|
*/ |
||||||
|
|
||||||
|
public class ReturnHomeState extends RemoteDebugHandler { |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String sn) { |
||||||
|
IDeviceRedisService deviceRedisService = SpringBeanUtils.getBean(IDeviceRedisService.class); |
||||||
|
return deviceRedisService.getDeviceOnline(sn) |
||||||
|
.map(DeviceDTO::getChildDeviceSn) |
||||||
|
.flatMap(deviceSn -> deviceRedisService.getDeviceOsd(deviceSn, OsdSubDeviceReceiver.class)) |
||||||
|
.map(OsdSubDeviceReceiver::getElevation) |
||||||
|
.map(elevation -> elevation > 0) |
||||||
|
.orElse(false); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.dji.sample.control.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.TakeoffStatusEnum; |
||||||
|
import com.dji.sample.wayline.model.enums.WaylineErrorCodeEnum; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/14 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class TakeoffProgressReceiver { |
||||||
|
|
||||||
|
private WaylineErrorCodeEnum result; |
||||||
|
|
||||||
|
private TakeoffStatusEnum status; |
||||||
|
|
||||||
|
private String flightId; |
||||||
|
|
||||||
|
private String trackId; |
||||||
|
|
||||||
|
private Integer wayPointIndex; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/3 |
||||||
|
*/ |
||||||
|
public enum CameraModeEnum { |
||||||
|
|
||||||
|
PHOTO, VIDEO; |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return ordinal(); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static CameraModeEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(modeEnum -> modeEnum.ordinal() == val).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public enum CameraStateEnum { |
||||||
|
|
||||||
|
IDLE, WORKING; |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return ordinal(); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static CameraStateEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(stateEnum -> stateEnum.ordinal() == val).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
import lombok.Getter; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/3 |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
public enum CameraTypeEnum { |
||||||
|
|
||||||
|
ZOOM("zoom"), |
||||||
|
|
||||||
|
WIDE("wide"), |
||||||
|
|
||||||
|
IR("ir"); |
||||||
|
|
||||||
|
String type; |
||||||
|
|
||||||
|
CameraTypeEnum(String type) { |
||||||
|
this.type = type; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public String getType() { |
||||||
|
return type; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static CameraTypeEnum find(String cameraType) { |
||||||
|
return Arrays.stream(CameraTypeEnum.values()).filter(typeEnum -> typeEnum.type.equals(cameraType)).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
public enum DrcMethodEnum { |
||||||
|
|
||||||
|
DRC_MODE_ENTER("drc_mode_enter"), |
||||||
|
|
||||||
|
DRC_MODE_EXIT("drc_mode_exit"); |
||||||
|
|
||||||
|
String method; |
||||||
|
|
||||||
|
DrcMethodEnum(String method) { |
||||||
|
this.method = method; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/14 |
||||||
|
*/ |
||||||
|
public enum DrcModeReasonEnum { |
||||||
|
|
||||||
|
UNKNOWN(-1, "unknown"), |
||||||
|
|
||||||
|
RC_LOST(0, "The remote controller is lost."), |
||||||
|
|
||||||
|
BATTERY_LOW_GO_HOME(1, "Due to low battery, the drone automatically returned home."), |
||||||
|
|
||||||
|
BATTERY_SUPER_LOW_LANDING(2, "Due to the serious low battery, the drone landed automatically."), |
||||||
|
|
||||||
|
NEAR_BOUNDARY(3, "The drone is near a not-fly zone."), |
||||||
|
|
||||||
|
RC_AUTHORITY(4, "The remote controller grabs control authority."); |
||||||
|
|
||||||
|
int val; |
||||||
|
|
||||||
|
String message; |
||||||
|
|
||||||
|
DrcModeReasonEnum(int val, String message) { |
||||||
|
this.val = val; |
||||||
|
this.message = message; |
||||||
|
} |
||||||
|
|
||||||
|
public int getVal() { |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage() { |
||||||
|
return message; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) |
||||||
|
public static DrcModeReasonEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(reasonEnum -> reasonEnum.val == val).findAny().orElse(UNKNOWN); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.dji.sample.common.error.IErrorInfo; |
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/17 |
||||||
|
*/ |
||||||
|
public enum DrcStatusErrorEnum implements IErrorInfo { |
||||||
|
|
||||||
|
SUCCESS(0, "success"), |
||||||
|
|
||||||
|
MQTT_ERR(514300, "The mqtt connection error."), |
||||||
|
|
||||||
|
HEARTBEAT_TIMEOUT(514301, "The heartbeat times out and the dock disconnects."), |
||||||
|
|
||||||
|
MQTT_CERTIFICATE_ERR(514302, "The mqtt certificate is abnormal and the connection fails."), |
||||||
|
|
||||||
|
MQTT_LOST(514303, "The dock network is abnormal and the mqtt connection is lost."), |
||||||
|
|
||||||
|
MQTT_REFUSE(514304, "The dock connection to mqtt server was refused."), |
||||||
|
|
||||||
|
UNKNOWN(-1, "Unknown"); |
||||||
|
|
||||||
|
String msg; |
||||||
|
|
||||||
|
int code; |
||||||
|
|
||||||
|
DrcStatusErrorEnum(int code, String msg) { |
||||||
|
this.code = code; |
||||||
|
this.msg = msg; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getErrorMsg() { |
||||||
|
return msg; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Integer getErrorCode() { |
||||||
|
return code; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) |
||||||
|
public static DrcStatusErrorEnum find(int code) { |
||||||
|
return Arrays.stream(values()).filter(error -> error.code == code).findAny().orElse(UNKNOWN); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/1 |
||||||
|
*/ |
||||||
|
public enum DroneAuthorityEnum { |
||||||
|
|
||||||
|
FLIGHT(1), PAYLOAD(2); |
||||||
|
|
||||||
|
int val; |
||||||
|
|
||||||
|
DroneAuthorityEnum(int val) { |
||||||
|
this.val = val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/2/21 |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
public enum DroneControlMethodEnum { |
||||||
|
|
||||||
|
FLIGHT_AUTHORITY_GRAB("flight_authority_grab"), |
||||||
|
|
||||||
|
PAYLOAD_AUTHORITY_GRAB("payload_authority_grab"), |
||||||
|
|
||||||
|
FLY_TO_POINT("fly_to_point"), |
||||||
|
|
||||||
|
FLY_TO_POINT_STOP("fly_to_point_stop"), |
||||||
|
|
||||||
|
TAKE_OFF_TO_POINT("takeoff_to_point"); |
||||||
|
|
||||||
|
String method; |
||||||
|
|
||||||
|
DroneControlMethodEnum(String method) { |
||||||
|
this.method = method; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/14 |
||||||
|
*/ |
||||||
|
public enum FlyToStatusEnum { |
||||||
|
|
||||||
|
WAYLINE_PROGRESS("wayline_progress", "The FlyTo job is in progress."), |
||||||
|
|
||||||
|
WAYLINE_FAILED("wayline_failed", "The Fly To task execution failed."), |
||||||
|
|
||||||
|
WAYLINE_OK("wayline_ok", "The FlyTo job executed successfully."), |
||||||
|
|
||||||
|
WAYLINE_CANCEL("wayline_cancel", "The FlyTo job is closed."); |
||||||
|
|
||||||
|
String status; |
||||||
|
|
||||||
|
String message; |
||||||
|
|
||||||
|
FlyToStatusEnum(String status, String message) { |
||||||
|
this.status = status; |
||||||
|
this.message = message; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage() { |
||||||
|
return message; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) |
||||||
|
public static FlyToStatusEnum find(String status) { |
||||||
|
return Arrays.stream(values()).filter(statusEnum -> statusEnum.status.equals(status)).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/13 |
||||||
|
*/ |
||||||
|
public enum GimbalResetModeEnum { |
||||||
|
|
||||||
|
RECENTER, DOWN, RECENTER_PAN, PITCH_DOWN; |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return ordinal(); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static GimbalResetModeEnum find(int value) { |
||||||
|
return Arrays.stream(values()).filter(resetModeEnum -> resetModeEnum.ordinal() == value).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/13 |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
public enum MqttAclAccessEnum { |
||||||
|
|
||||||
|
SUB(1), |
||||||
|
|
||||||
|
PUB(2), |
||||||
|
|
||||||
|
ALL(3); |
||||||
|
|
||||||
|
int value; |
||||||
|
|
||||||
|
MqttAclAccessEnum(int value) { |
||||||
|
this.value = value; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.dji.sample.control.service.impl.*; |
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/2 |
||||||
|
*/ |
||||||
|
public enum PayloadCommandsEnum { |
||||||
|
|
||||||
|
CAMERA_MODE_SWitCH("camera_mode_switch", CameraModeSwitchImpl.class), |
||||||
|
|
||||||
|
CAMERA_PHOTO_TAKE("camera_photo_take", CameraPhotoTakeImpl.class), |
||||||
|
|
||||||
|
CAMERA_RECORDING_START("camera_recording_start", CameraRecordingStartImpl.class), |
||||||
|
|
||||||
|
CAMERA_RECORDING_STOP("camera_recording_stop", CameraRecordingStopImpl.class), |
||||||
|
|
||||||
|
CAMERA_AIM("camera_aim", CameraAimImpl.class), |
||||||
|
|
||||||
|
CAMERA_FOCAL_LENGTH_SET("camera_focal_length_set", CameraFocalLengthSetImpl.class), |
||||||
|
|
||||||
|
GIMBAL_RESET("gimbal_reset", GimbalResetImpl.class); |
||||||
|
|
||||||
|
String cmd; |
||||||
|
|
||||||
|
Class<? extends PayloadCommandsHandler> clazz; |
||||||
|
|
||||||
|
PayloadCommandsEnum(String cmd, Class<? extends PayloadCommandsHandler> clazz) { |
||||||
|
this.cmd = cmd; |
||||||
|
this.clazz = clazz; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public String getCmd() { |
||||||
|
return cmd; |
||||||
|
} |
||||||
|
|
||||||
|
public Class<? extends PayloadCommandsHandler> getClazz() { |
||||||
|
return clazz; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) |
||||||
|
public static PayloadCommandsEnum find(String cmd) { |
||||||
|
return Arrays.stream(values()).filter(cmdEnum -> cmdEnum.cmd.equals(cmd)).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package com.dji.sample.control.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/17 |
||||||
|
*/ |
||||||
|
public enum TakeoffStatusEnum { |
||||||
|
|
||||||
|
TASK_READY("task_ready", "The drone is preparing to take off."), |
||||||
|
|
||||||
|
WAYLINE_PROGRESS("wayline_progress", "The drone is taking off."), |
||||||
|
|
||||||
|
WAYLINE_FAILED("wayline_failed", "The drone failed to take off."), |
||||||
|
|
||||||
|
WAYLINE_OK("wayline_ok", "The drone took off successfully."), |
||||||
|
|
||||||
|
WAYLINE_CANCEL("wayline_cancel", "The drone takeoff job has been cancelled."), |
||||||
|
|
||||||
|
TASK_FINISH("task_finish", "The drone takeoff job is completed."); |
||||||
|
|
||||||
|
String status; |
||||||
|
|
||||||
|
String message; |
||||||
|
|
||||||
|
TakeoffStatusEnum(String status, String message) { |
||||||
|
this.status = status; |
||||||
|
this.message = message; |
||||||
|
} |
||||||
|
|
||||||
|
public String getStatus() { |
||||||
|
return status; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage() { |
||||||
|
return message; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) |
||||||
|
public static TakeoffStatusEnum find(String status) { |
||||||
|
return Arrays.stream(values()).filter(statusEnum -> statusEnum.status.equals(status)).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/2/2 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class DeviceDrcInfoParam { |
||||||
|
|
||||||
|
@Range(min = 1, max = 30) |
||||||
|
private Integer osdFrequency = 10; |
||||||
|
|
||||||
|
@Range(min = 1, max = 30) |
||||||
|
private Integer hsiFrequency = 1; |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import com.dji.sample.component.redis.RedisConst; |
||||||
|
import lombok.Data; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class DrcConnectParam { |
||||||
|
|
||||||
|
private String clientId; |
||||||
|
|
||||||
|
@Range(min = 1800, max = 86400) |
||||||
|
private long expireSec = RedisConst.DRC_MODE_ALIVE_SECOND; |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import com.dji.sample.component.redis.RedisConst; |
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
import javax.validation.Valid; |
||||||
|
import javax.validation.constraints.NotBlank; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@NoArgsConstructor |
||||||
|
@AllArgsConstructor |
||||||
|
public class DrcModeParam { |
||||||
|
|
||||||
|
@NotBlank |
||||||
|
private String clientId; |
||||||
|
|
||||||
|
@NotBlank |
||||||
|
private String dockSn; |
||||||
|
|
||||||
|
@Range(min = 1800, max = 86400) |
||||||
|
private long expireSec = RedisConst.DRC_MODE_ALIVE_SECOND; |
||||||
|
|
||||||
|
@Valid |
||||||
|
private DeviceDrcInfoParam deviceInfo = new DeviceDrcInfoParam(); |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraModeEnum; |
||||||
|
import com.dji.sample.control.model.enums.CameraTypeEnum; |
||||||
|
import com.dji.sample.control.model.enums.GimbalResetModeEnum; |
||||||
|
import lombok.Data; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull; |
||||||
|
import javax.validation.constraints.Pattern; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/1 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class DronePayloadParam { |
||||||
|
|
||||||
|
@Pattern(regexp = "\\d+-\\d+-\\d+") |
||||||
|
@NotNull |
||||||
|
private String payloadIndex; |
||||||
|
|
||||||
|
private CameraTypeEnum cameraType; |
||||||
|
|
||||||
|
@Range(min = 2, max = 200) |
||||||
|
private Float zoomFactor; |
||||||
|
|
||||||
|
private CameraModeEnum cameraMode; |
||||||
|
|
||||||
|
/** |
||||||
|
* true: Lock the gimbal, the gimbal and the drone rotate together. |
||||||
|
* false: Only the gimbal rotates, but the drone does not. |
||||||
|
*/ |
||||||
|
private Boolean locked; |
||||||
|
|
||||||
|
private Double pitchSpeed; |
||||||
|
|
||||||
|
/** |
||||||
|
* Only valid when locked is false. |
||||||
|
*/ |
||||||
|
private Double yawSpeed; |
||||||
|
|
||||||
|
/** |
||||||
|
* upper left corner as center point |
||||||
|
*/ |
||||||
|
@Range(min = 0, max = 1) |
||||||
|
private Double x; |
||||||
|
|
||||||
|
@Range(min = 0, max = 1) |
||||||
|
private Double y; |
||||||
|
|
||||||
|
private GimbalResetModeEnum resetMode; |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.dto.PointDTO; |
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
import javax.validation.Valid; |
||||||
|
import javax.validation.constraints.NotNull; |
||||||
|
import javax.validation.constraints.Size; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/2/14 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class FlyToPointParam { |
||||||
|
|
||||||
|
private String flyToId; |
||||||
|
|
||||||
|
@Range(min = 1, max = 15) |
||||||
|
@NotNull |
||||||
|
private Integer maxSpeed; |
||||||
|
|
||||||
|
/** |
||||||
|
* The M30 series only support one point. |
||||||
|
*/ |
||||||
|
@Size(min = 1) |
||||||
|
@Valid |
||||||
|
@NotNull |
||||||
|
private List<PointDTO> points; |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.PayloadCommandsEnum; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import javax.validation.Valid; |
||||||
|
import javax.validation.constraints.NotNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/2 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class PayloadCommandsParam { |
||||||
|
|
||||||
|
private String sn; |
||||||
|
|
||||||
|
@NotNull |
||||||
|
@Valid |
||||||
|
private PayloadCommandsEnum cmd; |
||||||
|
|
||||||
|
@Valid |
||||||
|
@NotNull |
||||||
|
private DronePayloadParam data; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
package com.dji.sample.control.model.param; |
||||||
|
|
||||||
|
import com.dji.sample.manage.model.enums.DroneRcLostActionEnum; |
||||||
|
import com.dji.sample.manage.model.enums.WaylineRcLostActionEnum; |
||||||
|
import lombok.Data; |
||||||
|
import org.hibernate.validator.constraints.Range; |
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/1 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class TakeoffToPointParam { |
||||||
|
|
||||||
|
private String flightId; |
||||||
|
|
||||||
|
@Range(min = -180, max = 180) |
||||||
|
@NotNull |
||||||
|
private Double targetLongitude; |
||||||
|
|
||||||
|
@Range(min = -90, max = 90) |
||||||
|
@NotNull |
||||||
|
private Double targetLatitude; |
||||||
|
|
||||||
|
@Range(min = 2, max = 1500) |
||||||
|
@NotNull |
||||||
|
private Double targetHeight; |
||||||
|
|
||||||
|
@Range(min = 2, max = 1500) |
||||||
|
@NotNull |
||||||
|
private Double securityTakeoffHeight; |
||||||
|
|
||||||
|
@Range(min = 2, max = 1500) |
||||||
|
@NotNull |
||||||
|
private Double rthAltitude; |
||||||
|
|
||||||
|
@NotNull |
||||||
|
private DroneRcLostActionEnum rcLostAction; |
||||||
|
|
||||||
|
@NotNull |
||||||
|
private WaylineRcLostActionEnum exitWaylineWhenRcLost; |
||||||
|
|
||||||
|
@Range(min = 1, max = 15) |
||||||
|
@NotNull |
||||||
|
private Double maxSpeed; |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package com.dji.sample.control.service; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.dto.JwtAclDTO; |
||||||
|
import com.dji.sample.control.model.dto.MqttBrokerDTO; |
||||||
|
import com.dji.sample.control.model.param.DrcConnectParam; |
||||||
|
import com.dji.sample.control.model.param.DrcModeParam; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
public interface IDrcService { |
||||||
|
|
||||||
|
/** |
||||||
|
* Save the drc mode of dock in redis. |
||||||
|
* @param dockSn |
||||||
|
* @param clientId |
||||||
|
*/ |
||||||
|
void setDrcModeInRedis(String dockSn, String clientId); |
||||||
|
|
||||||
|
/** |
||||||
|
* Query the client that is controlling the dock. |
||||||
|
* @param dockSn |
||||||
|
* @return clientId |
||||||
|
*/ |
||||||
|
String getDrcModeInRedis(String dockSn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Delete the drc mode of dock in redis. |
||||||
|
* @param dockSn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Boolean delDrcModeInRedis(String dockSn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Provide mqtt options for the control terminal. |
||||||
|
* @param workspaceId |
||||||
|
* @param userId |
||||||
|
* @param username |
||||||
|
* @param param |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
MqttBrokerDTO userDrcAuth(String workspaceId, String userId, String username, DrcConnectParam param); |
||||||
|
|
||||||
|
/** |
||||||
|
* Make the dock enter drc mode. And grant relevant permissions. |
||||||
|
* @param workspaceId |
||||||
|
* @param param |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
JwtAclDTO deviceDrcEnter(String workspaceId, DrcModeParam param); |
||||||
|
|
||||||
|
/** |
||||||
|
* Make the dock exit drc mode. |
||||||
|
* @param workspaceId |
||||||
|
* @param param |
||||||
|
*/ |
||||||
|
void deviceDrcExit(String workspaceId, DrcModeParam param); |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class CameraAimImpl extends PayloadCommandsHandler { |
||||||
|
|
||||||
|
public CameraAimImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean valid() { |
||||||
|
return Objects.nonNull(param.getX()) && Objects.nonNull(param.getY()) |
||||||
|
&& Objects.nonNull(param.getLocked()) && Objects.nonNull(param.getCameraType()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraStateEnum; |
||||||
|
import com.dji.sample.control.model.enums.CameraTypeEnum; |
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class CameraFocalLengthSetImpl extends PayloadCommandsHandler { |
||||||
|
|
||||||
|
public CameraFocalLengthSetImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean valid() { |
||||||
|
return Objects.nonNull(param.getCameraType()) && Objects.nonNull(param.getZoomFactor()) |
||||||
|
&& (CameraTypeEnum.ZOOM == param.getCameraType() |
||||||
|
|| CameraTypeEnum.IR == param.getCameraType()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String deviceSn) { |
||||||
|
super.canPublish(deviceSn); |
||||||
|
if (CameraStateEnum.WORKING == osdCamera.getPhotoState()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
switch (param.getCameraType()) { |
||||||
|
case IR: |
||||||
|
return param.getZoomFactor().intValue() != osdCamera.getIrZoomFactor(); |
||||||
|
case ZOOM: |
||||||
|
return param.getZoomFactor().intValue() != osdCamera.getZoomFactor(); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraStateEnum; |
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class CameraModeSwitchImpl extends PayloadCommandsHandler { |
||||||
|
|
||||||
|
public CameraModeSwitchImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean valid() { |
||||||
|
return Objects.nonNull(param.getCameraMode()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String deviceSn) { |
||||||
|
super.canPublish(deviceSn); |
||||||
|
return param.getCameraMode() != osdCamera.getCameraMode() |
||||||
|
&& CameraStateEnum.IDLE == osdCamera.getPhotoState() |
||||||
|
&& CameraStateEnum.IDLE == osdCamera.getRecordingState(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraStateEnum; |
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class CameraPhotoTakeImpl extends PayloadCommandsHandler { |
||||||
|
|
||||||
|
public CameraPhotoTakeImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String deviceSn) { |
||||||
|
super.canPublish(deviceSn); |
||||||
|
return CameraStateEnum.WORKING != osdCamera.getPhotoState() && osdCamera.getRemainPhotoNum() > 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraModeEnum; |
||||||
|
import com.dji.sample.control.model.enums.CameraStateEnum; |
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class CameraRecordingStartImpl extends PayloadCommandsHandler { |
||||||
|
|
||||||
|
public CameraRecordingStartImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String deviceSn) { |
||||||
|
super.canPublish(deviceSn); |
||||||
|
return CameraModeEnum.VIDEO == osdCamera.getCameraMode() |
||||||
|
&& CameraStateEnum.IDLE == osdCamera.getRecordingState() |
||||||
|
&& osdCamera.getRemainRecordDuration() > 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraStateEnum; |
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class CameraRecordingStopImpl extends PayloadCommandsHandler { |
||||||
|
|
||||||
|
public CameraRecordingStopImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canPublish(String deviceSn) { |
||||||
|
super.canPublish(deviceSn); |
||||||
|
return CameraStateEnum.WORKING == osdCamera.getRecordingState(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,249 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.common.model.ResponseResult; |
||||||
|
import com.dji.sample.component.mqtt.config.MqttConfiguration; |
||||||
|
import com.dji.sample.component.mqtt.model.*; |
||||||
|
import com.dji.sample.component.mqtt.service.IMessageSenderService; |
||||||
|
import com.dji.sample.component.redis.RedisConst; |
||||||
|
import com.dji.sample.component.redis.RedisOpsUtils; |
||||||
|
import com.dji.sample.component.websocket.model.BizCodeEnum; |
||||||
|
import com.dji.sample.component.websocket.service.ISendMessageService; |
||||||
|
import com.dji.sample.control.model.dto.*; |
||||||
|
import com.dji.sample.control.model.enums.DrcMethodEnum; |
||||||
|
import com.dji.sample.control.model.enums.DrcStatusErrorEnum; |
||||||
|
import com.dji.sample.control.model.enums.DroneAuthorityEnum; |
||||||
|
import com.dji.sample.control.model.enums.MqttAclAccessEnum; |
||||||
|
import com.dji.sample.control.model.param.DrcConnectParam; |
||||||
|
import com.dji.sample.control.model.param.DrcModeParam; |
||||||
|
import com.dji.sample.control.service.IControlService; |
||||||
|
import com.dji.sample.control.service.IDrcService; |
||||||
|
import com.dji.sample.manage.model.dto.DeviceDTO; |
||||||
|
import com.dji.sample.manage.model.enums.DockModeCodeEnum; |
||||||
|
import com.dji.sample.manage.model.enums.UserTypeEnum; |
||||||
|
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver; |
||||||
|
import com.dji.sample.manage.service.IDeviceRedisService; |
||||||
|
import com.dji.sample.manage.service.IDeviceService; |
||||||
|
import com.dji.sample.wayline.model.dto.WaylineTaskProgressReceiver; |
||||||
|
import com.dji.sample.wayline.model.enums.WaylineJobStatusEnum; |
||||||
|
import com.dji.sample.wayline.model.enums.WaylineTaskStatusEnum; |
||||||
|
import com.dji.sample.wayline.model.param.UpdateJobParam; |
||||||
|
import com.dji.sample.wayline.service.IWaylineJobService; |
||||||
|
import com.dji.sample.wayline.service.IWaylineRedisService; |
||||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.integration.annotation.ServiceActivator; |
||||||
|
import org.springframework.messaging.MessageHeaders; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2023/1/11 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
@Slf4j |
||||||
|
public class DrcServiceImpl implements IDrcService { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IMessageSenderService messageSenderService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private ObjectMapper objectMapper; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IWaylineJobService waylineJobService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IDeviceService deviceService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private ObjectMapper mapper; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private ISendMessageService webSocketMessageService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IControlService controlService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IDeviceRedisService deviceRedisService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IWaylineRedisService waylineRedisService; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setDrcModeInRedis(String dockSn, String clientId) { |
||||||
|
RedisOpsUtils.setWithExpire(RedisConst.DRC_PREFIX + dockSn, clientId, RedisConst.DRC_MODE_ALIVE_SECOND); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getDrcModeInRedis(String dockSn) { |
||||||
|
return (String) RedisOpsUtils.get(RedisConst.DRC_PREFIX + dockSn); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean delDrcModeInRedis(String dockSn) { |
||||||
|
return RedisOpsUtils.del(RedisConst.DRC_PREFIX + dockSn); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MqttBrokerDTO userDrcAuth(String workspaceId, String userId, String username, DrcConnectParam param) { |
||||||
|
|
||||||
|
// refresh token
|
||||||
|
String clientId = param.getClientId(); |
||||||
|
// first time
|
||||||
|
if (!StringUtils.hasText(clientId) || !RedisOpsUtils.checkExist(RedisConst.MQTT_ACL_PREFIX + clientId)) { |
||||||
|
clientId = userId + "-" + System.currentTimeMillis(); |
||||||
|
RedisOpsUtils.hashSet(RedisConst.MQTT_ACL_PREFIX + clientId, "", MqttAclAccessEnum.ALL.getValue()); |
||||||
|
} |
||||||
|
|
||||||
|
String key = RedisConst.MQTT_ACL_PREFIX + clientId; |
||||||
|
|
||||||
|
try { |
||||||
|
RedisOpsUtils.expireKey(key, RedisConst.DRC_MODE_ALIVE_SECOND); |
||||||
|
|
||||||
|
return MqttConfiguration.getMqttBrokerWithDrc( |
||||||
|
clientId, username, param.getExpireSec(), Collections.emptyMap()); |
||||||
|
} catch (RuntimeException e) { |
||||||
|
RedisOpsUtils.del(key); |
||||||
|
throw e; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void checkDrcModeCondition(String workspaceId, String dockSn) { |
||||||
|
Optional<EventsReceiver<WaylineTaskProgressReceiver>> runningOpt = waylineRedisService.getRunningWaylineJob(dockSn); |
||||||
|
if (runningOpt.isPresent() && WaylineJobStatusEnum.IN_PROGRESS == waylineJobService.getWaylineState(dockSn)) { |
||||||
|
waylineJobService.updateJobStatus(workspaceId, runningOpt.get().getBid(), |
||||||
|
UpdateJobParam.builder().status(WaylineTaskStatusEnum.PAUSE).build()); |
||||||
|
} |
||||||
|
|
||||||
|
DockModeCodeEnum dockMode = deviceService.getDockMode(dockSn); |
||||||
|
Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(dockSn); |
||||||
|
if (dockOpt.isPresent() && (DockModeCodeEnum.IDLE == dockMode || DockModeCodeEnum.WORKING == dockMode)) { |
||||||
|
Optional<OsdSubDeviceReceiver> deviceOsd = deviceRedisService.getDeviceOsd(dockOpt.get().getChildDeviceSn(), OsdSubDeviceReceiver.class); |
||||||
|
if (deviceOsd.isEmpty() || deviceOsd.get().getElevation() <= 0) { |
||||||
|
throw new RuntimeException("The drone is not in the sky and cannot enter command flight mode."); |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw new RuntimeException("The current state of the dock does not support entering command flight mode."); |
||||||
|
} |
||||||
|
|
||||||
|
ResponseResult result = controlService.seizeAuthority(dockSn, DroneAuthorityEnum.FLIGHT, null); |
||||||
|
if (ResponseResult.CODE_SUCCESS != result.getCode()) { |
||||||
|
throw new IllegalArgumentException(result.getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JwtAclDTO deviceDrcEnter(String workspaceId, DrcModeParam param) { |
||||||
|
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + param.getDockSn() + TopicConst.DRC; |
||||||
|
String pubTopic = topic + TopicConst.DOWN; |
||||||
|
String subTopic = topic + TopicConst.UP; |
||||||
|
|
||||||
|
// If the dock is in drc mode, refresh the permissions directly.
|
||||||
|
if (deviceService.checkDockDrcMode(param.getDockSn()) |
||||||
|
&& param.getClientId().equals(this.getDrcModeInRedis(param.getDockSn()))) { |
||||||
|
refreshAcl(param.getDockSn(), param.getClientId(), topic, subTopic); |
||||||
|
return JwtAclDTO.builder().sub(List.of(subTopic)).pub(List.of(pubTopic)).build(); |
||||||
|
} |
||||||
|
|
||||||
|
checkDrcModeCondition(workspaceId, param.getDockSn()); |
||||||
|
|
||||||
|
ServiceReply reply = messageSenderService.publishServicesTopic( |
||||||
|
param.getDockSn(), DrcMethodEnum.DRC_MODE_ENTER.getMethod(), |
||||||
|
DrcModeDTO.builder() |
||||||
|
.mqttBroker(MqttConfiguration.getMqttBrokerWithDrc(param.getDockSn() + "-" + System.currentTimeMillis(), param.getDockSn(), |
||||||
|
RedisConst.DRC_MODE_ALIVE_SECOND.longValue(), |
||||||
|
Map.of(MapKeyConst.ACL, objectMapper.convertValue(JwtAclDTO.builder() |
||||||
|
.pub(List.of(subTopic)) |
||||||
|
.sub(List.of(pubTopic)) |
||||||
|
.build(), new TypeReference<Map<String, ?>>() {})))) |
||||||
|
.build()); |
||||||
|
|
||||||
|
if (ResponseResult.CODE_SUCCESS != reply.getResult()) { |
||||||
|
throw new RuntimeException("SN: " + param.getDockSn() + "; Error Code:" + reply.getResult() + "; Failed to enter command flight control mode, please try again later!"); |
||||||
|
} |
||||||
|
|
||||||
|
refreshAcl(param.getDockSn(), param.getClientId(), pubTopic, subTopic); |
||||||
|
return JwtAclDTO.builder().sub(List.of(subTopic)).pub(List.of(pubTopic)).build(); |
||||||
|
} |
||||||
|
|
||||||
|
private void refreshAcl(String dockSn, String clientId, String pubTopic, String subTopic) { |
||||||
|
this.setDrcModeInRedis(dockSn, clientId); |
||||||
|
|
||||||
|
// assign acl,Match by clientId. https://www.emqx.io/docs/zh/v4.4/advanced/acl-redis.html
|
||||||
|
// scheme: HSET mqtt_acl:[clientid] [topic] [access]
|
||||||
|
String key = RedisConst.MQTT_ACL_PREFIX + clientId; |
||||||
|
RedisOpsUtils.hashSet(key, pubTopic, MqttAclAccessEnum.PUB.getValue()); |
||||||
|
RedisOpsUtils.hashSet(key, subTopic, MqttAclAccessEnum.SUB.getValue()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void deviceDrcExit(String workspaceId, DrcModeParam param) { |
||||||
|
if (!deviceService.checkDockDrcMode(param.getDockSn())) { |
||||||
|
throw new RuntimeException("The dock is not in flight control mode."); |
||||||
|
} |
||||||
|
ServiceReply reply = messageSenderService.publishServicesTopic( |
||||||
|
param.getDockSn(), DrcMethodEnum.DRC_MODE_EXIT.getMethod(), ""); |
||||||
|
if (ResponseResult.CODE_SUCCESS != reply.getResult()) { |
||||||
|
throw new RuntimeException("SN: " + param.getDockSn() + "; Error Code:" + |
||||||
|
reply.getResult() + "; Failed to exit command flight control mode, please try again later!"); |
||||||
|
} |
||||||
|
|
||||||
|
String jobId = waylineRedisService.getPausedWaylineJobId(param.getDockSn()); |
||||||
|
if (StringUtils.hasText(jobId)) { |
||||||
|
waylineJobService.updateJobStatus(workspaceId, jobId, UpdateJobParam.builder().status(WaylineTaskStatusEnum.RESUME).build()); |
||||||
|
} |
||||||
|
|
||||||
|
this.delDrcModeInRedis(param.getDockSn()); |
||||||
|
RedisOpsUtils.del(RedisConst.MQTT_ACL_PREFIX + param.getClientId()); |
||||||
|
} |
||||||
|
|
||||||
|
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_DRC_STATUS_NOTIFY, outputChannel = ChannelName.OUTBOUND_EVENTS) |
||||||
|
public CommonTopicReceiver handleDrcStatusNotify(CommonTopicReceiver receiver, MessageHeaders headers) { |
||||||
|
String dockSn = receiver.getGateway(); |
||||||
|
|
||||||
|
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(dockSn); |
||||||
|
if (deviceOpt.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
DrcStatusNotifyReceiver eventsReceiver = mapper.convertValue(receiver.getData(), new TypeReference<DrcStatusNotifyReceiver>(){}); |
||||||
|
if (DrcStatusErrorEnum.SUCCESS != eventsReceiver.getResult()) { |
||||||
|
webSocketMessageService.sendBatch( |
||||||
|
deviceOpt.get().getWorkspaceId(), UserTypeEnum.WEB.getVal(), BizCodeEnum.DRC_STATUS_NOTIFY.getCode(), |
||||||
|
ResultNotifyDTO.builder().sn(dockSn) |
||||||
|
.message(eventsReceiver.getResult().getErrorMsg()) |
||||||
|
.result(eventsReceiver.getResult().getErrorCode()).build()); |
||||||
|
} |
||||||
|
return receiver; |
||||||
|
} |
||||||
|
|
||||||
|
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_DRC_MODE_EXIT_NOTIFY, outputChannel = ChannelName.OUTBOUND_EVENTS) |
||||||
|
public CommonTopicReceiver handleDrcModeExitNotify(CommonTopicReceiver receiver, MessageHeaders headers) { |
||||||
|
String dockSn = receiver.getGateway(); |
||||||
|
|
||||||
|
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(dockSn); |
||||||
|
if (deviceOpt.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
DrcModeReasonReceiver eventsReceiver = mapper.convertValue(receiver.getData(), new TypeReference<DrcModeReasonReceiver>(){}); |
||||||
|
webSocketMessageService.sendBatch( |
||||||
|
deviceOpt.get().getWorkspaceId(), UserTypeEnum.WEB.getVal(), BizCodeEnum.JOYSTICK_INVALID_NOTIFY.getCode(), |
||||||
|
ResultNotifyDTO.builder().sn(dockSn) |
||||||
|
.message(eventsReceiver.getReason().getMessage()) |
||||||
|
.result(eventsReceiver.getReason().getVal()).build()); |
||||||
|
return receiver; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public class GimbalResetImpl extends PayloadCommandsHandler { |
||||||
|
public GimbalResetImpl(DronePayloadParam param) { |
||||||
|
super(param); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean valid() { |
||||||
|
return Objects.nonNull(param.getResetMode()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.common.util.SpringBeanUtils; |
||||||
|
import com.dji.sample.control.model.param.DronePayloadParam; |
||||||
|
import com.dji.sample.manage.model.dto.DeviceDTO; |
||||||
|
import com.dji.sample.manage.model.receiver.OsdCameraReceiver; |
||||||
|
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver; |
||||||
|
import com.dji.sample.manage.service.IDevicePayloadService; |
||||||
|
import com.dji.sample.manage.service.IDeviceRedisService; |
||||||
|
|
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/4/23 |
||||||
|
*/ |
||||||
|
public abstract class PayloadCommandsHandler { |
||||||
|
|
||||||
|
DronePayloadParam param; |
||||||
|
|
||||||
|
OsdCameraReceiver osdCamera; |
||||||
|
|
||||||
|
PayloadCommandsHandler(DronePayloadParam param) { |
||||||
|
this.param = param; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean valid() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canPublish(String deviceSn) { |
||||||
|
Optional<OsdSubDeviceReceiver> deviceOpt = SpringBeanUtils.getBean(IDeviceRedisService.class) |
||||||
|
.getDeviceOsd(deviceSn, OsdSubDeviceReceiver.class); |
||||||
|
if (deviceOpt.isEmpty()) { |
||||||
|
throw new RuntimeException("The device is offline."); |
||||||
|
} |
||||||
|
osdCamera = deviceOpt.get().getCameras().stream() |
||||||
|
.filter(osdCamera -> param.getPayloadIndex().equals(osdCamera.getPayloadIndex())) |
||||||
|
.findAny() |
||||||
|
.orElseThrow(() -> new RuntimeException("Did not receive osd information about the camera, please check the cache data.")); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private String checkDockOnline(String dockSn) { |
||||||
|
Optional<DeviceDTO> deviceOpt = SpringBeanUtils.getBean(IDeviceRedisService.class).getDeviceOnline(dockSn); |
||||||
|
if (deviceOpt.isEmpty()) { |
||||||
|
throw new RuntimeException("The dock is offline."); |
||||||
|
} |
||||||
|
return deviceOpt.get().getChildDeviceSn(); |
||||||
|
} |
||||||
|
|
||||||
|
private void checkDeviceOnline(String deviceSn) { |
||||||
|
boolean isOnline = SpringBeanUtils.getBean(IDeviceRedisService.class).checkDeviceOnline(deviceSn); |
||||||
|
if (!isOnline) { |
||||||
|
throw new RuntimeException("The device is offline."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void checkAuthority(String deviceSn) { |
||||||
|
boolean hasAuthority = SpringBeanUtils.getBean(IDevicePayloadService.class) |
||||||
|
.checkAuthorityPayload(deviceSn, param.getPayloadIndex()); |
||||||
|
if (!hasAuthority) { |
||||||
|
throw new RuntimeException("The device does not have payload control authority."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public final void checkCondition(String dockSn) { |
||||||
|
if (!valid()) { |
||||||
|
throw new RuntimeException("illegal argument"); |
||||||
|
} |
||||||
|
|
||||||
|
String deviceSn = checkDockOnline(dockSn); |
||||||
|
checkDeviceOnline(deviceSn); |
||||||
|
checkAuthority(deviceSn); |
||||||
|
|
||||||
|
if (!canPublish(deviceSn)) { |
||||||
|
throw new RuntimeException("The current state of the drone does not support this function, please try again later."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.dji.sample.control.service.impl; |
||||||
|
|
||||||
|
import com.dji.sample.common.util.SpringBeanUtils; |
||||||
|
import com.dji.sample.manage.model.enums.DockModeCodeEnum; |
||||||
|
import com.dji.sample.manage.service.IDeviceService; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.3 |
||||||
|
* @date 2022/10/27 |
||||||
|
*/ |
||||||
|
public class RemoteDebugHandler { |
||||||
|
|
||||||
|
public boolean valid() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canPublish(String sn) { |
||||||
|
IDeviceService deviceService = SpringBeanUtils.getBean(IDeviceService.class); |
||||||
|
DockModeCodeEnum dockMode = deviceService.getDockMode(sn); |
||||||
|
return DockModeCodeEnum.REMOTE_DEBUGGING == dockMode; |
||||||
|
} |
||||||
|
} |
@ -1,35 +0,0 @@ |
|||||||
package com.dji.sample.manage.controller; |
|
||||||
|
|
||||||
import com.dji.sample.component.mqtt.model.ChannelName; |
|
||||||
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver; |
|
||||||
import com.dji.sample.manage.service.IDevicePayloadService; |
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.integration.annotation.ServiceActivator; |
|
||||||
import org.springframework.messaging.MessageHeaders; |
|
||||||
import org.springframework.web.bind.annotation.RestController; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author sean.zhou |
|
||||||
* @date 2021/11/19 |
|
||||||
* @version 0.1 |
|
||||||
*/ |
|
||||||
@RestController |
|
||||||
public class DevicePayloadController { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private IDevicePayloadService devicePayloadService; |
|
||||||
|
|
||||||
/** |
|
||||||
* Handles messages in the state topic about basic drone data. |
|
||||||
* |
|
||||||
* Note: Only the data of the drone payload is handled here. You can handle other data from the drone |
|
||||||
* according to your business needs. |
|
||||||
* @param deviceBasic basic drone data |
|
||||||
* @param headers |
|
||||||
*/ |
|
||||||
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC) |
|
||||||
public void stateBasic(DeviceBasicReceiver deviceBasic, MessageHeaders headers) { |
|
||||||
|
|
||||||
devicePayloadService.saveDeviceBasicPayload(deviceBasic.getPayloads(), headers.getTimestamp()); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.manage.model.dto; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.DroneAuthorityEnum; |
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Builder; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/2 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@Builder |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class DeviceAuthorityDTO { |
||||||
|
|
||||||
|
private String sn; |
||||||
|
|
||||||
|
private DroneAuthorityEnum type; |
||||||
|
|
||||||
|
private String controlSource; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.manage.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/16 |
||||||
|
*/ |
||||||
|
public enum ControlSourceEnum { |
||||||
|
|
||||||
|
A, B; |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public String getControlSource() { |
||||||
|
return name(); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static ControlSourceEnum find(String controlSource) { |
||||||
|
return Arrays.stream(values()).filter(controlSourceEnum -> controlSourceEnum.name().equals(controlSource)).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
package com.dji.sample.manage.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/9 |
||||||
|
*/ |
||||||
|
public enum DeviceModeCodeEnum { |
||||||
|
|
||||||
|
IDLE(0), |
||||||
|
|
||||||
|
TAKEOFF_PREPARE(1), |
||||||
|
|
||||||
|
TAKEOFF_FINISHED(2), |
||||||
|
|
||||||
|
MANUAL(3), |
||||||
|
|
||||||
|
TAKEOFF_AUTO(4), |
||||||
|
|
||||||
|
WAYLINE(5), |
||||||
|
|
||||||
|
PANORAMIC_SHOT(6), |
||||||
|
|
||||||
|
ACTIVE_TRACK(7), |
||||||
|
|
||||||
|
ADS_B_AVOIDANCE(8), |
||||||
|
|
||||||
|
RETURN_AUTO(9), |
||||||
|
|
||||||
|
LANDING_AUTO(10), |
||||||
|
|
||||||
|
LANDING_FORCED(11), |
||||||
|
|
||||||
|
LANDING_THREE_PROPELLER(12), |
||||||
|
|
||||||
|
UPGRADING(13), |
||||||
|
|
||||||
|
DISCONNECTED(14), |
||||||
|
|
||||||
|
APAS(15), |
||||||
|
|
||||||
|
VIRTUAL_JOYSTICK(16); |
||||||
|
|
||||||
|
int val; |
||||||
|
|
||||||
|
DeviceModeCodeEnum(int val) { |
||||||
|
this.val = val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static DeviceModeCodeEnum find(int value) { |
||||||
|
return Arrays.stream(values()).filter(modeCodeEnum -> modeCodeEnum.ordinal() == value).findAny().orElse(DISCONNECTED); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package com.dji.sample.manage.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/2/28 |
||||||
|
*/ |
||||||
|
public enum DockDrcStateEnum { |
||||||
|
|
||||||
|
DISCONNECTED(0), |
||||||
|
|
||||||
|
CONNECTING(1), |
||||||
|
|
||||||
|
CONNECTED(2); |
||||||
|
|
||||||
|
int val; |
||||||
|
|
||||||
|
DockDrcStateEnum(int val) { |
||||||
|
this.val = val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static DockDrcStateEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(drcState -> drcState.getVal() == val).findAny().orElse(DISCONNECTED); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
package com.dji.sample.manage.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/2/28 |
||||||
|
*/ |
||||||
|
public enum DockModeCodeEnum { |
||||||
|
|
||||||
|
IDLE(0), |
||||||
|
|
||||||
|
DEBUGGING(1), |
||||||
|
|
||||||
|
REMOTE_DEBUGGING(2), |
||||||
|
|
||||||
|
UPGRADING(3), |
||||||
|
|
||||||
|
WORKING(4), |
||||||
|
|
||||||
|
DISCONNECTED(-1); |
||||||
|
|
||||||
|
int val; |
||||||
|
|
||||||
|
DockModeCodeEnum(int val) { |
||||||
|
this.val = val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static DockModeCodeEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(modeCode -> modeCode.getVal() == val).findAny().orElse(DISCONNECTED); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.manage.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/1 |
||||||
|
*/ |
||||||
|
public enum DroneRcLostActionEnum { |
||||||
|
|
||||||
|
HOVER, LAND, RETURN_HOME; |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return ordinal(); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static DroneRcLostActionEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(controlActionEnum -> controlActionEnum.ordinal() == val).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.dji.sample.manage.model.enums; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator; |
||||||
|
import com.fasterxml.jackson.annotation.JsonValue; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/15 |
||||||
|
*/ |
||||||
|
public enum WaylineRcLostActionEnum { |
||||||
|
|
||||||
|
CONTINUE_WAYLINE, EXECUTE_RC_LOST_ACTION; |
||||||
|
|
||||||
|
@JsonValue |
||||||
|
public int getVal() { |
||||||
|
return ordinal(); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonCreator |
||||||
|
public static WaylineRcLostActionEnum find(int val) { |
||||||
|
return Arrays.stream(values()).filter(lostActionEnum -> lostActionEnum.ordinal() == val).findAny().get(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package com.dji.sample.manage.model.receiver; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/30 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class FirmwareProgressExtReceiver { |
||||||
|
|
||||||
|
private Long rate; |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.dji.sample.manage.model.receiver; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/8 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class LiveviewWorldRegionReceiver { |
||||||
|
|
||||||
|
private Double bottom; |
||||||
|
|
||||||
|
private Double left; |
||||||
|
|
||||||
|
private Double right; |
||||||
|
|
||||||
|
private Double top; |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.dji.sample.manage.model.receiver; |
||||||
|
|
||||||
|
import com.dji.sample.control.model.enums.CameraModeEnum; |
||||||
|
import com.dji.sample.control.model.enums.CameraStateEnum; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/8 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class OsdCameraReceiver { |
||||||
|
|
||||||
|
private CameraModeEnum cameraMode; |
||||||
|
|
||||||
|
private LiveviewWorldRegionReceiver liveviewWorldRegion; |
||||||
|
|
||||||
|
private String payloadIndex; |
||||||
|
|
||||||
|
private CameraStateEnum photoState; |
||||||
|
|
||||||
|
private Integer recordTime; |
||||||
|
|
||||||
|
private CameraStateEnum recordingState; |
||||||
|
|
||||||
|
private Long remainPhotoNum; |
||||||
|
|
||||||
|
private Long remainRecordDuration; |
||||||
|
|
||||||
|
private Float zoomFactor; |
||||||
|
|
||||||
|
private Float irZoomFactor; |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package com.dji.sample.manage.model.receiver; |
||||||
|
|
||||||
|
import com.dji.sample.manage.model.enums.DroneRcLostActionEnum; |
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.EqualsAndHashCode; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/3 |
||||||
|
*/ |
||||||
|
@EqualsAndHashCode(callSuper = true) |
||||||
|
@Data |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class OutOfControlActionReceiver extends BasicDeviceProperty { |
||||||
|
|
||||||
|
private Integer value; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean valid() { |
||||||
|
return Objects.nonNull(value) && value >= 0 && value < DroneRcLostActionEnum.values().length; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package com.dji.sample.manage.model.receiver; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.EqualsAndHashCode; |
||||||
|
import lombok.NoArgsConstructor; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/3 |
||||||
|
*/ |
||||||
|
@EqualsAndHashCode(callSuper = true) |
||||||
|
@Data |
||||||
|
@AllArgsConstructor |
||||||
|
@NoArgsConstructor |
||||||
|
public class RthAltitudeReceiver extends BasicDeviceProperty { |
||||||
|
|
||||||
|
private Integer value; |
||||||
|
|
||||||
|
private static final int RTH_ALTITUDE_MAX = 500; |
||||||
|
|
||||||
|
private static final int RTH_ALTITUDE_MIN = 20; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean valid() { |
||||||
|
return Objects.nonNull(this.value) && this.value >= RTH_ALTITUDE_MIN && this.value <= RTH_ALTITUDE_MAX; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
package com.dji.sample.manage.service; |
||||||
|
|
||||||
|
import com.dji.sample.component.mqtt.model.EventsOutputProgressReceiver; |
||||||
|
import com.dji.sample.component.mqtt.model.EventsReceiver; |
||||||
|
import com.dji.sample.manage.model.dto.DeviceDTO; |
||||||
|
import com.dji.sample.manage.model.receiver.FirmwareProgressExtReceiver; |
||||||
|
|
||||||
|
import java.util.Optional; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author sean |
||||||
|
* @version 1.4 |
||||||
|
* @date 2023/3/21 |
||||||
|
*/ |
||||||
|
public interface IDeviceRedisService { |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if the device is online. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Boolean checkDeviceOnline(String sn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Query the basic information of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Optional<DeviceDTO> getDeviceOnline(String sn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Save the basic information of the device in redis. |
||||||
|
* @param device |
||||||
|
*/ |
||||||
|
void setDeviceOnline(DeviceDTO device); |
||||||
|
|
||||||
|
/** |
||||||
|
* Delete the basic device information saved in redis. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Boolean delDeviceOnline(String sn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the device's osd real-time data. |
||||||
|
* @param sn |
||||||
|
* @param clazz |
||||||
|
* @param <T> |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
<T> Optional<T> getDeviceOsd(String sn, Class<T> clazz); |
||||||
|
|
||||||
|
/** |
||||||
|
* Save the firmware update progress of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @param events |
||||||
|
*/ |
||||||
|
void setFirmwareUpgrading(String sn, EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>> events); |
||||||
|
|
||||||
|
/** |
||||||
|
* Query the firmware update progress of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Optional<EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>>> getFirmwareUpgradingProgress(String sn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Delete the firmware update progress of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Boolean delFirmwareUpgrading(String sn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Save the hms key of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @param keys |
||||||
|
*/ |
||||||
|
void addEndHmsKeys(String sn, String... keys); |
||||||
|
|
||||||
|
/** |
||||||
|
* Query all hms keys of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Set<String> getAllHmsKeys(String sn); |
||||||
|
|
||||||
|
/** |
||||||
|
* Delete all hms keys of the device in redis. |
||||||
|
* @param sn |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Boolean delHmsKeysBySn(String sn); |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue