| | |
| | | import com.dji.sample.component.websocket.model.CustomWebSocketMessage; |
| | | import com.dji.sample.component.websocket.service.ISendMessageService; |
| | | import com.dji.sample.component.websocket.service.IWebSocketManageService; |
| | | import com.dji.sample.control.model.enums.DroneAuthorityEnum; |
| | | import com.dji.sample.manage.dao.IDeviceMapper; |
| | | import com.dji.sample.manage.model.dto.*; |
| | | import com.dji.sample.manage.model.entity.DeviceEntity; |
| | | import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
| | | import com.dji.sample.manage.model.enums.DeviceFirmwareStatusEnum; |
| | | import com.dji.sample.manage.model.enums.IconUrlEnum; |
| | | import com.dji.sample.manage.model.enums.UserTypeEnum; |
| | | import com.dji.sample.manage.model.enums.*; |
| | | import com.dji.sample.manage.model.param.DeviceOtaCreateParam; |
| | | import com.dji.sample.manage.model.param.DeviceQueryParam; |
| | | import com.dji.sample.manage.model.receiver.*; |
| | | import com.dji.sample.manage.service.*; |
| | | import com.dji.sample.wayline.model.entity.WaylineJobEntity; |
| | | import com.dji.sample.wayline.model.param.WaylineJobQueryParam; |
| | | import com.dji.sample.wayline.service.IWaylineJobService; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.JsonNode; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.integration.mqtt.support.MqttHeaders; |
| | | import org.springframework.messaging.Message; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private ObjectMapper objectMapper; |
| | | |
| | | @Autowired |
| | | private RedisOpsUtils redisOps; |
| | | |
| | | @Autowired |
| | | private IWebSocketManageService webSocketManageService; |
| | | |
| | | @Autowired |
| | | private IDeviceFirmwareService deviceFirmwareService; |
| | | |
| | | @Autowired |
| | | private ICapacityCameraService capacityCameraService; |
| | | |
| | | @Autowired |
| | | private IDeviceRedisService deviceRedisService; |
| | | |
| | | @Autowired |
| | | private IWaylineJobService waylineJobService; |
| | | |
| | | @Autowired |
| | | @Qualifier("gatewayOSDServiceImpl") |
| | | private ITSAService tsaService; |
| | | |
| | | private static final List<String> INIT_TOPICS_SUFFIX = List.of( |
| | | OSD_SUF, STATE_SUF, SERVICES_SUF + _REPLY_SUF, EVENTS_SUF, PROPERTY_SUF + SET_SUF + _REPLY_SUF); |
| | | |
| | | @Override |
| | | public Boolean deviceOffline(String gatewaySn) { |
| | | public Boolean deviceOffline(StatusGatewayReceiver gateway) { |
| | | String gatewaySn = gateway.getSn(); |
| | | this.subscribeTopicOnline(gatewaySn); |
| | | |
| | | // Only the remote controller is logged in and the aircraft is not connected. |
| | | String key = RedisConst.DEVICE_ONLINE_PREFIX + gatewaySn; |
| | | |
| | | boolean exist = redisOps.checkExist(key); |
| | | if (!exist) { |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(gatewaySn); |
| | | if (deviceOpt.isEmpty()) { |
| | | Optional<DeviceDTO> gatewayOpt = this.getDeviceBySn(gatewaySn); |
| | | if (gatewayOpt.isPresent()) { |
| | | DeviceDTO value = gatewayOpt.get(); |
| | | value.setChildDeviceSn(value.getDeviceSn()); |
| | | value.setBoundTime(null); |
| | | value.setLoginTime(null); |
| | | redisOps.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND); |
| | | value.setChildDeviceSn(null); |
| | | deviceRedisService.setDeviceOnline(value); |
| | | this.pushDeviceOnlineTopo(value.getWorkspaceId(), gatewaySn, gatewaySn); |
| | | return true; |
| | | } |
| | | DeviceDTO gateway = DeviceDTO.builder() |
| | | .deviceSn(gatewaySn) |
| | | .childDeviceSn(gatewaySn) |
| | | .domain(DeviceDomainEnum.GATEWAY.getDesc()) |
| | | .build(); |
| | | gatewayOpt.map(DeviceDTO::getWorkspaceId).ifPresent(gateway::setWorkspaceId); |
| | | redisOps.setWithExpire(key, gateway, RedisConst.DEVICE_ALIVE_SECOND); |
| | | this.pushDeviceOnlineTopo(gateway.getWorkspaceId(), gatewaySn, gatewaySn); |
| | | return true; |
| | | |
| | | // When connecting for the first time |
| | | DeviceEntity gatewayDevice = deviceGatewayConvertToDeviceEntity(gateway); |
| | | return onlineSaveDevice(gatewayDevice, null, null).isPresent(); |
| | | } |
| | | |
| | | String deviceSn = ((DeviceDTO)(redisOps.get(key))).getChildDeviceSn(); |
| | | if (deviceSn.equals(gatewaySn)) { |
| | | DeviceDTO deviceDTO = deviceOpt.get(); |
| | | String deviceSn = deviceDTO.getChildDeviceSn(); |
| | | if (!StringUtils.hasText(deviceSn)) { |
| | | return true; |
| | | } |
| | | |
| | |
| | | |
| | | @Override |
| | | public Boolean subDeviceOffline(String deviceSn) { |
| | | // Cancel drone-related subscriptions. |
| | | this.unsubscribeTopicOffline(deviceSn); |
| | | |
| | | payloadService.deletePayloadsByDeviceSn(new ArrayList<>(List.of(deviceSn))); |
| | | // If no information about this gateway device exists in the database, the drone is considered to be offline. |
| | | String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn; |
| | | if (!redisOps.checkExist(key) || redisOps.getExpire(key) <= 0) { |
| | | // If no information about this device exists in the cache, the drone is considered to be offline. |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceSn); |
| | | if (deviceOpt.isEmpty()) { |
| | | log.debug("The drone is already offline."); |
| | | return true; |
| | | } |
| | | DeviceDTO device = (DeviceDTO) redisOps.get(key); |
| | | DeviceDTO device = deviceOpt.get(); |
| | | // Cancel drone-related subscriptions. |
| | | this.unsubscribeTopicOffline(deviceSn); |
| | | |
| | | capacityCameraService.deleteCapacityCameraByDeviceSn(deviceSn); |
| | | deviceRedisService.delDeviceOnline(deviceSn); |
| | | RedisOpsUtils.del(RedisConst.OSD_PREFIX + deviceSn); |
| | | deviceRedisService.delHmsKeysBySn(deviceSn); |
| | | // Publish the latest device topology information in the current workspace. |
| | | this.pushDeviceOfflineTopo(device.getWorkspaceId(), deviceSn); |
| | | |
| | | redisOps.del(key); |
| | | log.debug("{} offline.", deviceSn); |
| | | return true; |
| | | } |
| | |
| | | @Override |
| | | public Boolean deviceOnline(StatusGatewayReceiver deviceGateway) { |
| | | String deviceSn = deviceGateway.getSubDevices().get(0).getSn(); |
| | | String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn; |
| | | // change log: Use redis instead of |
| | | long time = redisOps.getExpire(key); |
| | | long gatewayTime = redisOps.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn()); |
| | | long now = System.currentTimeMillis(); |
| | | |
| | | if (time > 0 && gatewayTime > 0) { |
| | | redisOps.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND); |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceSn); |
| | | Optional<DeviceDTO> gatewayOpt = deviceRedisService.getDeviceOnline(deviceGateway.getSn()); |
| | | |
| | | if (deviceOpt.isPresent() && gatewayOpt.isPresent()) { |
| | | DeviceDTO device = DeviceDTO.builder().loginTime(LocalDateTime.now()).deviceSn(deviceSn).build(); |
| | | DeviceDTO gateway = DeviceDTO.builder() |
| | | .loginTime(LocalDateTime.now()) |
| | |
| | | .childDeviceSn(deviceSn).build(); |
| | | this.updateDevice(gateway); |
| | | this.updateDevice(device); |
| | | String workspaceId = ((DeviceDTO)(redisOps.get(key))).getWorkspaceId(); |
| | | String workspaceId = deviceOpt.get().getWorkspaceId(); |
| | | if (StringUtils.hasText(workspaceId)) { |
| | | this.subscribeTopicOnline(deviceSn); |
| | | this.subscribeTopicOnline(deviceGateway.getSn()); |
| | |
| | | DeviceQueryParam.builder() |
| | | .childSn(deviceSn) |
| | | .build()); |
| | | gatewaysList.stream().filter( |
| | | gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn())) |
| | | gatewaysList.stream() |
| | | .filter(gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn())) |
| | | .findAny() |
| | | .ifPresent(gateway -> { |
| | | gateway.setChildDeviceSn(""); |
| | | this.updateDevice(gateway); |
| | | }); |
| | | |
| | | |
| | | DeviceEntity gateway = deviceGatewayConvertToDeviceEntity(deviceGateway); |
| | | gateway.setChildSn(deviceSn); |
| | | // Set the icon of the gateway device displayed in the pilot's map, required in the TSA module. |
| | | gateway.setUrlNormal(IconUrlEnum.NORMAL_PERSON.getUrl()); |
| | | // Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module. |
| | | gateway.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl()); |
| | | gateway.setLoginTime(now); |
| | | Optional<DeviceEntity> gatewayEntityOpt = onlineSaveDevice(gateway, deviceSn, null); |
| | | if (gatewayEntityOpt.isEmpty()) { |
| | | log.error("Failed to go online, please check the status data or code logic."); |
| | | return false; |
| | | } |
| | | |
| | | DeviceEntity subDevice = subDeviceConvertToDeviceEntity(deviceGateway.getSubDevices().get(0)); |
| | | // Set the icon of the drone device displayed in the pilot's map when it is selected, required in the TSA module. |
| | | subDevice.setUrlNormal(IconUrlEnum.NORMAL_EQUIPMENT.getUrl()); |
| | | // Set the icon of the drone device displayed in the pilot's map, required in the TSA module. |
| | | subDevice.setUrlSelect(IconUrlEnum.SELECT_EQUIPMENT.getUrl()); |
| | | subDevice.setLoginTime(now); |
| | | Optional<DeviceEntity> subDeviceEntityOpt = onlineSaveDevice(subDevice, null, gateway.getDeviceSn()); |
| | | if (subDeviceEntityOpt.isEmpty()) { |
| | | log.error("Failed to go online, please check the status data or code logic."); |
| | | return false; |
| | | } |
| | | |
| | | subDevice = subDeviceEntityOpt.get(); |
| | | gateway = gatewayEntityOpt.get(); |
| | | |
| | | // dock go online |
| | | if (deviceGateway.getDomain() != null && DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain()) { |
| | | Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(deviceGateway.getSn()); |
| | | if (deviceOpt.isEmpty()) { |
| | | log.info("The dock is not bound and cannot go online."); |
| | | return false; |
| | | } |
| | | gateway.setNickname(null); |
| | | subDevice.setNickname(null); |
| | | if (DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain() && !subDevice.getBoundStatus()) { |
| | | // Directly bind the drone of the dock to the same workspace as the dock. |
| | | bindDevice(DeviceDTO.builder().deviceSn(deviceSn).workspaceId(gateway.getWorkspaceId()).build()); |
| | | subDevice.setWorkspaceId(gateway.getWorkspaceId()); |
| | | } |
| | | |
| | | Optional<DeviceEntity> gatewayOpt = this.saveDevice(gateway); |
| | | String workspaceId = this.saveDevice(subDevice).orElse(subDevice).getWorkspaceId(); |
| | | |
| | | redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceSn, |
| | | DeviceDTO.builder() |
| | | .deviceSn(deviceSn) |
| | | .domain(DeviceDomainEnum.SUB_DEVICE.getDesc()) |
| | | .workspaceId(workspaceId) |
| | | .build(), |
| | | RedisConst.DEVICE_ALIVE_SECOND); |
| | | redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn(), |
| | | DeviceDTO.builder() |
| | | .deviceSn(gateway.getDeviceSn()) |
| | | .workspaceId(gatewayOpt.orElse(gateway).getWorkspaceId()) |
| | | .childDeviceSn(deviceSn) |
| | | .domain(deviceGateway.getDomain() != null ? |
| | | DeviceDomainEnum.getDesc(deviceGateway.getDomain()) : |
| | | DeviceDomainEnum.GATEWAY.getDesc()) |
| | | .build(), |
| | | RedisConst.DEVICE_ALIVE_SECOND); |
| | | log.debug("{} online.", subDevice.getDeviceSn()); |
| | | |
| | | if (StringUtils.hasText(workspaceId)) { |
| | | this.pushDeviceOnlineTopo(workspaceId, deviceGateway.getSn(), deviceSn); |
| | | } |
| | | // Subscribe to topic related to drone devices. |
| | | this.subscribeTopicOnline(deviceSn); |
| | | this.subscribeTopicOnline(deviceGateway.getSn()); |
| | | this.subscribeTopicOnline(deviceSn); |
| | | this.pushDeviceOnlineTopo(subDevice.getWorkspaceId(), deviceGateway.getSn(), deviceSn); |
| | | |
| | | log.debug("{} online.", subDevice.getDeviceSn()); |
| | | return true; |
| | | } |
| | | |
| | |
| | | return; |
| | | } |
| | | } |
| | | topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + OSD_SUF); |
| | | topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + STATE_SUF); |
| | | topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + SERVICES_SUF + _REPLY_SUF); |
| | | topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + REQUESTS_SUF); |
| | | topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + EVENTS_SUF); |
| | | String prefix = THING_MODEL_PRE + PRODUCT + sn; |
| | | INIT_TOPICS_SUFFIX.forEach(suffix -> topicService.subscribe(prefix + suffix)); |
| | | } |
| | | |
| | | @Override |
| | | public void unsubscribeTopicOffline(String sn) { |
| | | topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + OSD_SUF); |
| | | topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + STATE_SUF); |
| | | topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + SERVICES_SUF + _REPLY_SUF); |
| | | topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + REQUESTS_SUF); |
| | | topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + EVENTS_SUF); |
| | | String prefix = THING_MODEL_PRE + PRODUCT + sn; |
| | | INIT_TOPICS_SUFFIX.forEach(suffix -> topicService.unsubscribe(prefix + suffix)); |
| | | } |
| | | |
| | | @Override |
| | |
| | | public List<DeviceDTO> getDevicesByParams(DeviceQueryParam param) { |
| | | return mapper.selectList( |
| | | new LambdaQueryWrapper<DeviceEntity>() |
| | | //设备编码 |
| | | .eq(StringUtils.hasText(param.getDeviceSn()), |
| | | DeviceEntity::getDeviceSn, param.getDeviceSn()) |
| | | //设备类型 |
| | | .eq(param.getDeviceType() != null, |
| | | DeviceEntity::getDeviceType, param.getDeviceType()) |
| | | //负载类型 |
| | | .eq(param.getSubType() != null, |
| | | DeviceEntity::getSubType, param.getSubType()) |
| | | .eq(StringUtils.hasText(param.getChildSn()), |
| | |
| | | List<DeviceDTO> devicesList = this.getDevicesByParams( |
| | | DeviceQueryParam.builder() |
| | | .workspaceId(workspaceId) |
| | | .domains(List.of(DeviceDomainEnum.SUB_DEVICE.getVal())) |
| | | .domains(List.of(DeviceDomainEnum.GATEWAY.getVal(), DeviceDomainEnum.DOCK.getVal())) |
| | | .build()); |
| | | |
| | | devicesList.forEach(device -> { |
| | | this.spliceDeviceTopo(device); |
| | | device.setWorkspaceId(workspaceId); |
| | | device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn())); |
| | | devicesList.stream() |
| | | .filter(gateway -> DeviceDomainEnum.DOCK.getVal() == gateway.getDomain() || |
| | | deviceRedisService.checkDeviceOnline(gateway.getDeviceSn())) |
| | | .forEach(this::spliceDeviceTopo); |
| | | |
| | | devicesList.forEach(deviceDTO -> { |
| | | WaylineJobQueryParam waylineJobQueryParam = new WaylineJobQueryParam(); |
| | | waylineJobQueryParam.setDockSn(deviceDTO.getDeviceSn()); |
| | | WaylineJobEntity latestJob = waylineJobService.getLatestJob(workspaceId, waylineJobQueryParam); |
| | | deviceDTO.setLatestWaylineJob(latestJob); |
| | | }); |
| | | |
| | | return devicesList; |
| | | } |
| | | |
| | | @Override |
| | | public void spliceDeviceTopo(DeviceDTO device) { |
| | | public void spliceDeviceTopo(DeviceDTO gateway) { |
| | | |
| | | // remote controller |
| | | List<DeviceDTO> gatewaysList = getDevicesByParams( |
| | | DeviceQueryParam.builder() |
| | | .childSn(device.getDeviceSn()) |
| | | .build()); |
| | | gateway.setStatus(deviceRedisService.checkDeviceOnline(gateway.getDeviceSn())); |
| | | |
| | | // sub device |
| | | if (!StringUtils.hasText(gateway.getChildDeviceSn())) { |
| | | return; |
| | | } |
| | | |
| | | DeviceDTO subDevice = getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()).get(0); |
| | | subDevice.setStatus(deviceRedisService.checkDeviceOnline(subDevice.getDeviceSn())); |
| | | gateway.setChildren(subDevice); |
| | | |
| | | // payloads |
| | | List<DevicePayloadDTO> payloadsList = payloadService |
| | | .getDevicePayloadEntitiesByDeviceSn(device.getDeviceSn()); |
| | | |
| | | |
| | | device.setGatewaysList(gatewaysList); |
| | | device.setPayloadsList(payloadsList); |
| | | |
| | | subDevice.setPayloadsList(payloadService.getDevicePayloadEntitiesByDeviceSn(gateway.getChildDeviceSn())); |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | this.getDeviceTopoForPilot(sn) |
| | | .ifPresent(pilotMessage::setData); |
| | | boolean exist = redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn); |
| | | pilotMessage.getData().setOnlineStatus(exist); |
| | | pilotMessage.getData().setOnlineStatus(deviceRedisService.checkDeviceOnline(sn)); |
| | | pilotMessage.getData().setGatewaySn(gatewaySn.equals(sn) ? "" : gatewaySn); |
| | | |
| | | sendMessageService.sendBatch(sessions, pilotMessage); |
| | |
| | | TopologyDeviceDTO.TopologyDeviceDTOBuilder builder = TopologyDeviceDTO.builder(); |
| | | |
| | | if (device != null) { |
| | | int domain = DeviceDomainEnum.getVal(device.getDomain()); |
| | | String subType = String.valueOf(device.getSubType()); |
| | | String type = String.valueOf(device.getType()); |
| | | |
| | | builder.sn(device.getDeviceSn()) |
| | | .deviceCallsign(device.getNickname()) |
| | | .deviceModel(DeviceModelDTO.builder() |
| | | .domain(String.valueOf(domain)) |
| | | .subType(subType) |
| | | .type(type) |
| | | .key(domain + "-" + type + "-" + subType) |
| | | .domain(String.valueOf(device.getDomain())) |
| | | .subType(String.valueOf(device.getSubType())) |
| | | .type(String.valueOf(device.getType())) |
| | | .key(device.getDomain() + "-" + device.getType() + "-" + device.getSubType()) |
| | | .build()) |
| | | .iconUrls(device.getIconUrl()) |
| | | .onlineStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn())) |
| | | .onlineStatus(deviceRedisService.checkDeviceOnline(device.getDeviceSn())) |
| | | .boundStatus(device.getBoundStatus()) |
| | | .model(device.getDeviceName()) |
| | | .userId(device.getUserId()) |
| | | .domain(DeviceDomainEnum.getDesc(domain)) |
| | | .domain(device.getDomain()) |
| | | .build(); |
| | | } |
| | | return builder.build(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void handleOSD(String topic, byte[] payload) { |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_OSD) |
| | | public void handleOSD(Message<?> message) { |
| | | String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | | byte[] payload = (byte[])message.getPayload(); |
| | | CommonTopicReceiver receiver; |
| | | try { |
| | | String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(), |
| | | topic.indexOf(OSD_SUF)); |
| | | |
| | | // Real-time update of device status in memory |
| | | redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND); |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(from); |
| | | |
| | | DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + from); |
| | | |
| | | if (device == null) { |
| | | Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(from); |
| | | if (deviceOpt.isEmpty()) { |
| | | deviceOpt = this.getDeviceBySn(from); |
| | | if (deviceOpt.isEmpty()) { |
| | | log.error("Please restart the drone."); |
| | | return; |
| | | } |
| | | device = deviceOpt.get(); |
| | | if (!StringUtils.hasText(device.getWorkspaceId())) { |
| | | |
| | | if (!StringUtils.hasText(deviceOpt.get().getWorkspaceId())) { |
| | | this.unsubscribeTopicOffline(from); |
| | | return; |
| | | } |
| | | redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + from, device, |
| | | RedisConst.DEVICE_ALIVE_SECOND); |
| | | deviceRedisService.setDeviceOnline(deviceOpt.get()); |
| | | this.subscribeTopicOnline(from); |
| | | } |
| | | DeviceDTO device = deviceOpt.get(); |
| | | deviceRedisService.setDeviceOnline(device); |
| | | |
| | | receiver = objectMapper.readValue(payload, CommonTopicReceiver.class); |
| | | |
| | |
| | | .eq(DeviceEntity::getDeviceSn, entity.getDeviceSn())); |
| | | // Update the information directly if the device already exists. |
| | | if (deviceEntity != null) { |
| | | if (deviceEntity.getDeviceName().equals(entity.getNickname())) { |
| | | entity.setNickname(null); |
| | | } |
| | | entity.setId(deviceEntity.getId()); |
| | | mapper.updateById(entity); |
| | | return Optional.of(deviceEntity); |
| | | fillNullField(entity, deviceEntity); |
| | | return Optional.of(entity); |
| | | } |
| | | return mapper.insert(entity) > 0 ? Optional.of(entity) : Optional.empty(); |
| | | } |
| | | |
| | | private void fillNullField(DeviceEntity entity, DeviceEntity oldEntity) { |
| | | if (Objects.isNull(entity) || Objects.isNull(oldEntity)) { |
| | | return; |
| | | } |
| | | if (Objects.isNull(entity.getWorkspaceId())) { |
| | | entity.setWorkspaceId(oldEntity.getWorkspaceId()); |
| | | } |
| | | if (Objects.isNull(entity.getUserId())) { |
| | | entity.setUserId(oldEntity.getUserId()); |
| | | } |
| | | if (Objects.isNull(entity.getChildSn())) { |
| | | entity.setChildSn(oldEntity.getChildSn()); |
| | | } |
| | | if (Objects.isNull(entity.getBoundStatus())) { |
| | | entity.setBoundStatus(oldEntity.getBoundStatus()); |
| | | } |
| | | if (Objects.isNull(entity.getBoundTime())) { |
| | | entity.setBoundTime(oldEntity.getBoundTime()); |
| | | } |
| | | if (Objects.isNull(entity.getFirmwareVersion())) { |
| | | entity.setFirmwareVersion(oldEntity.getFirmwareVersion()); |
| | | } |
| | | if (Objects.isNull(entity.getDeviceIndex())) { |
| | | entity.setDeviceIndex(oldEntity.getDeviceIndex()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | // Query the model information of this gateway device. |
| | | Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService |
| | | .getOneDictionaryInfoByTypeSubType(gateway.getType(), gateway.getSubType()); |
| | | .getOneDictionaryInfoByTypeSubType(Objects.nonNull(gateway.getDomain()) ? |
| | | gateway.getDomain() : DeviceDomainEnum.GATEWAY.getVal(), |
| | | gateway.getType(), gateway.getSubType()); |
| | | |
| | | dictionaryOpt.ifPresent(entity -> |
| | | builder.deviceName(entity.getDeviceName()) |
| | |
| | | .version(gateway.getVersion()) |
| | | .domain(gateway.getDomain() != null ? |
| | | gateway.getDomain() : DeviceDomainEnum.GATEWAY.getVal()) |
| | | .deviceIndex(gateway.getSubDevices().isEmpty() ? null : gateway.getSubDevices().get(0).getIndex()) |
| | | .build(); |
| | | } |
| | | |
| | |
| | | |
| | | // Query the model information of this drone device. |
| | | Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService |
| | | .getOneDictionaryInfoByTypeSubType(device.getType(), device.getSubType()); |
| | | .getOneDictionaryInfoByTypeSubType(DeviceDomainEnum.SUB_DEVICE.getVal(), device.getType(), device.getSubType()); |
| | | |
| | | dictionaryOpt.ifPresent(dictionary -> |
| | | builder.deviceName(dictionary.getDeviceName()) |
| | |
| | | .deviceType(device.getType()) |
| | | .subType(device.getSubType()) |
| | | .version(device.getVersion()) |
| | | .deviceIndex(device.getIndex()) |
| | | .domain(device.getDomain() != null ? |
| | | device.getDomain() : DeviceDomainEnum.SUB_DEVICE.getVal()) |
| | | .domain(DeviceDomainEnum.SUB_DEVICE.getVal()) |
| | | .build(); |
| | | } |
| | | |
| | |
| | | if (entity == null) { |
| | | return null; |
| | | } |
| | | DeviceDTO.DeviceDTOBuilder deviceDTOBuilder = DeviceDTO.builder() |
| | | DeviceDTO deviceDTO = DeviceDTO.builder() |
| | | .deviceSn(entity.getDeviceSn()) |
| | | .childDeviceSn(entity.getChildSn()) |
| | | .deviceName(entity.getDeviceName()) |
| | | .deviceDesc(entity.getDeviceDesc()) |
| | | .deviceIndex(entity.getDeviceIndex()) |
| | | .controlSource(entity.getDeviceIndex()) |
| | | .workspaceId(entity.getWorkspaceId()) |
| | | .type(entity.getDeviceType()) |
| | | .subType(entity.getSubType()) |
| | | .domain(DeviceDomainEnum.getDesc(entity.getDomain())) |
| | | .domain(entity.getDomain()) |
| | | .iconUrl(IconUrlDTO.builder() |
| | | .normalUrl(entity.getUrlNormal()) |
| | | .selectUrl(entity.getUrlSelect()) |
| | |
| | | .firmwareVersion(entity.getFirmwareVersion()) |
| | | .workspaceName(entity.getWorkspaceId() != null ? |
| | | workspaceService.getWorkspaceByWorkspaceId(entity.getWorkspaceId()) |
| | | .map(WorkspaceDTO::getWorkspaceName).orElse("") : ""); |
| | | .map(WorkspaceDTO::getWorkspaceName).orElse("") : "") |
| | | .firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build(); |
| | | |
| | | addFirmwareStatus(deviceDTO, entity); |
| | | return deviceDTO; |
| | | } |
| | | |
| | | private void addFirmwareStatus(DeviceDTO deviceDTO, DeviceEntity entity) { |
| | | if (!StringUtils.hasText(entity.getFirmwareVersion())) { |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build(); |
| | | return; |
| | | } |
| | | // Query whether the device is updating firmware. |
| | | Object progress = redisOps.get(RedisConst.FIRMWARE_UPGRADING_PREFIX + entity.getDeviceSn()); |
| | | if (Objects.nonNull(progress)) { |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.UPGRADING.getVal()).firmwareProgress((int)progress).build(); |
| | | Optional<EventsReceiver<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>>> progressOpt = |
| | | deviceRedisService.getFirmwareUpgradingProgress(entity.getDeviceSn()); |
| | | if (progressOpt.isPresent()) { |
| | | deviceDTO.setFirmwareStatus(DeviceFirmwareStatusEnum.UPGRADING.getVal()); |
| | | deviceDTO.setFirmwareProgress(progressOpt.map(EventsReceiver::getOutput) |
| | | .map(EventsOutputProgressReceiver::getProgress) |
| | | .map(OutputProgressReceiver::getPercent) |
| | | .orElse(0)); |
| | | return; |
| | | } |
| | | |
| | | // First query the latest firmware version of the device model and compare it with the current firmware version |
| | | // to see if it needs to be upgraded. |
| | | Optional<DeviceFirmwareNoteDTO> firmwareReleaseNoteOpt = deviceFirmwareService.getLatestFirmwareReleaseNote(entity.getDeviceName()); |
| | | if (firmwareReleaseNoteOpt.isPresent()) { |
| | | DeviceFirmwareNoteDTO firmwareNoteDTO = firmwareReleaseNoteOpt.get(); |
| | | if (firmwareNoteDTO.getProductVersion().equals(entity.getFirmwareVersion())) { |
| | | return deviceDTOBuilder.firmwareStatus(entity.getCompatibleStatus() ? |
| | | DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal() : |
| | | DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE.getVal()).build(); |
| | | } |
| | | |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NORMAL_UPGRADE.getVal()).build(); |
| | | if (firmwareReleaseNoteOpt.isEmpty()) { |
| | | deviceDTO.setFirmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()); |
| | | return; |
| | | } |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build(); |
| | | if (entity.getFirmwareVersion().equals(firmwareReleaseNoteOpt.get().getProductVersion())) { |
| | | deviceDTO.setFirmwareStatus(Objects.requireNonNullElse(entity.getCompatibleStatus(), true) ? |
| | | DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal() : |
| | | DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE.getVal()); |
| | | return; |
| | | } |
| | | deviceDTO.setFirmwareStatus(DeviceFirmwareStatusEnum.NORMAL_UPGRADE.getVal()); |
| | | } |
| | | |
| | | @Override |
| | |
| | | device.setBoundTime(LocalDateTime.now()); |
| | | |
| | | boolean isUpd = this.saveDevice(this.deviceDTO2Entity(device)).isPresent(); |
| | | if (DeviceDomainEnum.DOCK.getDesc().equals(device.getDomain())) { |
| | | return isUpd; |
| | | } |
| | | if (!isUpd) { |
| | | return false; |
| | | } |
| | | |
| | | String key = RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(); |
| | | DeviceDTO redisDevice = (DeviceDTO)redisOps.get(key); |
| | | redisDevice.setWorkspaceId(device.getWorkspaceId()); |
| | | redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND); |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(device.getDeviceSn()); |
| | | if (deviceOpt.isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | if (DeviceDomainEnum.GATEWAY.getDesc().equals(redisDevice.getDomain())) { |
| | | DeviceDTO redisDevice = deviceOpt.get(); |
| | | redisDevice.setWorkspaceId(device.getWorkspaceId()); |
| | | deviceRedisService.setDeviceOnline(redisDevice); |
| | | |
| | | if (DeviceDomainEnum.GATEWAY.getVal() == redisDevice.getDomain()) { |
| | | this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()), |
| | | device.getDeviceSn(), device.getDeviceSn()); |
| | | } |
| | | if (DeviceDomainEnum.SUB_DEVICE.getDesc().equals(redisDevice.getDomain())) { |
| | | if (DeviceDomainEnum.SUB_DEVICE.getVal() == redisDevice.getDomain()) { |
| | | DeviceDTO subDevice = this.getDevicesByParams(DeviceQueryParam.builder() |
| | | .childSn(device.getChildDeviceSn()) |
| | | .build()).get(0); |
| | |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | /** |
| | | * Handle dock binding status requests. |
| | | * @param receiver |
| | | * @param headers |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_AIRPORT_BIND_STATUS, outputChannel = ChannelName.OUTBOUND) |
| | | public void bindStatus(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | List<Map<String, String>> data = ((Map<String, List<Map<String, String>>>) receiver.getData()).get(MapKeyConst.DEVICES); |
| | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | /** |
| | | * Handle dock binding requests. |
| | | * @param receiver |
| | | * @param headers |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND) |
| | | public void bindDevice(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | Map<String, List<BindDeviceReceiver>> data = objectMapper.convertValue(receiver.getData(), |
| | |
| | | } |
| | | } |
| | | |
| | | assert dock != null; |
| | | |
| | | Optional<DeviceEntity> dockEntityOpt = this.bindDevice2Entity(dock); |
| | | Optional<DeviceEntity> droneEntityOpt = this.bindDevice2Entity(drone); |
| | | Optional<DeviceEntity> dockEntityOpt = this.bindDevice2Entity(DeviceDomainEnum.DOCK.getVal(), dock); |
| | | Optional<DeviceEntity> droneEntityOpt = this.bindDevice2Entity(DeviceDomainEnum.SUB_DEVICE.getVal(), drone); |
| | | |
| | | List<ErrorInfoReply> bindResult = new ArrayList<>(); |
| | | |
| | |
| | | |
| | | @Override |
| | | public PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page, |
| | | Long pageSize, String domain) { |
| | | Long pageSize, Integer domain) { |
| | | |
| | | Page<DeviceEntity> pagination = mapper.selectPage(new Page<>(page, pageSize), |
| | | new LambdaQueryWrapper<DeviceEntity>() |
| | | .eq(DeviceEntity::getDomain, DeviceDomainEnum.getVal(domain)) |
| | | .eq(DeviceEntity::getDomain, domain) |
| | | .eq(DeviceEntity::getWorkspaceId, workspaceId) |
| | | .eq(DeviceEntity::getBoundStatus, true)); |
| | | List<DeviceDTO> devicesList = pagination.getRecords().stream().map(this::deviceEntityConvertToDTO) |
| | | .peek(device -> { |
| | | device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn())); |
| | | device.setStatus(deviceRedisService.checkDeviceOnline(device.getDeviceSn())); |
| | | if (StringUtils.hasText(device.getChildDeviceSn())) { |
| | | Optional<DeviceDTO> childOpt = this.getDeviceBySn(device.getChildDeviceSn()); |
| | | childOpt.ifPresent(child -> { |
| | | child.setStatus( |
| | | redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn())); |
| | | child.setStatus(deviceRedisService.checkDeviceOnline(child.getDeviceSn())); |
| | | child.setWorkspaceName(device.getWorkspaceName()); |
| | | device.setChildren(child); |
| | | }); |
| | |
| | | |
| | | @Override |
| | | public void unbindDevice(String deviceSn) { |
| | | String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn; |
| | | DeviceDTO redisDevice = (DeviceDTO) redisOps.get(key); |
| | | redisDevice.setWorkspaceId(""); |
| | | redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND); |
| | | |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceSn); |
| | | if (deviceOpt.isPresent()) { |
| | | subDeviceOffline(deviceSn); |
| | | } else { |
| | | deviceOpt = getDeviceBySn(deviceSn); |
| | | } |
| | | if (deviceOpt.isEmpty()) { |
| | | return; |
| | | } |
| | | DeviceDTO device = DeviceDTO.builder() |
| | | .deviceSn(deviceSn) |
| | | .workspaceId("") |
| | |
| | | return Optional.empty(); |
| | | } |
| | | DeviceDTO device = devicesList.get(0); |
| | | device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn)); |
| | | device.setStatus(deviceRedisService.checkDeviceOnline(sn)); |
| | | return Optional.of(device); |
| | | } |
| | | |
| | | @Override |
| | | /** |
| | | * Update the firmware version information of the device or payload. |
| | | * @param receiver |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_FIRMWARE_VERSION) |
| | | public void updateFirmwareVersion(FirmwareVersionReceiver receiver) { |
| | | // If the reported version is empty, it will not be processed to prevent misleading page. |
| | | if (!StringUtils.hasText(receiver.getFirmwareVersion())) { |
| | | return; |
| | | } |
| | | |
| | | if (receiver.getDomain() == DeviceDomainEnum.SUB_DEVICE) { |
| | | final DeviceDTO device = DeviceDTO.builder() |
| | | .deviceSn(receiver.getSn()) |
| | |
| | | |
| | | @Override |
| | | public ResponseResult createDeviceOtaJob(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) { |
| | | List<DeviceOtaCreateParam> deviceOtaFirmwares = deviceFirmwareService.getDeviceOtaFirmware(upgradeDTOS); |
| | | List<DeviceOtaCreateParam> deviceOtaFirmwares = deviceFirmwareService.getDeviceOtaFirmware(workspaceId, upgradeDTOS); |
| | | if (deviceOtaFirmwares.isEmpty()) { |
| | | return ResponseResult.error(); |
| | | } |
| | | |
| | | DeviceOtaCreateParam deviceOtaFirmware = deviceOtaFirmwares.get(0); |
| | | List<DeviceDTO> devices = getDevicesByParams(DeviceQueryParam.builder().childSn(deviceOtaFirmware.getSn()).build()); |
| | | String gatewaySn = devices.isEmpty() ? deviceOtaFirmware.getSn() : devices.get(0).getDeviceSn(); |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceOtaFirmwares.get(0).getSn()); |
| | | if (deviceOpt.isEmpty()) { |
| | | throw new RuntimeException("设备离线"); |
| | | } |
| | | DeviceDTO device = deviceOpt.get(); |
| | | String gatewaySn = DeviceDomainEnum.DOCK.getVal() == device.getDomain() ? device.getDeviceSn() : device.getParentSn(); |
| | | |
| | | String topic = THING_MODEL_PRE + PRODUCT + gatewaySn + SERVICES_SUF; |
| | | checkOtaConditions(gatewaySn); |
| | | |
| | | // The bids in the progress messages reported subsequently are the same. |
| | | String bid = UUID.randomUUID().toString(); |
| | | Optional<ServiceReply> serviceReplyOpt = messageSender.publishWithReply( |
| | | topic, CommonTopicResponse.<Map<String, List<DeviceOtaCreateParam>>>builder() |
| | | .tid(UUID.randomUUID().toString()) |
| | | .bid(bid) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .method(ServicesMethodEnum.OTA_CREATE.getMethod()) |
| | | .data(Map.of(MapKeyConst.DEVICES, deviceOtaFirmwares)) |
| | | .build()); |
| | | if (serviceReplyOpt.isEmpty()) { |
| | | return ResponseResult.error("No message reply received."); |
| | | } |
| | | ServiceReply serviceReply = serviceReplyOpt.get(); |
| | | ServiceReply serviceReply = messageSender.publishServicesTopic( |
| | | gatewaySn, FirmwareMethodEnum.OTA_CREATE.getMethod(), Map.of(MapKeyConst.DEVICES, deviceOtaFirmwares), bid); |
| | | if (serviceReply.getResult() != ResponseResult.CODE_SUCCESS) { |
| | | return ResponseResult.error(serviceReply.getResult(), "Firmware Error Code: " + serviceReply.getResult()); |
| | | return ResponseResult.error(serviceReply.getResult(), "硬件错误码 " + serviceReply.getResult()); |
| | | } |
| | | if (ServicesMethodEnum.OTA_CREATE.getProgress()) { |
| | | // Record the device state that needs to be updated. |
| | | deviceOtaFirmwares.forEach(deviceOta -> redisOps.setWithExpire( |
| | | RedisConst.FIRMWARE_UPGRADING_PREFIX + deviceOta.getSn(), |
| | | bid, |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND)); |
| | | } |
| | | |
| | | // Record the device state that needs to be updated. |
| | | deviceOtaFirmwares.forEach(deviceOta -> deviceRedisService.setFirmwareUpgrading(deviceOta.getSn(), |
| | | EventsReceiver.<EventsOutputProgressReceiver<FirmwareProgressExtReceiver>>builder() |
| | | .bid(bid).sn(deviceOta.getSn()).build())); |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | /** |
| | | * Determine whether the firmware can be upgraded. |
| | | * @param dockSn |
| | | */ |
| | | private void checkOtaConditions(String dockSn) { |
| | | Optional<OsdDockReceiver> deviceOpt = deviceRedisService.getDeviceOsd(dockSn, OsdDockReceiver.class); |
| | | if (deviceOpt.isEmpty()) { |
| | | throw new RuntimeException("机场离线"); |
| | | } |
| | | boolean emergencyStopState = deviceOpt.get().getEmergencyStopState(); |
| | | if (emergencyStopState) { |
| | | // throw new RuntimeException("The emergency stop button of the dock is pressed and can't be upgraded."); |
| | | throw new RuntimeException("机场急停按钮被按下,无法升级"); |
| | | } |
| | | |
| | | DockModeCodeEnum dockMode = this.getDockMode(dockSn); |
| | | if (DockModeCodeEnum.IDLE != dockMode) { |
| | | throw new RuntimeException("当前机场状态无法升级"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void devicePropertySet(String workspaceId, String dockSn, DeviceSetPropertyEnum propertyEnum, JsonNode param) { |
| | | Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(dockSn); |
| | | if (dockOpt.isEmpty()) { |
| | | throw new RuntimeException("机场离线"); |
| | | } |
| | | String childSn = dockOpt.get().getChildDeviceSn(); |
| | | boolean deviceOnline = deviceRedisService.checkDeviceOnline(childSn); |
| | | Optional<OsdSubDeviceReceiver> osdOpt = deviceRedisService.getDeviceOsd(childSn, OsdSubDeviceReceiver.class); |
| | | if (!deviceOnline || osdOpt.isEmpty()) { |
| | | throw new RuntimeException("设备离线"); |
| | | } |
| | | |
| | | // Make sure the data is valid. |
| | | BasicDeviceProperty basicDeviceProperty = objectMapper.convertValue(param, propertyEnum.getClazz()); |
| | | boolean valid = basicDeviceProperty.valid(); |
| | | if (!valid) { |
| | | throw new IllegalArgumentException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg()); |
| | | } |
| | | |
| | | String topic = THING_MODEL_PRE + PRODUCT + dockSn + PROPERTY_SUF + SET_SUF; |
| | | if (!param.isObject()) { |
| | | this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param)); |
| | | return; |
| | | } |
| | | // If there are multiple parameters, set them separately. |
| | | for (Iterator<Map.Entry<String, JsonNode>> filed = param.fields(); filed.hasNext(); ) { |
| | | Map.Entry<String, JsonNode> node = filed.next(); |
| | | boolean isPublish = basicDeviceProperty.canPublish(node.getKey(), osdOpt.get()); |
| | | if (!isPublish) { |
| | | continue; |
| | | } |
| | | this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), node)); |
| | | } |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void deviceOnePropertySet(String topic, DeviceSetPropertyEnum propertyEnum, Map.Entry<String, Object> value) { |
| | | if (Objects.isNull(value) || Objects.isNull(value.getValue())) { |
| | | throw new IllegalArgumentException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg()); |
| | | } |
| | | |
| | | Map reply = messageSender.publishWithReply( |
| | | Map.class, topic, |
| | | CommonTopicResponse.builder() |
| | | .bid(UUID.randomUUID().toString()) |
| | | .tid(UUID.randomUUID().toString()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data(value) |
| | | .build()); |
| | | |
| | | while (true) { |
| | | reply = (Map<String, Object>) reply.get(value.getKey()); |
| | | if (value.getValue() instanceof JsonNode) { |
| | | break; |
| | | } |
| | | value = (Map.Entry) value.getValue(); |
| | | } |
| | | |
| | | SetReply setReply = objectMapper.convertValue(reply, SetReply.class); |
| | | if (SetReplyStatusResultEnum.SUCCESS.getVal() != setReply.getResult()) { |
| | | throw new RuntimeException("设置失败" + value.getKey() + "; 错误码: " + setReply.getResult()); |
| | | } |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public DockModeCodeEnum getDockMode(String dockSn) { |
| | | return deviceRedisService.getDeviceOsd(dockSn, OsdDockReceiver.class) |
| | | .map(OsdDockReceiver::getModeCode).orElse(DockModeCodeEnum.DISCONNECTED); |
| | | } |
| | | |
| | | @Override |
| | | public DeviceModeCodeEnum getDeviceMode(String deviceSn) { |
| | | return deviceRedisService.getDeviceOsd(deviceSn, OsdSubDeviceReceiver.class) |
| | | .map(OsdSubDeviceReceiver::getModeCode).orElse(DeviceModeCodeEnum.DISCONNECTED); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean checkDockDrcMode(String dockSn) { |
| | | return deviceRedisService.getDeviceOsd(dockSn, OsdDockReceiver.class) |
| | | .map(OsdDockReceiver::getDrcState) |
| | | .orElse(DockDrcStateEnum.DISCONNECTED) != DockDrcStateEnum.DISCONNECTED; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean checkAuthorityFlight(String gatewaySn) { |
| | | return deviceRedisService.getDeviceOnline(gatewaySn).flatMap(gateway -> |
| | | Optional.of((DeviceDomainEnum.DOCK.getVal() == gateway.getDomain() |
| | | || DeviceDomainEnum.GATEWAY.getVal() == gateway.getDomain()) |
| | | && ControlSourceEnum.A.getControlSource().equals(gateway.getControlSource()))) |
| | | .orElse(true); |
| | | } |
| | | |
| | | /** |
| | |
| | | .boundTime(dto.getBoundTime() != null ? |
| | | dto.getBoundTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null) |
| | | .childSn(dto.getChildDeviceSn()) |
| | | .domain(StringUtils.hasText(dto.getDomain()) ? DeviceDomainEnum.getVal(dto.getDomain()) : null) |
| | | .domain(dto.getDomain()) |
| | | .firmwareVersion(dto.getFirmwareVersion()) |
| | | .compatibleStatus(dto.getFirmwareStatus() == null ? null : |
| | | DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE != DeviceFirmwareStatusEnum.find(dto.getFirmwareStatus())) |
| | |
| | | |
| | | /** |
| | | * Convert device binding data object into database entity object. |
| | | * |
| | | * @param domain |
| | | * @param receiver |
| | | * @return |
| | | */ |
| | | private Optional<DeviceEntity> bindDevice2Entity(BindDeviceReceiver receiver) { |
| | | private Optional<DeviceEntity> bindDevice2Entity(Integer domain, BindDeviceReceiver receiver) { |
| | | if (receiver == null) { |
| | | return Optional.empty(); |
| | | } |
| | | int[] droneKey = Arrays.stream(receiver.getDeviceModelKey().split("-")).mapToInt(Integer::parseInt).toArray(); |
| | | Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService.getOneDictionaryInfoByTypeSubType(droneKey[1], droneKey[2]); |
| | | Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService.getOneDictionaryInfoByTypeSubType(domain, droneKey[1], droneKey[2]); |
| | | DeviceEntity.DeviceEntityBuilder builder = DeviceEntity.builder(); |
| | | |
| | | dictionaryOpt.ifPresent(entity -> |
| | |
| | | .organizationName(device.getWorkspaceName()) |
| | | .build(); |
| | | } |
| | | } |
| | | |
| | | private Optional<DeviceEntity> onlineSaveDevice(DeviceEntity device, String childSn, String parentSn) { |
| | | |
| | | Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(device.getDeviceSn()); |
| | | if (deviceOpt.isEmpty()) { |
| | | // Set the icon of the gateway device displayed in the pilot's map, required in the TSA module. |
| | | device.setUrlNormal(IconUrlEnum.NORMAL_PERSON.getUrl()); |
| | | // Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module. |
| | | device.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl()); |
| | | device.setBoundStatus(false); |
| | | } else { |
| | | DeviceDTO oldDevice = deviceOpt.get(); |
| | | device.setNickname(oldDevice.getNickname()); |
| | | device.setBoundStatus(oldDevice.getBoundStatus()); |
| | | } |
| | | |
| | | device.setChildSn(childSn); |
| | | device.setLoginTime(System.currentTimeMillis()); |
| | | |
| | | Optional<DeviceEntity> saveDeviceOpt = this.saveDevice(device); |
| | | if (saveDeviceOpt.isEmpty()) { |
| | | return saveDeviceOpt; |
| | | } |
| | | |
| | | DeviceDTO redisDevice = this.deviceEntityConvertToDTO(saveDeviceOpt.get()); |
| | | redisDevice.setParentSn(parentSn); |
| | | |
| | | deviceRedisService.setDeviceOnline(redisDevice); |
| | | |
| | | return saveDeviceOpt; |
| | | } |
| | | |
| | | /** |
| | | * Handles messages in the state topic about basic drone data. |
| | | * |
| | | * Note: Only the data of the drone payload is handled here. You can handle other data from the drone |
| | | * according to your business needs. |
| | | * @param deviceBasic basic drone data |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC, outputChannel = ChannelName.INBOUND_STATE_PAYLOAD) |
| | | public List<DevicePayloadReceiver> stateBasic(DeviceBasicReceiver deviceBasic) { |
| | | Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceBasic.getDeviceSn()); |
| | | if (deviceOpt.isEmpty()) { |
| | | return deviceBasic.getPayloads(); |
| | | } |
| | | Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(deviceOpt.get().getParentSn()); |
| | | if (dockOpt.isEmpty()) { |
| | | return deviceBasic.getPayloads(); |
| | | } |
| | | DeviceDTO dock = dockOpt.get(); |
| | | if (!deviceBasic.getControlSource().equals(dock.getControlSource())) { |
| | | dock.setControlSource(deviceBasic.getControlSource()); |
| | | deviceRedisService.setDeviceOnline(dock); |
| | | |
| | | sendMessageService.sendBatch(dock.getWorkspaceId(), UserTypeEnum.WEB.getVal(), |
| | | BizCodeEnum.CONTROL_SOURCE_CHANGE.getCode(), |
| | | DeviceAuthorityDTO.builder() |
| | | .controlSource(dock.getControlSource()) |
| | | .sn(dock.getDeviceSn()) |
| | | .type(DroneAuthorityEnum.FLIGHT) |
| | | .build()); |
| | | |
| | | } |
| | | return deviceBasic.getPayloads(); |
| | | } |
| | | } |