From 39ffdf5754b4ebca682bd3c925f7a500e8a1bbda Mon Sep 17 00:00:00 2001
From: aix <vip_xiaobin810@163.com>
Date: Thu, 08 Aug 2024 16:56:36 +0800
Subject: [PATCH] 国土调查云身份凭证token

---
 src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java |  387 +++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 265 insertions(+), 122 deletions(-)

diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
index 6677ca8..1aebd88 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
@@ -17,6 +17,7 @@
 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;
@@ -25,6 +26,9 @@
 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;
@@ -92,6 +96,15 @@
     private IDeviceFirmwareService deviceFirmwareService;
 
     @Autowired
+    private ICapacityCameraService capacityCameraService;
+
+    @Autowired
+    private IDeviceRedisService deviceRedisService;
+
+    @Autowired
+    private IWaylineJobService waylineJobService;
+
+    @Autowired
     @Qualifier("gatewayOSDServiceImpl")
     private ITSAService tsaService;
 
@@ -104,24 +117,23 @@
         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 = RedisOpsUtils.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();
-                RedisOpsUtils.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
+                value.setChildDeviceSn(null);
+                deviceRedisService.setDeviceOnline(value);
                 this.pushDeviceOnlineTopo(value.getWorkspaceId(), gatewaySn, gatewaySn);
                 return true;
             }
 
             // When connecting for the first time
             DeviceEntity gatewayDevice = deviceGatewayConvertToDeviceEntity(gateway);
-            return onlineSaveDevice(gatewayDevice, null).isPresent();
+            return onlineSaveDevice(gatewayDevice, null, null).isPresent();
         }
 
-        DeviceDTO deviceDTO = (DeviceDTO) (RedisOpsUtils.get(key));
+        DeviceDTO deviceDTO = deviceOpt.get();
         String deviceSn = deviceDTO.getChildDeviceSn();
         if (!StringUtils.hasText(deviceSn)) {
             return true;
@@ -134,22 +146,22 @@
     public Boolean subDeviceOffline(String deviceSn) {
 
         // If no information about this device exists in the cache, the drone is considered to be offline.
-        String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
-        if (!RedisOpsUtils.checkExist(key) || RedisOpsUtils.getExpire(key) <= 0) {
+        Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(deviceSn);
+        if (deviceOpt.isEmpty()) {
             log.debug("The drone is already offline.");
             return true;
         }
-        DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(key);
+        DeviceDTO device = deviceOpt.get();
         // Cancel drone-related subscriptions.
         this.unsubscribeTopicOffline(deviceSn);
 
-        payloadService.deletePayloadsByDeviceSn(new ArrayList<>(List.of(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);
 
-        RedisOpsUtils.del(key);
-        RedisOpsUtils.del(RedisConst.OSD_PREFIX + device.getDeviceSn());
-        RedisOpsUtils.del(RedisConst.HMS_PREFIX + device.getDeviceSn());
         log.debug("{} offline.", deviceSn);
         return true;
     }
@@ -157,13 +169,11 @@
     @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 = RedisOpsUtils.getExpire(key);
-        long gatewayTime = RedisOpsUtils.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn());
 
-        if (time > 0 && gatewayTime > 0) {
-            RedisOpsUtils.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())
@@ -171,7 +181,7 @@
                     .childDeviceSn(deviceSn).build();
             this.updateDevice(gateway);
             this.updateDevice(device);
-            String workspaceId = ((DeviceDTO)(RedisOpsUtils.get(key))).getWorkspaceId();
+            String workspaceId = deviceOpt.get().getWorkspaceId();
             if (StringUtils.hasText(workspaceId)) {
                 this.subscribeTopicOnline(deviceSn);
                 this.subscribeTopicOnline(deviceGateway.getSn());
@@ -193,14 +203,14 @@
                 });
 
         DeviceEntity gateway = deviceGatewayConvertToDeviceEntity(deviceGateway);
-        Optional<DeviceEntity> gatewayEntityOpt = onlineSaveDevice(gateway, deviceSn);
+        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));
-        Optional<DeviceEntity> subDeviceEntityOpt = onlineSaveDevice(subDevice, null);
+        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;
@@ -275,10 +285,13 @@
     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()),
@@ -291,6 +304,7 @@
                         .eq(StringUtils.hasText(param.getWorkspaceId()),
                                 DeviceEntity::getWorkspaceId, param.getWorkspaceId())
                         .eq(param.getBoundStatus() != null, DeviceEntity::getBoundStatus, param.getBoundStatus())
+                        .eq(param.getReserveId() != null, DeviceEntity::getReserveId, param.getReserveId())
                         .orderBy(param.isOrderBy(),
                                 param.isAsc(), DeviceEntity::getId))
                 .stream()
@@ -299,17 +313,29 @@
     }
 
     @Override
-    public List<DeviceDTO> getDevicesTopoForWeb(String workspaceId) {
+    public List<DeviceDTO> getDevicesTopoForWeb(String workspaceId, String reserveId) {
         List<DeviceDTO> devicesList = this.getDevicesByParams(
                 DeviceQueryParam.builder()
                         .workspaceId(workspaceId)
+                        .reserveId(reserveId)
                         .domains(List.of(DeviceDomainEnum.GATEWAY.getVal(), DeviceDomainEnum.DOCK.getVal()))
                         .build());
 
         devicesList.stream()
                 .filter(gateway -> DeviceDomainEnum.DOCK.getVal() == gateway.getDomain() ||
-                        RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn()))
+                        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);
+            deviceDTO.setOnlineStatus(true);
+            OsdDockReceiver osdDockReceiver = (OsdDockReceiver) RedisOpsUtils.get("osd:" + deviceDTO.getDeviceSn());
+            deviceDTO.setLatitude(osdDockReceiver!=null? osdDockReceiver.getLatitude():null);
+            deviceDTO.setLongitude(osdDockReceiver!=null? osdDockReceiver.getLongitude():null);
+        });
 
         return devicesList;
     }
@@ -317,7 +343,7 @@
     @Override
     public void spliceDeviceTopo(DeviceDTO gateway) {
 
-        gateway.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn()));
+        gateway.setStatus(deviceRedisService.checkDeviceOnline(gateway.getDeviceSn()));
 
         // sub device
         if (!StringUtils.hasText(gateway.getChildDeviceSn())) {
@@ -325,7 +351,7 @@
         }
 
         DeviceDTO subDevice = getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()).get(0);
-        subDevice.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + subDevice.getDeviceSn()));
+        subDevice.setStatus(deviceRedisService.checkDeviceOnline(subDevice.getDeviceSn()));
         gateway.setChildren(subDevice);
 
         // payloads
@@ -362,8 +388,7 @@
 
         this.getDeviceTopoForPilot(sn)
                 .ifPresent(pilotMessage::setData);
-        boolean exist = RedisOpsUtils.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);
@@ -383,7 +408,7 @@
                             .key(device.getDomain() + "-" + device.getType() + "-" + device.getSubType())
                             .build())
                     .iconUrls(device.getIconUrl())
-                    .onlineStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
+                    .onlineStatus(deviceRedisService.checkDeviceOnline(device.getDeviceSn()))
                     .boundStatus(device.getBoundStatus())
                     .model(device.getDeviceName())
                     .userId(device.getUserId())
@@ -427,25 +452,24 @@
             String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(),
                     topic.indexOf(OSD_SUF));
 
-            // Real-time update of device status in memory
-            RedisOpsUtils.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND);
+            Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(from);
 
-            DeviceDTO device = (DeviceDTO) RedisOpsUtils.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("请重新启动无人机.");
                     return;
                 }
-                device = deviceOpt.get();
-                if (!StringUtils.hasText(device.getWorkspaceId())) {
+
+                if (!StringUtils.hasText(deviceOpt.get().getWorkspaceId())) {
                     this.unsubscribeTopicOffline(from);
                     return;
                 }
-                RedisOpsUtils.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);
 
@@ -516,9 +540,37 @@
             }
             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());
+        }
     }
 
     /**
@@ -550,6 +602,7 @@
                 .version(gateway.getVersion())
                 .domain(gateway.getDomain() != null ?
                         gateway.getDomain() : DeviceDomainEnum.GATEWAY.getVal())
+                .deviceIndex(gateway.getSubDevices().isEmpty() ? null : gateway.getSubDevices().get(0).getIndex())
                 .build();
     }
 
@@ -578,7 +631,6 @@
                 .deviceType(device.getType())
                 .subType(device.getSubType())
                 .version(device.getVersion())
-                .deviceIndex(device.getIndex())
                 .domain(DeviceDomainEnum.SUB_DEVICE.getVal())
                 .build();
     }
@@ -592,12 +644,12 @@
         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())
@@ -617,31 +669,43 @@
                 .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 = RedisOpsUtils.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
@@ -661,14 +725,14 @@
             return false;
         }
 
-        String key = RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn();
-        if (!RedisOpsUtils.checkExist(key)) {
+        Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(device.getDeviceSn());
+        if (deviceOpt.isEmpty()) {
             return false;
         }
 
-        DeviceDTO redisDevice = (DeviceDTO)RedisOpsUtils.get(key);
+        DeviceDTO redisDevice = deviceOpt.get();
         redisDevice.setWorkspaceId(device.getWorkspaceId());
-        RedisOpsUtils.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
+        deviceRedisService.setDeviceOnline(redisDevice);
 
         if (DeviceDomainEnum.GATEWAY.getVal() == redisDevice.getDomain()) {
             this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()),
@@ -686,7 +750,11 @@
         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);
@@ -715,7 +783,11 @@
 
     }
 
-    @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(),
@@ -732,8 +804,6 @@
                 drone = device;
             }
         }
-
-        assert dock != null;
 
         Optional<DeviceEntity> dockEntityOpt = this.bindDevice2Entity(DeviceDomainEnum.DOCK.getVal(), dock);
         Optional<DeviceEntity> droneEntityOpt = this.bindDevice2Entity(DeviceDomainEnum.SUB_DEVICE.getVal(), drone);
@@ -780,12 +850,11 @@
                         .eq(DeviceEntity::getBoundStatus, true));
         List<DeviceDTO> devicesList = pagination.getRecords().stream().map(this::deviceEntityConvertToDTO)
                 .peek(device -> {
-                    device.setStatus(RedisOpsUtils.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(
-                                    RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn()));
+                            child.setStatus(deviceRedisService.checkDeviceOnline(child.getDeviceSn()));
                             child.setWorkspaceName(device.getWorkspaceName());
                             device.setChildren(child);
                         });
@@ -797,11 +866,16 @@
 
     @Override
     public void unbindDevice(String deviceSn) {
-        String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
-        DeviceDTO redisDevice = (DeviceDTO) RedisOpsUtils.get(key);
-        redisDevice.setWorkspaceId("");
-        RedisOpsUtils.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("")
@@ -818,11 +892,14 @@
             return Optional.empty();
         }
         DeviceDTO device = devicesList.get(0);
-        device.setStatus(RedisOpsUtils.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.
@@ -851,44 +928,61 @@
             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();
-        ServiceReply serviceReply = messageSender.publishWithReply(
-                topic, CommonTopicResponse.<Map<String, List<DeviceOtaCreateParam>>>builder()
-                        .tid(UUID.randomUUID().toString())
-                        .bid(bid)
-                        .timestamp(System.currentTimeMillis())
-                        .method(FirmwareMethodEnum.OTA_CREATE.getMethod())
-                        .data(Map.of(MapKeyConst.DEVICES, deviceOtaFirmwares))
-                        .build());
+        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());
         }
 
         // Record the device state that needs to be updated.
-        deviceOtaFirmwares.forEach(deviceOta -> RedisOpsUtils.setWithExpire(
-                RedisConst.FIRMWARE_UPGRADING_PREFIX + deviceOta.getSn(),
-                bid,
-                RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND));
+        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) {
-        boolean dockOnline = this.checkDeviceOnline(dockSn);
-        if (!dockOnline) {
-            throw new RuntimeException("Dock is offline.");
+        Optional<DeviceDTO> dockOpt = deviceRedisService.getDeviceOnline(dockSn);
+        if (dockOpt.isEmpty()) {
+            throw new RuntimeException("机场离线");
         }
-        DeviceDTO deviceDTO = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn);
-        boolean deviceOnline = this.checkDeviceOnline(deviceDTO.getChildDeviceSn());
-        if (!deviceOnline) {
-            throw new RuntimeException("Device is offline.");
+        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.
@@ -899,7 +993,6 @@
         }
 
         String topic = THING_MODEL_PRE + PRODUCT + dockSn + PROPERTY_SUF + SET_SUF;
-        OsdSubDeviceReceiver osd = (OsdSubDeviceReceiver) RedisOpsUtils.get(RedisConst.OSD_PREFIX + deviceDTO.getChildDeviceSn());
         if (!param.isObject()) {
             this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param));
             return;
@@ -907,7 +1000,7 @@
         // 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(), osd);
+            boolean isPublish = basicDeviceProperty.canPublish(node.getKey(), osdOpt.get());
             if (!isPublish) {
                 continue;
             }
@@ -929,8 +1022,7 @@
                         .tid(UUID.randomUUID().toString())
                         .timestamp(System.currentTimeMillis())
                         .data(value)
-                        .build(),
-                2);
+                        .build());
 
         while (true) {
             reply = (Map<String, Object>) reply.get(value.getKey());
@@ -942,14 +1034,37 @@
 
         SetReply setReply = objectMapper.convertValue(reply, SetReply.class);
         if (SetReplyStatusResultEnum.SUCCESS.getVal() != setReply.getResult()) {
-            throw new RuntimeException("Failed to set " + value.getKey() + "; Error Code: " + setReply.getResult());
+            throw new RuntimeException("设置失败" + value.getKey() + "; 错误码: " + setReply.getResult());
         }
 
     }
 
-    public Boolean checkDeviceOnline(String sn) {
-        String key = RedisConst.DEVICE_ONLINE_PREFIX + sn;
-        return RedisOpsUtils.checkExist(key) && RedisOpsUtils.getExpire(key) > 0;
+    @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);
     }
 
     /**
@@ -1038,7 +1153,7 @@
                 .build();
     }
 
-    private Optional<DeviceEntity> onlineSaveDevice(DeviceEntity device, String childSn) {
+    private Optional<DeviceEntity> onlineSaveDevice(DeviceEntity device, String childSn, String parentSn) {
 
         Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(device.getDeviceSn());
         if (deviceOpt.isEmpty()) {
@@ -1060,19 +1175,47 @@
         if (saveDeviceOpt.isEmpty()) {
             return saveDeviceOpt;
         }
-        device.setWorkspaceId(saveDeviceOpt.get().getWorkspaceId());
 
-        RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(),
-                DeviceDTO.builder()
-                        .deviceSn(device.getDeviceSn())
-                        .workspaceId(device.getWorkspaceId())
-                        .childDeviceSn(childSn)
-                        .domain(device.getDomain())
-                        .type(device.getDeviceType())
-                        .subType(device.getSubType())
-                        .build(),
-                RedisConst.DEVICE_ALIVE_SECOND);
+        DeviceDTO redisDevice = this.deviceEntityConvertToDTO(saveDeviceOpt.get());
+        redisDevice.setParentSn(parentSn);
+
+        deviceRedisService.setDeviceOnline(redisDevice);
 
         return saveDeviceOpt;
     }
-}
\ No newline at end of file
+
+    /**
+     * 处理关于基本无人机数据的状态主题的消息。
+     * 注:这里只处理无人机有效载荷的数据。你可以处理无人机的其他数据
+     * *根据您的业务需要。
+     * @param deviceBasic   无人机基本数据
+     */
+    @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC, outputChannel = ChannelName.INBOUND_STATE_PAYLOAD)
+    public List<DevicePayloadReceiver> stateBasic(DeviceBasicReceiver deviceBasic) {
+        log.info("无人机数据的状态主题的消息--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();
+        log.info("redis dockOpt:{}",dockOpt);
+        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();
+    }
+}

--
Gitblit v1.9.3