- sample代码架构
- sample代码实现
- 开发注意事项
4.11.1 sample代码架构
指令飞行功能只在机场上云支持,遥控器Pilot2不支持指令飞行。指令飞行API可以划分为:飞行控制类(DRC)、负载控制类、flyto指令与一键起飞指令。
sample基于延时的考虑,飞行控制指令是在前端下发,前端通过ws协议连接上mqtt服务器下发指令控制飞机飞行。负载控制类、flyto指令与一键起飞指令都是前端调用后端,由后端再下发给机场执行。
4.11.2 sample代码实现
1、机场飞机在执行航线任务中,需要在前端先请求航线任务暂停,航线暂停后,可以下发flyto控制飞机飞向目标点,也可以直接下发飞行控制指令控制飞机飞行。注意在下发DRC-飞行控制之前,需要先获取飞机的飞行控制权,并使飞机进入DRC指令飞行控制模式。前端通过POST ${url.control.prefix}${url.control.version}/workspaces/{workspace_id}/drc/enter 请求后端进入DRC指令飞行控制模式,对应后端接口为DrcController#drcEnter:
@PostMapping("/workspaces/{workspace_id}/drc/enter")
public HttpResultResponse drcEnter(@PathVariable("workspace_id") String workspaceId, @Valid @RequestBody DrcModeParam param) {
// 调用drcService#deviceDrcEnter获取drc链路配置的mqtt登录信息
JwtAclDTO acl = drcService.deviceDrcEnter(workspaceId, param);
return HttpResultResponse.success(acl);
}
drcService#deviceDrcEnter:
@Override
public JwtAclDTO deviceDrcEnter(String workspaceId, DrcModeParam param) {
// 与DRC相关的mqtt消息发布订阅主题
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + param.getDockSn() + TopicConst.DRC;
String pubTopic = topic + TopicConst.DOWN;
String subTopic = topic + TopicConst.UP;
// 如果机场已经进入了drc模式,则直接返回前端进入drc需要的配置信息
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();
}
// 检查机场能否进入drc模式,如果机场处于航线任务中或者飞机没有起飞等情况,机场无法进入drc状态
checkDrcModeCondition(workspaceId, param.getDockSn());
// 调用sdk封装好的接口,下发机场进入drc模式的指令
TopicServicesResponse<ServicesReplyData> reply = abstractControlService.drcModeEnter(
SDKManager.getDeviceSDK(param.getDockSn()),
new DrcModeEnterRequest()
.setMqttBroker(MqttPropertyConfiguration.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, ?>>() {}))))
.setHsiFrequency(1).setOsdFrequency(10));
// 如果机场返回进入drc报错,返回给前端报错信息
if (!reply.getData().getResult().isSuccess()) {
throw new RuntimeException("SN: " + param.getDockSn() + "; Error:" + reply.getData().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();
}
2、通过控制负载进行拍照,首先需要机场获取到飞机的负载控制权,获取到负载控制权后才能控制飞机进行拍照。前端通过POST ${url.control.prefix}${url.control.version}/devices/{sn}/authority/payload请求机场抢夺飞机的负载控制权,对应后端接口为:DockController#seizePayloadAuthority
@PostMapping("/{sn}/authority/payload")
public HttpResultResponse seizePayloadAuthority(@PathVariable String sn, @Valid @RequestBody DronePayloadParam param) {
// 通过controlService#seizeAuthority下发指令给机场抢夺飞机的负载控制权
return controlService.seizeAuthority(sn, DroneAuthorityEnum.PAYLOAD, param);
}
controlService#seizeAuthority:
@Override
public HttpResultResponse seizeAuthority(String sn, DroneAuthorityEnum authority, DronePayloadParam param) {
TopicServicesResponse<ServicesReplyData> response;
switch (authority) {
case FLIGHT:
if (deviceService.checkAuthorityFlight(sn)) {
return HttpResultResponse.success();
}
response = abstractControlService.flightAuthorityGrab(SDKManager.getDeviceSDK(sn));
break;
case PAYLOAD:
// 如果之前已经获取到负载控制权,则直接返回
if (checkPayloadAuthority(sn, param.getPayloadIndex())) {
return HttpResultResponse.success();
}
// 调用sdk包封装好的接口下发负载控制权抢夺指令
response = abstractControlService.payloadAuthorityGrab(SDKManager.getDeviceSDK(sn),
new PayloadAuthorityGrabRequest().setPayloadIndex(new PayloadIndex(param.getPayloadIndex())));
break;
default:
return HttpResultResponse.error(CloudSDKErrorEnum.INVALID_PARAMETER);
}
ServicesReplyData serviceReply = response.getData();
return serviceReply.getResult().isSuccess() ?
HttpResultResponse.success() : HttpResultResponse.error(serviceReply.getResult());
}
前端通过POST ${url.control.prefix}${url.control.version}/devices/{sn}/payload/commands携带拍照参数开启拍照,对应后端接口为:
4.11.3 开发注意事项
- 通过控制负载拍摄的照片,在飞机没有起飞的情况下,不会上传到云端;在飞机起飞后,会自动上传云端。
评论
2 条评论
4.11.3 中说的是,飞机没起飞的情况下,不会上传到云端。飞机起飞后,会自动上传。如果,是我没有下任务,只是在飞机开机且在机巢里的情况下,我抢夺负载控制权,然后拍了照片。这个时候的照片,是飞机在下一次任务起飞后的情况下,会自动上传上来吗?这个时候上传的图片的flightId是当前这个任务的吗?
您好,请问飞行控制指令是在前端下发,会不会有泄露mqtt密码的安全问题?
请登录写评论。