Browse Source

单点登录 流媒体

S0025136190 1 year ago
parent
commit
b5ecff144f

+ 2 - 2
Backend/cloud-sdk/src/main/java/com/dji/sdk/common/AMap.java

@@ -23,8 +23,8 @@ public class AMap {
         this.latitude = wgLat;
     }
 
-
-
+    public AMap() {
+    }
 
     @Override
     public String toString() {

+ 46 - 13
Backend/sample/src/main/java/com/dji/sample/common/smsp/CallSmsp.java

@@ -3,6 +3,9 @@ package com.dji.sample.common.smsp;
 import cn.hutool.crypto.digest.MD5;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
+import com.dji.sample.manage.model.dto.ManageDeviceLivestreamUrlDTO;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
@@ -10,11 +13,19 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
 
+import java.time.Instant;
+import java.util.ArrayList;
+
+import static com.dji.sample.configuration.CustomConfiguration.smspRtmpUrl;
+import static com.dji.sample.configuration.CustomConfiguration.smspTokenUrl;
+
 @Slf4j
 public class CallSmsp {
     public static String getSmspToken(String username,String password) {
-        String pass = MD5.create().digestHex(password);
-        String url = "https://smsp.jkec.info:4443/api/v1/login?_t=1722393429&username="+username+"&password="+pass;
+//        String pass = MD5.create().digestHex(password);
+//        Instant now = Instant.now();
+//        long currentTimeMillis = now.toEpochMilli();
+        String url = smspTokenUrl+"?username="+username+"&password="+password;
         try {
             String response = sendGetRequest(url);
             log.debug("Response from API: " + response);
@@ -27,23 +38,45 @@ public class CallSmsp {
         }
     }
 
-    public static String getRtmp(String token,String deviceSn) {
-        String url = "https://smsp.jkec.info:4443/api/v1/channelstream/all?token="+token;
+    public static ManageDeviceLivestreamUrlDTO getRtmp(String token, String deviceSn,String payload) {
+        ManageDeviceLivestreamUrlDTO resultDto = new ManageDeviceLivestreamUrlDTO();
+        if(token == null) {
+            return resultDto;
+        }
+        String url = smspRtmpUrl+"?token="+token;
+        ObjectMapper objectMapper = new ObjectMapper();
         try {
             String response = sendGetRequest(url);
             log.debug("Response from API: " + response);
-            JSONObject json = new JSONObject(response);
-            JSONArray dataArray = json.getJSONArray("data");
-            for (int i = 0; i < dataArray.size(); i++) {
-                JSONObject dataObject = dataArray.getJSONObject(i);
-                if (deviceSn.equals(dataObject.getStr("ChannelName"))) {
-                    return dataObject.getStr("RTMP");
+            JsonNode rootNode = objectMapper.readTree(response);
+            // 遍历顶层的设备列表
+            for (JsonNode deviceNode : rootNode.get("data")) {
+                String deviceName = deviceNode.get("DeviceName").asText();
+                // 查找特定设备名
+                if (deviceSn.equals(deviceName)) {
+                    // 获取该设备的子节点
+                    JsonNode childrenNode = deviceNode.get("Children");
+                    // 遍历子节点
+                    for (JsonNode childNode : childrenNode) {
+                        String channelId = childNode.get("ChannelID").asText();
+                        // 查找特定子设备名
+                        if (payload.equals(channelId)) {
+                            // 获取RTMP和WEBRTC数据
+                            String rtmpUrl = childNode.get("RTMP").asText();
+                            String webRtcUrl = childNode.get("WEBRTC").asText();
+                            Integer sid = childNode.get("Sid").asInt();
+                            resultDto.setChannelId(sid);
+                            resultDto.setRtmpUrl(rtmpUrl);
+                            resultDto.setWebRtcUrl(webRtcUrl);
+
+                        }
+                    }
                 }
             }
-            return null;
+            return resultDto;
         } catch (Exception e) {
             e.printStackTrace();
-            return null;
+            return resultDto;
         }
     }
 
@@ -56,7 +89,7 @@ public class CallSmsp {
             if (statusCode == 200) {
                 return EntityUtils.toString(response.getEntity());
             } else {
-                throw new RuntimeException("Failed : HTTP error code : " + statusCode);
+                throw new RuntimeException("Failed : 流媒体平台错误 : " + statusCode);
             }
         } finally {
             response.close();

+ 25 - 4
Backend/sample/src/main/java/com/dji/sample/configuration/CustomConfiguration.java

@@ -24,16 +24,25 @@ public class CustomConfiguration {
      */
     public static String key;
 
-    public void setSignKey(String signKey) {
-        CustomConfiguration.signKey = signKey;
-    }
 
     /**
      * 加密密钥
-     * @param frequency
+     * @param signKey
      */
     public static String signKey;
 
+    /**
+     * 获取token地址
+     * @param smspTokenUrl
+     */
+    public static String smspTokenUrl;
+
+    /**
+     * 获取URL地址
+     * @param smspRtmpUrl
+     */
+    public static String smspRtmpUrl;
+
     public void setFrequency(int frequency) {
         CustomConfiguration.frequency = frequency;
     }
@@ -41,6 +50,18 @@ public class CustomConfiguration {
     public void setKey(String key) {
         CustomConfiguration.key = key;
     }
+
+    public void setSignKey(String signKey) {
+        CustomConfiguration.signKey = signKey;
+    }
+
+    public void setSmspTokenUrl(String smspTokenUrl) {
+        CustomConfiguration.smspTokenUrl = smspTokenUrl;
+    }
+
+    public void setSmspRtmpUrl(String smspRtmpUrl) {
+        CustomConfiguration.smspRtmpUrl = smspRtmpUrl;
+    }
 }
 
 

+ 6 - 0
Backend/sample/src/main/java/com/dji/sample/manage/controller/LoginController.java

@@ -1,6 +1,7 @@
 package com.dji.sample.manage.controller;
 
 import com.dji.sample.common.error.CommonErrorEnum;
+import com.dji.sample.manage.model.dto.SignLoginDTO;
 import com.dji.sample.manage.model.dto.UserDTO;
 import com.dji.sample.manage.model.dto.UserLoginDTO;
 import com.dji.sample.manage.service.IUserService;
@@ -56,4 +57,9 @@ public class LoginController {
 
         return HttpResultResponse.success(user.get());
     }
+
+    @PostMapping("/signLogin")
+    public HttpResultResponse signLogin(@RequestBody SignLoginDTO loginDTO) {
+        return userService.userLogin(loginDTO);
+    }
 }

+ 7 - 1
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/ManageDeviceLivestreamUrlDTO.java

@@ -24,9 +24,15 @@ public class ManageDeviceLivestreamUrlDTO {
 
     private String payload;
 
+    private Integer payloadIndex;
+
     private Integer urlType;
 
     private Integer subType;
 
-    private String url;
+    private Integer channelId;
+
+    private String rtmpUrl;
+
+    private String webRtcUrl;
 }

+ 31 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/SignLoginDTO.java

@@ -0,0 +1,31 @@
+package com.dji.sample.manage.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class
+SignLoginDTO {
+
+    @NonNull
+    private String username;
+
+    @NonNull
+    private String client_id;
+
+    @NonNull
+    private Long timestamp;
+
+    @NonNull
+    private String workspace_id;
+
+    @NonNull
+    private String workspace_name;
+
+    private String signature;
+
+}

+ 7 - 1
Backend/sample/src/main/java/com/dji/sample/manage/model/entity/ManageDeviceLivestreamUrlEntity.java

@@ -27,12 +27,18 @@ public class ManageDeviceLivestreamUrlEntity implements Serializable {
     @TableField(value = "payload")
     private String payload;
 
-    @TableField(value = "user_type")
+    @TableField(value = "payload_index")
+    private Integer payloadIndex;
+
+    @TableField(value = "url_type")
     private Integer urlType;
 
     @TableField(value = "sub_type")
     private Integer subType;
 
+    @TableField(value = "channel_id")
+    private Integer channelId;
+
     @TableField(value = "url")
     private String url;
 

+ 5 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/enums/LiveUrlTypeEnum.java

@@ -15,6 +15,8 @@ public enum LiveUrlTypeEnum {
 
     GB28181(3),
 
+    WEBRTC(4),
+
     UNKNOWN(-1);
 
     private int val;
@@ -40,6 +42,9 @@ public enum LiveUrlTypeEnum {
         if (GB28181.val == val) {
             return GB28181;
         }
+        if (WEBRTC.val == val) {
+            return WEBRTC;
+        }
         return UNKNOWN;
     }
 }

+ 2 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java

@@ -15,6 +15,8 @@ public enum UserTypeEnum {
 
     CLIENT(4,"API"),
 
+    SUPER_SYS(5,"SUPER_SYS"),
+
     UNKNOWN(-1, "Unknown");
 
     private int val;

+ 1 - 1
Backend/sample/src/main/java/com/dji/sample/manage/service/IManageDeviceLivestreamUrlService.java

@@ -13,5 +13,5 @@ public interface IManageDeviceLivestreamUrlService {
      * 通过接口获取RTMP
      * @return
      */
-    String getRtmpUrl(ManageDeviceLivestreamUrlDTO deviceLivestreamUrlDTO);
+    ManageDeviceLivestreamUrlDTO getUrl(ManageDeviceLivestreamUrlDTO deviceLivestreamUrlDTO);
 }

+ 3 - 0
Backend/sample/src/main/java/com/dji/sample/manage/service/IUserService.java

@@ -1,5 +1,6 @@
 package com.dji.sample.manage.service;
 
+import com.dji.sample.manage.model.dto.SignLoginDTO;
 import com.dji.sample.manage.model.dto.UserDTO;
 import com.dji.sample.manage.model.dto.UserListDTO;
 import com.dji.sample.manage.model.entity.UserEntity;
@@ -56,4 +57,6 @@ public interface IUserService {
     Boolean updateUserWorkspace(String newWorkspaceId, String userId);
 
     UserEntity getUserByUsername(String username);
+
+    HttpResultResponse userLogin(SignLoginDTO signLoginDTO);
 }

+ 13 - 2
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/LiveStreamServiceImpl.java

@@ -44,6 +44,9 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
     @Autowired
     private AbstractLivestreamService abstractLivestreamService;
 
+    @Autowired
+    private IManageDeviceLivestreamUrlService deviceLivestreamUrlService;
+
     @Override
     public List<CapacityDeviceDTO> getLiveCapacity(String workspaceId) {
 
@@ -72,14 +75,21 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
         if (HttpResultResponse.CODE_SUCCESS != responseResult.getCode()) {
             return responseResult;
         }
+        ManageDeviceLivestreamUrlDTO livestreamUrlDTO = new ManageDeviceLivestreamUrlDTO();
+        livestreamUrlDTO.setWorkspaceId(responseResult.getData().getWorkspaceId());
+        livestreamUrlDTO.setPayloadIndex(Integer.valueOf(liveParam.getVideoId().getPayloadIndex().toString()));
+        livestreamUrlDTO.setDeviceSn(responseResult.getData().getDeviceSn());
+        livestreamUrlDTO = deviceLivestreamUrlService.getUrl(livestreamUrlDTO);
 
         ILivestreamUrl url = LiveStreamProperty.get(liveParam.getUrlType());
+        LivestreamRtmpUrl rtmpUrl = (LivestreamRtmpUrl) url.clone();
+        rtmpUrl.setUrl(livestreamUrlDTO.getRtmpUrl());
         //url = setExt(liveParam.getUrlType(), url, liveParam.getVideoId());
 
         TopicServicesResponse<ServicesReplyData<String>> response = abstractLivestreamService.liveStartPush(
                 SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()),
                 new LiveStartPushRequest()
-                        .setUrl(url)
+                        .setUrl(rtmpUrl)
                         .setUrlType(liveParam.getUrlType())
                         .setVideoId(liveParam.getVideoId())
                         .setVideoQuality(liveParam.getVideoQuality()));
@@ -95,7 +105,8 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
                 break;
             case RTMP:
 //                live.setUrl("http://smsp.jkec.info:4443/flv/live/stream_27.flv");
-                live.setUrl("webrtc://smsp.jkec.info:18000/rtc/stream_27");
+                //live.setUrl("webrtc://smsp.jkec.info:18000/rtc/stream_27");
+                live.setUrl(livestreamUrlDTO.getWebRtcUrl());
                 //live.setUrl("webrtcs://smsp.jkec.info:4443/rtc/stream_27");
 //                live.setUrl(url.toString().replace("rtmp", "webrtc"));
                 break;

+ 60 - 17
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/ManageDeviceLivestreamUrlServiceImpl.java

@@ -3,9 +3,11 @@ package com.dji.sample.manage.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.dji.sample.common.smsp.CallSmsp;
 import com.dji.sample.common.util.DesUtil;
+import com.dji.sample.manage.dao.IDevicePayloadMapper;
 import com.dji.sample.manage.dao.IManageDeviceLivestreamUrlMapper;
 import com.dji.sample.manage.dao.IUserMapper;
 import com.dji.sample.manage.model.dto.ManageDeviceLivestreamUrlDTO;
+import com.dji.sample.manage.model.entity.DevicePayloadEntity;
 import com.dji.sample.manage.model.entity.ManageDeviceLivestreamUrlEntity;
 import com.dji.sample.manage.model.entity.UserEntity;
 import com.dji.sample.manage.model.enums.LiveUrlTypeEnum;
@@ -16,6 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.List;
+
 
 @Service
 @Transactional
@@ -28,19 +32,14 @@ public class ManageDeviceLivestreamUrlServiceImpl implements IManageDeviceLivest
     @Autowired
     private IManageDeviceLivestreamUrlMapper mapper;
 
+    @Autowired
+    private IDevicePayloadMapper payloadMapper;
+
     private final String clientId = "e534550a85d94faba73e8040e76514bc";
 
     @Override
-    public String getRtmpUrl(ManageDeviceLivestreamUrlDTO deviceLivestreamUrlDTO) {
+    public ManageDeviceLivestreamUrlDTO getUrl(ManageDeviceLivestreamUrlDTO deviceLivestreamUrlDTO) {
 
-        QueryWrapper<ManageDeviceLivestreamUrlEntity> wrapper = new QueryWrapper<>();
-        wrapper.lambda().eq(ManageDeviceLivestreamUrlEntity::getDeviceSn,deviceLivestreamUrlDTO.getDeviceSn())
-                .eq(ManageDeviceLivestreamUrlEntity::getWorkspaceId,deviceLivestreamUrlDTO.getWorkspaceId())
-                .eq(ManageDeviceLivestreamUrlEntity::getPayload,deviceLivestreamUrlDTO.getPayload());
-        ManageDeviceLivestreamUrlEntity urlEntity = mapper.selectOne(wrapper);
-        if (urlEntity != null) {
-            return urlEntity.getUrl();
-        }
 
         QueryWrapper<UserEntity> userWrapper = new QueryWrapper<>();
         userWrapper.lambda().eq(UserEntity::getUserType,3).eq(UserEntity::getClientId,clientId);
@@ -53,14 +52,58 @@ public class ManageDeviceLivestreamUrlServiceImpl implements IManageDeviceLivest
         String password = DesUtil.getDecryptData(userEntity.getPassword(),userEntity.getSalt());
         //获取token
         String token = CallSmsp.getSmspToken(userEntity.getUsername(),password);
+        if(token == null) {
+            log.debug("The smsp token is already null.");
+        }
+
         //获取rtmp地址
-        String rtmp = CallSmsp.getRtmp(token,deviceLivestreamUrlDTO.getDeviceSn());
-        deviceLivestreamUrlDTO.setUrlType(LiveUrlTypeEnum.RTMP.getVal());
-        deviceLivestreamUrlDTO.setSubType(2);
-        //dto转entity
-        BeanUtils.copyProperties(urlEntity,deviceLivestreamUrlDTO);
-        //存库
-        mapper.insert(urlEntity);
-        return rtmp;
+        ManageDeviceLivestreamUrlDTO rtmpDto = CallSmsp.getRtmp(token,deviceLivestreamUrlDTO.getDeviceSn(),deviceLivestreamUrlDTO.getPayload());
+        QueryWrapper<DevicePayloadEntity> payloadWrapper = new QueryWrapper<>();
+        payloadWrapper.lambda().eq(DevicePayloadEntity::getPayloadIndex,deviceLivestreamUrlDTO.getPayload())
+                .eq(DevicePayloadEntity::getDeviceSn,deviceLivestreamUrlDTO.getDeviceSn());
+        DevicePayloadEntity payloadEntity = payloadMapper.selectOne(payloadWrapper);
+
+        deviceLivestreamUrlDTO.setPayload(payloadEntity.getPayloadName());
+        deviceLivestreamUrlDTO.setPayloadIndex(payloadEntity.getPayloadIndex());
+        deviceLivestreamUrlDTO.setChannelId(rtmpDto.getChannelId());
+
+        ManageDeviceLivestreamUrlEntity urlEntity = new ManageDeviceLivestreamUrlEntity();
+        QueryWrapper<ManageDeviceLivestreamUrlEntity> wrapper = new QueryWrapper<>();
+        wrapper.lambda().eq(ManageDeviceLivestreamUrlEntity::getDeviceSn,deviceLivestreamUrlDTO.getDeviceSn())
+                .eq(ManageDeviceLivestreamUrlEntity::getWorkspaceId,deviceLivestreamUrlDTO.getWorkspaceId())
+                .eq(ManageDeviceLivestreamUrlEntity::getPayloadIndex,deviceLivestreamUrlDTO.getPayloadIndex());
+        List<ManageDeviceLivestreamUrlEntity> urlList = mapper.selectList(wrapper);
+        if (urlList.size() > 0) {
+            for(int i = 0; i< urlList.size();i++) {
+                urlEntity = urlList.get(i);
+                if (urlEntity.getUrlType().equals(LiveUrlTypeEnum.RTMP.getVal())) {
+                    if(!urlEntity.getUrl().equals(rtmpDto.getRtmpUrl())) {
+                        urlEntity.setUrl(rtmpDto.getRtmpUrl());
+                        mapper.updateById(urlEntity);
+                    }
+                } else if(urlEntity.getUrlType().equals(LiveUrlTypeEnum.WEBRTC.getVal())) {
+                    if(!urlEntity.getUrl().equals(rtmpDto.getWebRtcUrl())) {
+                        urlEntity.setUrl(rtmpDto.getWebRtcUrl());
+                        mapper.updateById(urlEntity);
+                    }
+                }
+            }
+            return rtmpDto;
+        } else {
+            //dto转entity
+            BeanUtils.copyProperties(deviceLivestreamUrlDTO,urlEntity);
+            //存库Rtmp
+            urlEntity.setSubType(1);
+            urlEntity.setUrlType(LiveUrlTypeEnum.RTMP.getVal());
+            urlEntity.setUrl(rtmpDto.getRtmpUrl());
+            mapper.insert(urlEntity);
+            //存库WEBRTC
+            urlEntity.setId(null);
+            urlEntity.setSubType(2);
+            urlEntity.setUrlType(LiveUrlTypeEnum.WEBRTC.getVal());
+            urlEntity.setUrl(rtmpDto.getWebRtcUrl());
+            mapper.insert(urlEntity);
+            return rtmpDto;
+        }
     }
 }

+ 141 - 8
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java

@@ -1,5 +1,8 @@
 package com.dji.sample.manage.service.impl;
 
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.digest.DigestUtil;
 import com.auth0.jwt.JWT;
 import com.auth0.jwt.exceptions.TokenExpiredException;
 import com.auth0.jwt.interfaces.DecodedJWT;
@@ -11,12 +14,14 @@ import com.dji.sample.common.model.CustomClaim;
 import com.dji.sample.common.util.DesUtil;
 import com.dji.sample.common.util.JwtUtil;
 import com.dji.sample.component.mqtt.config.MqttPropertyConfiguration;
+import com.dji.sample.component.mqtt.model.MqttClientOptions;
+import com.dji.sample.component.mqtt.model.MqttUseEnum;
+import com.dji.sample.configuration.CustomConfiguration;
 import com.dji.sample.manage.dao.IUserMapper;
-import com.dji.sample.manage.model.dto.DeviceDTO;
-import com.dji.sample.manage.model.dto.UserDTO;
-import com.dji.sample.manage.model.dto.UserListDTO;
-import com.dji.sample.manage.model.dto.WorkspaceDTO;
+import com.dji.sample.manage.dao.IWorkspaceMapper;
+import com.dji.sample.manage.model.dto.*;
 import com.dji.sample.manage.model.entity.UserEntity;
+import com.dji.sample.manage.model.entity.WorkspaceEntity;
 import com.dji.sample.manage.model.enums.UserTypeEnum;
 import com.dji.sample.manage.service.IDeviceService;
 import com.dji.sample.manage.service.IUserService;
@@ -24,6 +29,7 @@ import com.dji.sample.manage.service.IWorkspaceService;
 import com.dji.sdk.common.HttpResultResponse;
 import com.dji.sdk.common.Pagination;
 import com.dji.sdk.common.PaginationData;
+import com.fasterxml.classmate.Annotations;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
@@ -32,15 +38,17 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 
 import java.nio.charset.StandardCharsets;
+import java.time.Duration;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.UUID;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+
+
 @Service
 @Transactional
 public class UserServiceImpl implements IUserService {
@@ -57,6 +65,11 @@ public class UserServiceImpl implements IUserService {
     @Autowired
     private IDeviceService deviceService;
 
+    @Autowired
+    private IWorkspaceMapper workspaceMapper;
+
+
+
     @Override
     public HttpResultResponse getUserByUsername(String username, String workspaceId) {
 
@@ -323,6 +336,102 @@ public class UserServiceImpl implements IUserService {
                 .eq("username", username));
     }
 
+    @Override
+    public HttpResultResponse userLogin(SignLoginDTO signLoginDTO) {
+        String username = signLoginDTO.getUsername();
+        String sign = signLoginDTO.getSignature();
+        String workSpaceId = signLoginDTO.getWorkspace_id();
+        String workSpaceName = signLoginDTO.getWorkspace_name();
+        String clientId = signLoginDTO.getClient_id();
+
+        Long timestamp = signLoginDTO.getTimestamp();
+
+
+        // Step 1: Convert the date-time Long to LocalDateTime
+        LocalDateTime dateTime = LocalDateTime.ofInstant(
+                Instant.ofEpochSecond(timestamp),
+                ZoneId.systemDefault());
+        // Step 2: Calculate the difference between the current time and the extracted time
+        LocalDateTime currentTime = LocalDateTime.now();
+        Duration duration = Duration.between(dateTime, currentTime);
+
+        // Step 3: Check if the difference is greater than 5 minutes
+        boolean isMoreThanFiveMinutes = duration.toMinutes() > 5;
+        if (isMoreThanFiveMinutes) {
+            return new HttpResultResponse()
+                    .setCode(HttpStatus.UNAUTHORIZED.value())
+                    .setMessage("invalid time");
+        }
+        if (sign != null) {
+            String dataInput  = clientId+timestamp+username+workSpaceId+workSpaceName;
+            String generatedHash = DigestUtil.sha256Hex(dataInput.toUpperCase()+CustomConfiguration.signKey);
+            // Verify the hash
+            boolean isMatch = StrUtil.equals(generatedHash, sign);
+            if(!isMatch) {
+                return new HttpResultResponse()
+                        .setCode(HttpStatus.UNAUTHORIZED.value())
+                        .setMessage("invalid sign");
+            }
+        }
+        //用户入库
+        QueryWrapper<UserEntity> userWrapper = new QueryWrapper<>();
+        userWrapper.lambda().eq(UserEntity::getUserType,UserTypeEnum.SUPER_SYS.getVal())
+                .eq(UserEntity::getClientId,clientId);
+        UserEntity userEntity = mapper.selectOne(userWrapper);
+        if(userEntity == null) {
+            userEntity = new UserEntity();
+            userEntity.setUsername(username);
+            userEntity.setUserId(UUID.randomUUID().toString());
+            userEntity.setUserType(UserTypeEnum.SUPER_SYS.getVal());
+            userEntity.setPassword("");
+            userEntity.setWorkspaceId(workSpaceId);
+            userEntity.setMqttUsername(mqttPropertyConfiguration.mqttConnectOptions().getUserName());
+            userEntity.setMqttPassword(String.valueOf(mqttPropertyConfiguration.mqttConnectOptions().getPassword()));
+            userEntity.setClientId(clientId);
+            mapper.insert(userEntity);
+        } else {
+            userEntity.setMqttUsername(mqttPropertyConfiguration.mqttConnectOptions().getUserName());
+            userEntity.setMqttPassword(String.valueOf(mqttPropertyConfiguration.mqttConnectOptions().getPassword()));
+            userEntity.setUsername(username);
+            userEntity.setWorkspaceId(workSpaceId);
+            mapper.updateById(userEntity);
+        }
+
+        //工作空间入库
+        QueryWrapper<WorkspaceEntity> workSpaceWrapper = new QueryWrapper<>();
+        workSpaceWrapper.lambda().eq(WorkspaceEntity::getWorkspaceId,workSpaceId);
+        WorkspaceEntity workspace = workspaceMapper.selectOne(workSpaceWrapper);
+        if(workspace == null) {
+            workspace = new WorkspaceEntity();
+            workspace.setWorkspaceId(workSpaceId);
+            workspace.setWorkspaceName(workSpaceName);
+            workspace.setPlatformName("Cloud Api Platform");
+            workspace.setBindCode(RandomUtil.randomString(6));
+            workspaceMapper.insert(workspace);
+        } else {
+            workspace.setWorkspaceName(workSpaceName);
+            workspaceMapper.updateById(workspace);
+        }
+
+        CustomClaim customClaim = new CustomClaim(userEntity.getUserId(),
+                username, UserTypeEnum.SUPER_SYS.getVal(),
+                workSpaceId);
+
+        // create token
+        String token = JwtUtil.createToken(customClaim.convertToMap());
+
+        UserDTO userDTO = new UserDTO();
+        userDTO.setUsername(username);
+        userDTO.setWorkspaceId(workSpaceId);
+        userDTO.setUserId(userEntity.getUserId());
+        userDTO.setMqttUsername(userEntity.getMqttUsername());
+        userDTO.setMqttPassword(userEntity.getMqttPassword());
+        userDTO.setUserType(UserTypeEnum.SUPER_SYS.getVal());
+        userDTO.setMqttAddr(MqttPropertyConfiguration.getBasicMqttAddress());
+        userDTO.setAccessToken(token);
+        return HttpResultResponse.success(userDTO);
+    }
+
     private UserEntity getApiUser(String clientId) {
         return mapper.selectOne(new QueryWrapper<UserEntity>()
                 .eq("client_id", clientId)
@@ -353,4 +462,28 @@ public class UserServiceImpl implements IUserService {
                 .mqttAddr(MqttPropertyConfiguration.getBasicMqttAddress())
                 .build();
     }
+
+    private static String extractDateTime(String inputString,String userCode) {
+        // Step 1: Define the pattern
+        Pattern pattern = Pattern.compile(userCode+"(\\d+)"+userCode);
+        // Step 2: Create a matcher for the input string
+        Matcher matcher = pattern.matcher(inputString);
+        // Step 3: Check if the pattern matches
+        if (matcher.find()) {
+            // Step 4: Extract the number
+            String number = matcher.group(1); // group(1) refers to the first capturing group
+            return number;
+        } else {
+            return null;
+        }
+    }
+
+    private static LocalDateTime parseTimestamp(String timestampString) {
+        // Convert the timestamp to LocalDateTime
+        long timestamp = Long.parseLong(timestampString);
+        return LocalDateTime.ofInstant(
+                Instant.ofEpochSecond(timestamp),
+                ZoneId.systemDefault()
+        );
+    }
 }

+ 3 - 1
Backend/sample/src/main/resources/application.yml

@@ -182,4 +182,6 @@ custom-config:
   #航点采集频次(秒)
   frequency: 3
   key: b1uruk98vuk40cdego6jw5yv9tygjm3s
-  signKey: 7e92430eb1f949e9a750fadf68777c44
+  signKey: 7e92430eb1f949e9a750fadf68777c44
+  smspTokenUrl: https://smsp.jkec.info:4443/api/v1/login
+  smspRtmpUrl: https://smsp.jkec.info:4443/api/v1/channelstream/all