| | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.dji.sample.common.model.Pagination; |
| | | import com.dji.sample.common.model.PaginationData; |
| | |
| | | import com.dji.sample.component.oss.service.impl.OssServiceContext; |
| | | import com.dji.sample.component.redis.RedisConst; |
| | | import com.dji.sample.component.redis.RedisOpsUtils; |
| | | import com.dji.sample.component.websocket.model.CustomWebSocketMessage; |
| | | import com.dji.sample.component.websocket.model.BizCodeEnum; |
| | | import com.dji.sample.component.websocket.service.IWebSocketManageService; |
| | | import com.dji.sample.component.websocket.service.impl.SendMessageServiceImpl; |
| | | import com.dji.sample.manage.dao.IDeviceFirmwareMapper; |
| | |
| | | import com.dji.sample.manage.model.param.DeviceFirmwareQueryParam; |
| | | import com.dji.sample.manage.model.param.DeviceFirmwareUploadParam; |
| | | import com.dji.sample.manage.model.param.DeviceOtaCreateParam; |
| | | import com.dji.sample.manage.model.receiver.FirmwareProgressExtReceiver; |
| | | import com.dji.sample.manage.service.IDeviceFirmwareService; |
| | | import com.dji.sample.manage.service.IDeviceService; |
| | | import com.dji.sample.manage.service.IDeviceRedisService; |
| | | import com.dji.sample.manage.service.IFirmwareModelService; |
| | | 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.integration.mqtt.support.MqttHeaders; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.DigestUtils; |
| | |
| | | private IWebSocketManageService webSocketManageService; |
| | | |
| | | @Autowired |
| | | private IDeviceService deviceService; |
| | | |
| | | @Autowired |
| | | private OssServiceContext ossServiceContext; |
| | | |
| | | @Autowired |
| | | private IFirmwareModelService firmwareModelService; |
| | | |
| | | @Autowired |
| | | private IDeviceRedisService deviceRedisService; |
| | | |
| | | @Override |
| | | public Optional<DeviceFirmwareDTO> getFirmware(String deviceName, String version) { |
| | | public Optional<DeviceFirmwareDTO> getFirmware(String workspaceId, String deviceName, String version) { |
| | | return Optional.ofNullable(entity2Dto(mapper.selectOne( |
| | | new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | .eq(DeviceFirmwareEntity::getDeviceName, deviceName) |
| | | .eq(DeviceFirmwareEntity::getFirmwareVersion, version)))); |
| | | .eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId) |
| | | .eq(DeviceFirmwareEntity::getFirmwareVersion, version) |
| | | .eq(DeviceFirmwareEntity::getStatus, true), |
| | | deviceName))); |
| | | } |
| | | |
| | | @Override |
| | | public Optional<DeviceFirmwareNoteDTO> getLatestFirmwareReleaseNote(String deviceName) { |
| | | return Optional.ofNullable(entity2NoteDto(mapper.selectOne( |
| | | new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | .eq(DeviceFirmwareEntity::getDeviceName, deviceName) |
| | | Wrappers.lambdaQuery(DeviceFirmwareEntity.class) |
| | | .eq(DeviceFirmwareEntity::getStatus, true) |
| | | .orderByDesc(DeviceFirmwareEntity::getReleaseDate, DeviceFirmwareEntity::getFirmwareVersion) |
| | | .last(" limit 1 ")))); |
| | | .orderByDesc(DeviceFirmwareEntity::getReleaseDate, DeviceFirmwareEntity::getFirmwareVersion), |
| | | deviceName))); |
| | | } |
| | | |
| | | @Override |
| | | public List<DeviceOtaCreateParam> getDeviceOtaFirmware(List<DeviceFirmwareUpgradeDTO> upgradeDTOS) { |
| | | public List<DeviceOtaCreateParam> getDeviceOtaFirmware(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) { |
| | | List<DeviceOtaCreateParam> deviceOtaList = new ArrayList<>(); |
| | | upgradeDTOS.forEach(upgradeDevice -> { |
| | | boolean exist = deviceService.checkDeviceOnline(upgradeDevice.getSn()); |
| | | boolean exist = deviceRedisService.checkDeviceOnline(upgradeDevice.getSn()); |
| | | if (!exist) { |
| | | throw new IllegalArgumentException("Device is offline."); |
| | | } |
| | | Optional<DeviceFirmwareDTO> firmwareOpt = this.getFirmware( |
| | | upgradeDevice.getDeviceName(), upgradeDevice.getProductVersion()); |
| | | workspaceId, upgradeDevice.getDeviceName(), upgradeDevice.getProductVersion()); |
| | | if (firmwareOpt.isEmpty()) { |
| | | throw new IllegalArgumentException("This firmware version does not exist."); |
| | | } |
| | | if (!firmwareOpt.get().getFirmwareStatus()) { |
| | | throw new IllegalArgumentException("This firmware version is not available."); |
| | | throw new IllegalArgumentException("This firmware version does not exist or is not available."); |
| | | } |
| | | DeviceOtaCreateParam ota = dto2OtaCreateDto(firmwareOpt.get()); |
| | | ota.setSn(upgradeDevice.getSn()); |
| | |
| | | return deviceOtaList; |
| | | } |
| | | |
| | | @Override |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_OTA_PROGRESS, outputChannel = ChannelName.OUTBOUND) |
| | | public void handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | | String sn = topic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(), |
| | | topic.indexOf(TopicConst.EVENTS_SUF)); |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_OTA_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS) |
| | | public CommonTopicReceiver handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | String sn = receiver.getGateway(); |
| | | |
| | | EventsReceiver<EventsOutputReceiver> eventsReceiver = objectMapper.convertValue(receiver.getData(), |
| | | new TypeReference<EventsReceiver<EventsOutputReceiver>>(){}); |
| | | EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>> eventsReceiver = objectMapper.convertValue(receiver.getData(), |
| | | new TypeReference<EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>>>(){}); |
| | | eventsReceiver.setBid(receiver.getBid()); |
| | | eventsReceiver.setSn(sn); |
| | | |
| | | EventsOutputReceiver output = eventsReceiver.getOutput(); |
| | | EventsOutputProgressReceiver<FirmwareProgressExtReceiver> output = eventsReceiver.getOutput(); |
| | | log.info("SN: {}, {} ===> Upgrading progress: {}", |
| | | sn, receiver.getMethod(), output.getProgress().toString()); |
| | | |
| | |
| | | log.error("SN: {}, {} ===> Error code: {}", sn, receiver.getMethod(), eventsReceiver.getResult()); |
| | | } |
| | | |
| | | DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn); |
| | | String childDeviceSn = device.getChildDeviceSn(); |
| | | boolean upgrade = RedisOpsUtils.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn) > 0; |
| | | boolean childUpgrade = RedisOpsUtils.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn) > 0; |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(sn); |
| | | if (deviceOpt.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // Determine whether it is the ending state, delete the update state key in redis after the job ends. |
| | | EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus()); |
| | | if (upgrade) { |
| | | if (statusEnum.getEnd()) { |
| | | // Delete the cache after the update is complete. |
| | | RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn); |
| | | } else { |
| | | // Update the update progress of the dock in redis. |
| | | RedisOpsUtils.setWithExpire( |
| | | RedisConst.FIRMWARE_UPGRADING_PREFIX + sn, output.getProgress().getPercent(), |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | } |
| | | if (childUpgrade) { |
| | | if (statusEnum.getEnd()) { |
| | | RedisOpsUtils.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn); |
| | | } else { |
| | | // Update the update progress of the drone in redis. |
| | | RedisOpsUtils.setWithExpire( |
| | | RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn, output.getProgress().getPercent(), |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | } |
| | | DeviceDTO device = deviceOpt.get(); |
| | | handleProgress(device.getWorkspaceId(), sn, eventsReceiver, statusEnum.getEnd()); |
| | | handleProgress(device.getWorkspaceId(), device.getChildDeviceSn(), eventsReceiver, statusEnum.getEnd()); |
| | | |
| | | webSocketMessageService.sendBatch( |
| | | webSocketManageService.getValueWithWorkspaceAndUserType( |
| | | device.getWorkspaceId(), UserTypeEnum.WEB.getVal()), |
| | | CustomWebSocketMessage.builder() |
| | | .data(eventsReceiver) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .bizCode(receiver.getMethod()) |
| | | .build()); |
| | | return receiver; |
| | | } |
| | | |
| | | if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) { |
| | | String replyTopic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF; |
| | | messageSenderService.publish(replyTopic, |
| | | CommonTopicResponse.builder() |
| | | .tid(receiver.getTid()) |
| | | .bid(receiver.getBid()) |
| | | .method(receiver.getMethod()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data(RequestsReply.success()) |
| | | .build()); |
| | | private void handleProgress(String workspaceId, String sn, |
| | | EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>> events, boolean isEnd) { |
| | | boolean upgrade = deviceRedisService.getFirmwareUpgradingProgress(sn).isPresent(); |
| | | if (!upgrade) { |
| | | return; |
| | | } |
| | | if (isEnd) { |
| | | // Delete the cache after the update is complete. |
| | | deviceRedisService.delFirmwareUpgrading(sn); |
| | | } else { |
| | | // Update the update progress of the dock in redis. |
| | | deviceRedisService.setFirmwareUpgrading(sn, events); |
| | | } |
| | | events.setSn(sn); |
| | | webSocketMessageService.sendBatch(workspaceId, UserTypeEnum.WEB.getVal(), BizCodeEnum.OTA_PROGRESS.getCode(), events); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean checkFileExist(String workspaceId, String fileMd5) { |
| | | return mapper.selectCount(new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | return RedisOpsUtils.checkExist(RedisConst.FILE_UPLOADING_PREFIX + workspaceId + fileMd5) || |
| | | mapper.selectCount(new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | .eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId) |
| | | .eq(DeviceFirmwareEntity::getFileMd5, fileMd5)) |
| | | > 0; |
| | |
| | | new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | .eq(DeviceFirmwareEntity::getWorkspaceId, workspaceId) |
| | | .eq(Objects.nonNull(param.getStatus()), DeviceFirmwareEntity::getStatus, param.getStatus()) |
| | | .eq(StringUtils.hasText(param.getDeviceName()), DeviceFirmwareEntity::getDeviceName, param.getDeviceName()) |
| | | .like(StringUtils.hasText(param.getProductVersion()), DeviceFirmwareEntity::getFirmwareVersion, param.getProductVersion()) |
| | | .orderByDesc(DeviceFirmwareEntity::getReleaseDate)); |
| | | .orderByDesc(DeviceFirmwareEntity::getReleaseDate), param.getDeviceName()); |
| | | |
| | | List<DeviceFirmwareDTO> data = page.getRecords().stream().map(this::entity2Dto).collect(Collectors.toList()); |
| | | return new PaginationData<DeviceFirmwareDTO>(data, new Pagination(page)); |
| | |
| | | |
| | | @Override |
| | | public void importFirmwareFile(String workspaceId, String creator, DeviceFirmwareUploadParam param, MultipartFile file) { |
| | | String key = RedisConst.FILE_UPLOADING_PREFIX + workspaceId; |
| | | String existKey = key + file.getOriginalFilename(); |
| | | if (RedisOpsUtils.getExpire(existKey) > 0) { |
| | | throw new RuntimeException("Please try again later."); |
| | | } |
| | | RedisOpsUtils.setWithExpire(existKey, true, RedisConst.DEVICE_ALIVE_SECOND); |
| | | try (InputStream is = file.getInputStream()) { |
| | | long size = is.available(); |
| | | String md5 = DigestUtils.md5DigestAsHex(is); |
| | | key += md5; |
| | | boolean exist = checkFileExist(workspaceId, md5); |
| | | if (exist) { |
| | | throw new RuntimeException("The file already exists."); |
| | | } |
| | | |
| | | RedisOpsUtils.set(key, System.currentTimeMillis()); |
| | | Optional<DeviceFirmwareDTO> firmwareOpt = verifyFirmwareFile(file); |
| | | if (firmwareOpt.isEmpty()) { |
| | | throw new RuntimeException("The file format is incorrect."); |
| | |
| | | String objectKey = OssConfiguration.objectDirPrefix + File.separator + firmwareId + FirmwareFileProperties.FIRMWARE_FILE_SUFFIX; |
| | | |
| | | ossServiceContext.putObject(OssConfiguration.bucket, objectKey, file.getInputStream()); |
| | | log.info("upload success"); |
| | | log.info("upload success. {}", file.getOriginalFilename()); |
| | | DeviceFirmwareDTO firmware = DeviceFirmwareDTO.builder() |
| | | .deviceName(param.getDeviceName()) |
| | | .releaseNote(param.getReleaseNote()) |
| | | .firmwareStatus(param.getStatus()) |
| | | .fileMd5(md5) |
| | |
| | | .firmwareId(firmwareId) |
| | | .build(); |
| | | |
| | | saveFirmwareInfo(firmware); |
| | | saveFirmwareInfo(firmware, param.getDeviceName()); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | RedisOpsUtils.del(key); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void saveFirmwareInfo(DeviceFirmwareDTO firmware) { |
| | | mapper.insert(dto2Entity(firmware)); |
| | | public void saveFirmwareInfo(DeviceFirmwareDTO firmware, List<String> deviceNames) { |
| | | DeviceFirmwareEntity entity = dto2Entity(firmware); |
| | | mapper.insert(entity); |
| | | firmwareModelService.saveFirmwareDeviceName( |
| | | FirmwareModelDTO.builder().firmwareId(entity.getFirmwareId()).deviceNames(deviceNames).build()); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | return DeviceFirmwareEntity.builder() |
| | | .fileName(dto.getFileName()) |
| | | .deviceName(dto.getDeviceName()) |
| | | .fileMd5(dto.getFileMd5()) |
| | | .fileSize(dto.getFileSize()) |
| | | .firmwareId(dto.getFirmwareId()) |
| | |
| | | return null; |
| | | } |
| | | return DeviceFirmwareDTO.builder() |
| | | .deviceName(entity.getDeviceName()) |
| | | .deviceName(Arrays.asList(entity.getDeviceName().split(","))) |
| | | .fileMd5(entity.getFileMd5()) |
| | | .fileSize(entity.getFileSize()) |
| | | .objectKey(entity.getObjectKey()) |