功能概述
服务端推送设备坐标信息到pilot端,pilot会把推送过来的信息显示在地图中。实现了同一工作空间下的所有设备之间的拓扑结构,实现设备间的态势信息分享。
执行步骤
- Pilot2成功上云后,通过接口GET: /manage/api/v1/workspaces/{workspace_id}/devices/topologies获取同一个工作空间下的所有设备列表和拓扑结构。
@GetMapping(PREFIX + "/workspaces/{workspace_id}/devices/topologies")
HttpResultResponse<TopologyResponse> obtainDeviceTopologyList(
@PathVariable(name = "workspace_id") String workspaceId,
HttpServletRequest req, HttpServletResponse rsp);
// 对应实现
@Override
public HttpResultResponse<TopologyResponse> obtainDeviceTopologyList(String workspaceId, HttpServletRequest req, HttpServletResponse rsp) {
List<TopologyList> topologyList = topologyService.getDeviceTopology(workspaceId);
return HttpResultResponse.success(new TopologyResponse().setList(topologyList));
}
// 查询逻辑
@Override
public List<TopologyList> getDeviceTopology(String workspaceId) {
// 查询同一工作空间下的网关设备
List<DeviceDTO> gatewayList = deviceService.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
.domains(List.of(DeviceDomainEnum.REMOTER_CONTROL.getDomain()))
.build());
List<TopologyList> topologyList = new ArrayList<>();
// 获取网关设备下的设备拓扑
gatewayList.forEach(device -> this.getDeviceTopologyByGatewaySn(device.getDeviceSn())
.ifPresent(topologyList::add));
return topologyList;
}
public Optional<TopologyList> getDeviceTopologyByGatewaySn(String gatewaySn) {
Optional<DeviceDTO> dtoOptional = deviceService.getDeviceBySn(gatewaySn);
if (dtoOptional.isEmpty()) {
return Optional.empty();
}
List<DeviceTopology> parents = new ArrayList<>();
DeviceDTO device = dtoOptional.get();
DeviceTopology gateway = deviceService.deviceConvertToTopologyDTO(device);
parents.add(gateway);
// 根据飞行器sn查询拓扑数据。
Optional<TopologyDeviceDTO> deviceTopo = deviceService.getDeviceTopoForPilot(device.getChildDeviceSn());
List<DeviceTopology> deviceTopoList = new ArrayList<>();
deviceTopo.ifPresent(deviceTopoList::add);
return Optional.ofNullable(new TopologyList().setParents(parents).setHosts(deviceTopoList));
}
- 在设备上下线时,云端收到设备上下线消息,会通过websocket协议推送给同一工作空间下的所有设备,Pilot2 上处于同一工作空间下的设备会收到设备上下线消息。
- Pilot2内部会再次通过GET: /manage/api/v1/workspaces/{workspace_id}/devices/topologies请求后端获取设备列表拓扑。更新pilot2上的拓扑信息
- 设备收到上报的osd信息会通过websocket协议传给同一工作空间下的所有设备,pilot2收到消息后,会在地图上实时展示设备的位置信息,设备朝向等。osd处理后的消息根据设备类型不同,会交给不同的通道进行处理,通道可能如下:ChannelName.INBOUND_OSD_RC、ChannelName.INBOUND_OSD_DOCK、ChannelName.INBOUND_OSD_RC_DRONE、ChannelName.INBOUND_OSD_DOCK_DRONE。此处以ChannelName.INBOUND_OSD_RC为例,消息会交给osd封装的接口处理:AbstractDeviceService#osdRemoteControl
@ServiceActivator(inputChannel = ChannelName.INBOUND_OSD_RC)
public void osdRemoteControl(TopicOsdRequest<OsdRemoteControl> request, MessageHeaders headers) {
throw new UnsupportedOperationException("osdRemoteControl not implemented");
}
// 实现
@Override
public void osdRemoteControl(TopicOsdRequest<OsdRemoteControl> request, MessageHeaders headers) {
String from = request.getFrom();
// 查询redis中设备是否存在
Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(from);
if (deviceOpt.isEmpty()) {
// 数据库是否存在
deviceOpt = deviceService.getDeviceBySn(from);
if (deviceOpt.isEmpty()) {
log.error("Please restart the drone.");
return;
}
}
DeviceDTO device = deviceOpt.get();
if (StringUtils.hasText(device.getChildDeviceSn())) {
deviceRedisService.getDeviceOnline(device.getChildDeviceSn()).ifPresent(device::setChildren);
}
// 设置设备上线
deviceRedisService.setDeviceOnline(device);
OsdRemoteControl data = request.getData();
// 推送数据到pilot ws
deviceService.pushOsdDataToPilot(device.getWorkspaceId(), from,
new DeviceOsdHost()
.setLatitude(data.getLatitude())
.setLongitude(data.getLongitude())
.setHeight(data.getHeight()));
// 推送数据到web ws
deviceService.pushOsdDataToWeb(device.getWorkspaceId(), BizCodeEnum.RC_OSD, from, data);
}