| | |
| | | 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.dji.sample.component.mqtt.model.ChannelName; |
| | | 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.enums.DroneAuthorityEnum; |
| | | import com.dji.sample.manage.dao.IDevicePayloadMapper; |
| | | import com.dji.sample.manage.model.dto.DeviceAuthorityDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceDictionaryDTO; |
| | | import com.dji.sample.manage.model.dto.DevicePayloadDTO; |
| | | import com.dji.sample.manage.model.entity.DevicePayloadEntity; |
| | | import com.dji.sample.manage.model.enums.ControlSourceEnum; |
| | | import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
| | | import com.dji.sample.manage.model.enums.UserTypeEnum; |
| | | import com.dji.sample.manage.model.receiver.DevicePayloadReceiver; |
| | | import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver; |
| | | import com.dji.sample.manage.service.ICapacityCameraService; |
| | | import com.dji.sample.manage.service.IDeviceDictionaryService; |
| | | import com.dji.sample.manage.service.IDevicePayloadService; |
| | | import com.dji.sample.manage.service.IDeviceRedisService; |
| | | 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.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | * @version 0.1 |
| | | * @date 2021/11/19 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | @Transactional |
| | | public class DevicePayloadServiceImpl implements IDevicePayloadService { |
| | |
| | | |
| | | @Autowired |
| | | private ICapacityCameraService capacityCameraService; |
| | | |
| | | @Autowired |
| | | private ISendMessageService sendMessageService; |
| | | |
| | | @Autowired |
| | | private IDeviceRedisService deviceRedisService; |
| | | |
| | | @Override |
| | | public Integer checkPayloadExist(String payloadSn) { |
| | |
| | | // If it already exists, update the data directly. |
| | | if (id > 0) { |
| | | entity.setId(id); |
| | | return mapper.updateById(entity); |
| | | // For the payload of the drone itself, there is no firmware version. |
| | | entity.setFirmwareVersion(null); |
| | | return mapper.updateById(entity) > 0 ? entity.getId() : 0; |
| | | } |
| | | return mapper.insert(entity) > 0 ? entity.getId() : 0; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean savePayloadDTOs(List<DevicePayloadReceiver> payloadReceiverList) { |
| | | if (payloadReceiverList.isEmpty()) { |
| | | return true; |
| | | } |
| | | |
| | | String deviceSn = payloadReceiverList.get(0).getDeviceSn(); |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceSn); |
| | | if (deviceOpt.isEmpty()) { |
| | | return false; |
| | | } |
| | | DeviceDTO device = deviceOpt.get(); |
| | | List<DevicePayloadDTO> payloads = new ArrayList<>(); |
| | | |
| | | Map<String, String> controlMap = CollectionUtils.isEmpty(device.getPayloadsList()) ? |
| | | Collections.emptyMap() : |
| | | device.getPayloadsList().stream() |
| | | .collect(Collectors.toMap(DevicePayloadDTO::getPayloadIndex, DevicePayloadDTO::getControlSource)); |
| | | |
| | | for (DevicePayloadReceiver payloadReceiver : payloadReceiverList) { |
| | | int payloadId = this.saveOnePayloadDTO(payloadReceiver); |
| | | if (payloadId <= 0) { |
| | | return false; |
| | | } |
| | | payloads.add(this.receiver2Dto(payloadReceiver)); |
| | | if (!controlMap.getOrDefault(payloadReceiver.getPayloadIndex(), "").equals(payloadReceiver.getControlSource())) { |
| | | sendMessageService.sendBatch(device.getWorkspaceId(), UserTypeEnum.WEB.getVal(), |
| | | BizCodeEnum.CONTROL_SOURCE_CHANGE.getCode(), |
| | | DeviceAuthorityDTO.builder() |
| | | .controlSource(payloadReceiver.getControlSource()) |
| | | .sn(payloadReceiver.getSn()) |
| | | .type(DroneAuthorityEnum.PAYLOAD) |
| | | .build()); |
| | | } |
| | | } |
| | | |
| | | if (payloads.isEmpty()) { |
| | | payloads = this.getDevicePayloadEntitiesByDeviceSn(deviceSn); |
| | | } |
| | | device.setPayloadsList(payloads); |
| | | |
| | | deviceRedisService.setDeviceOnline(device); |
| | | return true; |
| | | } |
| | | |
| | |
| | | }); |
| | | } |
| | | |
| | | @Override |
| | | public void updateFirmwareVersion(FirmwareVersionReceiver receiver) { |
| | | mapper.update(DevicePayloadEntity.builder() |
| | | .firmwareVersion(receiver.getFirmwareVersion()) |
| | | .build() |
| | | , new LambdaUpdateWrapper<DevicePayloadEntity>() |
| | | .eq(DevicePayloadEntity::getDeviceSn, receiver.getSn())); |
| | | } |
| | | |
| | | /** |
| | | * Handle payload data for devices. |
| | | * @param payloadReceiverList |
| | | * @param headers |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_PAYLOAD) |
| | | public void handleDeviceBasicPayload(List<DevicePayloadReceiver> payloadReceiverList, MessageHeaders headers) { |
| | | if (payloadReceiverList.isEmpty()) { |
| | | return; |
| | | } |
| | | String deviceSn = payloadReceiverList.get(0).getDeviceSn(); |
| | | String key = RedisConst.STATE_PAYLOAD_PREFIX + deviceSn; |
| | | // Solve timing problems |
| | | long last = (long) Objects.requireNonNullElse(RedisOpsUtils.get(key), 0L); |
| | | long timestamp = headers.getTimestamp(); |
| | | if (last > timestamp) { |
| | | return; |
| | | } |
| | | |
| | | // Filter unsaved payload information. |
| | | Set<String> payloadSns = this.getDevicePayloadEntitiesByDeviceSn(payloadReceiverList.get(0).getDeviceSn()) |
| | | .stream().map(DevicePayloadDTO::getPayloadSn).collect(Collectors.toSet()); |
| | | |
| | | Set<String> newPayloadSns = payloadReceiverList.stream().map(DevicePayloadReceiver::getSn).collect(Collectors.toSet()); |
| | | payloadSns.removeAll(newPayloadSns); |
| | | this.deletePayloadsByPayloadsSn(payloadSns); |
| | | |
| | | // Save the new payload information. |
| | | boolean isSave = this.savePayloadDTOs(payloadReceiverList); |
| | | if (isSave) { |
| | | RedisOpsUtils.setWithExpire(key, timestamp, RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | log.debug("The result of saving the payloads is {}.", isSave); |
| | | } |
| | | |
| | | @Override |
| | | public void deletePayloadsByPayloadsSn(Collection<String> payloadSns) { |
| | | if (CollectionUtils.isEmpty(payloadSns)) { |
| | | return; |
| | | } |
| | | mapper.delete(new LambdaUpdateWrapper<DevicePayloadEntity>() |
| | | .or(wrapper -> payloadSns.forEach(sn -> wrapper.eq(DevicePayloadEntity::getPayloadSn, sn)))); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean checkAuthorityPayload(String deviceSn, String payloadIndex) { |
| | | return deviceRedisService.getDeviceOnline(deviceSn).flatMap(device -> |
| | | Optional.of(DeviceDomainEnum.SUB_DEVICE.getVal() == device.getDomain() |
| | | && !CollectionUtils.isEmpty(device.getPayloadsList()) |
| | | && ControlSourceEnum.A.getControlSource() |
| | | .equals(device.getPayloadsList().stream() |
| | | .filter(payload -> payloadIndex.equals(payload.getPayloadIndex())) |
| | | .map(DevicePayloadDTO::getControlSource).findAny() |
| | | .orElse(ControlSourceEnum.B.getControlSource())))).orElse(true); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * Convert database entity objects into payload data transfer object. |
| | | * @param entity |
| | |
| | | builder.payloadSn(entity.getPayloadSn()) |
| | | .payloadName(entity.getPayloadName()) |
| | | .payloadDesc(entity.getPayloadDesc()) |
| | | .payloadIndex(entity.getPayloadIndex()); |
| | | .index(entity.getPayloadIndex()) |
| | | .payloadIndex(entity.getPayloadType() + "-" + entity.getSubType() + "-" + entity.getPayloadIndex()) |
| | | .controlSource(entity.getControlSource()); |
| | | } |
| | | return builder.build(); |
| | | } |
| | |
| | | String[] payloadIndexArr = dto.getPayloadIndex().split("-"); |
| | | try { |
| | | int[] arr = Arrays.stream(payloadIndexArr) |
| | | .map(Integer::valueOf) |
| | | .mapToInt(Integer::intValue) |
| | | .mapToInt(Integer::parseInt) |
| | | .toArray(); |
| | | |
| | | if (arr.length == 3) { |
| | | Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService |
| | | .getOneDictionaryInfoByDomainTypeSubType(DeviceDomainEnum.PAYLOAD.getVal(), |
| | | arr[0], arr[1]); |
| | | dictionaryOpt.ifPresent(dictionary -> |
| | | builder.payloadName(dictionary.getDeviceName()) |
| | | .payloadDesc(dictionary.getDeviceDesc())); |
| | | Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService |
| | | .getOneDictionaryInfoByTypeSubType(DeviceDomainEnum.PAYLOAD.getVal(), arr[0], arr[1]); |
| | | dictionaryOpt.ifPresent(dictionary -> |
| | | builder.payloadName(dictionary.getDeviceName()) |
| | | .payloadDesc(dictionary.getDeviceDesc())); |
| | | |
| | | } |
| | | builder.payloadType(arr[0]) |
| | | .subType(arr[1]) |
| | | .payloadIndex(arr[2]); |
| | | .payloadIndex(arr[2]) |
| | | .controlSource(dto.getControlSource()); |
| | | } catch (NumberFormatException e) { |
| | | builder.payloadType(Integer.valueOf(payloadIndexArr[0])) |
| | | builder.payloadType(-1) |
| | | .subType(-1) |
| | | .payloadIndex(Integer.valueOf(payloadIndexArr[2])); |
| | | .payloadIndex(-1); |
| | | } |
| | | |
| | | return builder |
| | | .payloadSn(dto.getSn()) |
| | | .version(dto.getVersion()) |
| | | .deviceSn(dto.getSn() |
| | | .substring(0, |
| | | dto.getSn().indexOf("-"))) |
| | | .deviceSn(dto.getDeviceSn()) |
| | | .build(); |
| | | } |
| | | |
| | | private DevicePayloadDTO receiver2Dto(DevicePayloadReceiver receiver) { |
| | | DevicePayloadDTO.DevicePayloadDTOBuilder builder = DevicePayloadDTO.builder(); |
| | | if (receiver == null) { |
| | | return builder.build(); |
| | | } |
| | | return builder.payloadSn(receiver.getSn()) |
| | | .payloadIndex(receiver.getPayloadIndex()) |
| | | .controlSource(receiver.getControlSource()) |
| | | .build(); |
| | | } |
| | | |