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; import com.dji.sample.log.model.entity.DroneFlightLogEntity; import com.dji.sample.log.model.entity.DroneFlightLogInfoEntity; import com.dji.sample.log.service.IDroneFlightLogInfoService; import com.dji.sample.log.service.IDroneFlightLogService; import com.dji.sample.manage.model.dto.DeviceDTO; import com.dji.sample.manage.model.dto.DevicePayloadDTO; import com.dji.sample.manage.model.dto.TelemetryDTO; import com.dji.sample.manage.model.dto.TelemetryDeviceDTO; import com.dji.sample.manage.model.enums.DeviceDomainEnum; import com.dji.sample.manage.model.enums.DeviceModeCodeEnum; import com.dji.sample.manage.model.receiver.OsdPayloadReceiver; import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author sean * @version 0.3 * @date 2022/2/21 */ @Service @Slf4j public class DeviceOSDServiceImpl extends AbstractTSAService { @Autowired private IDroneFlightLogService droneFlightLogService; @Autowired private IDroneFlightLogInfoService droneFlightLogInfoService; protected DeviceOSDServiceImpl(@Autowired @Qualifier("dockOSDServiceImpl") AbstractTSAService tsaService) { super(tsaService); } @Override public void pushTelemetryData(Collection sessions, CustomWebSocketMessage message, Object osdData) { if (osdData instanceof OsdSubDeviceReceiver) { OsdSubDeviceReceiver data = (OsdSubDeviceReceiver) osdData; TelemetryDTO telemetry = message.getData(); telemetry.setHost(TelemetryDeviceDTO.builder() .latitude(data.getLatitude()) .longitude(data.getLongitude()) .altitude(data.getElevation()) .attitudeHead(data.getAttitudeHead()) .elevation(data.getElevation()) .horizontalSpeed(data.getHorizontalSpeed()) .verticalSpeed(data.getVerticalSpeed()) .build()); this.sendMessageService.sendBatch(sessions, message); } } @Override public void handleOSD(CommonTopicReceiver receiver, DeviceDTO device, Collection webSessions, CustomWebSocketMessage wsMessage) { if (DeviceDomainEnum.SUB_DEVICE.getVal() == device.getDomain()) { wsMessage.setBizCode(BizCodeEnum.DEVICE_OSD.getCode()); OsdSubDeviceReceiver data = mapper.convertValue(receiver.getData(), OsdSubDeviceReceiver.class); //保存飞行日志 状态启动 "3":"手动飞行","4":"自动起飞","5":"航线飞行" if (DeviceModeCodeEnum.MANUAL.getVal() == data.getModeCode().getVal() || DeviceModeCodeEnum.TAKEOFF_AUTO.getVal() == data.getModeCode().getVal() || DeviceModeCodeEnum.WAYLINE.getVal() == data.getModeCode().getVal() ) { if (!RedisOpsUtils.checkExist(RedisConst.FLIGHT_LOG + device.getDeviceSn())) { // 开始记录日志 DroneFlightLogEntity dflPo = DroneFlightLogEntity.builder() .deviceSn(device.getDeviceSn()) .deviceName(device.getDeviceName()) .nickname(device.getNickname()) .workspaceId(device.getWorkspaceId()) .title(data.getModeCode().getVal() == 3?"手动飞行":data.getModeCode().getVal() == 4?"自动起飞":data.getModeCode().getVal() == 5?"航线飞行":"未知") .startTime(System.currentTimeMillis()) .trackId(data.getTrackId()) .startFlightDistance(data.getTotalFlightDistance()) .build(); droneFlightLogService.save(dflPo); //缓存对象用于关联数据 RedisOpsUtils.set(RedisConst.FLIGHT_LOG + device.getDeviceSn(),dflPo); } } //状态0时取消 if (DeviceModeCodeEnum.IDLE.getVal() == data.getModeCode().getVal()) { //如果存在则删除并保存结束时间 if (RedisOpsUtils.checkExist(RedisConst.FLIGHT_LOG + device.getDeviceSn())) { DroneFlightLogEntity dflPo = (DroneFlightLogEntity) RedisOpsUtils.get(RedisConst.FLIGHT_LOG + device.getDeviceSn()); dflPo.setEndTime(System.currentTimeMillis()); dflPo.setTotalFlightDistance(data.getTotalFlightDistance()); dflPo.setEndFlightDistance(data.getTotalFlightDistance()); droneFlightLogService.update(dflPo); RedisOpsUtils.del(RedisConst.FLIGHT_LOG + device.getDeviceSn()); } } //保存无人机实时位置信息 if (RedisOpsUtils.checkExist(RedisConst.FLIGHT_LOG + device.getDeviceSn())) { DroneFlightLogEntity dflPo = (DroneFlightLogEntity) RedisOpsUtils.get(RedisConst.FLIGHT_LOG + device.getDeviceSn()); DroneFlightLogInfoEntity dfliPo = DroneFlightLogInfoEntity.builder() .latitude(data.getLatitude()) .longitude(data.getLongitude()) .flightId(dflPo.getId()) .height(data.getHeight()) .elevation(data.getElevation()) .build(); droneFlightLogInfoService.save(dfliPo); } List payloadsList = device.getPayloadsList(); try { Map receiverData = (Map) receiver.getData(); data.setPayloads(payloadsList.stream() .map(payload -> mapper.convertValue( receiverData.getOrDefault(payload.getPayloadIndex(), Map.of()), OsdPayloadReceiver.class)) .collect(Collectors.toList())); } catch (NullPointerException e) { log.warn("Please remount the payload, or restart the drone. Otherwise the data of the payload will not be received."); } RedisOpsUtils.setWithExpire(RedisConst.OSD_PREFIX + device.getDeviceSn(), data, RedisConst.DEVICE_ALIVE_SECOND); wsMessage.getData().setHost(data); sendMessageService.sendBatch(webSessions, wsMessage); this.pushTelemetryData(device.getWorkspaceId(), data, device.getDeviceSn()); } tsaService.handleOSD(receiver, device, webSessions, wsMessage); } }