xiewenjie 3 роки тому
коміт
32e05b237a
35 змінених файлів з 3423 додано та 0 видалено
  1. 34 0
      .gitignore
  2. 118 0
      pom.xml
  3. 18 0
      src/main/java/com/fdkk/fdkkmeta/FdkkMetaApplication.java
  4. 72 0
      src/main/java/com/fdkk/fdkkmeta/config/FastJson2JsonRedisSerializer.java
  5. 53 0
      src/main/java/com/fdkk/fdkkmeta/config/RedisConfig.java
  6. 71 0
      src/main/java/com/fdkk/fdkkmeta/config/SocketIOConfig.java
  7. 19 0
      src/main/java/com/fdkk/fdkkmeta/config/TrtcConfig.java
  8. 26 0
      src/main/java/com/fdkk/fdkkmeta/dto/BaseDto.java
  9. 24 0
      src/main/java/com/fdkk/fdkkmeta/dto/PushDto.java
  10. 20 0
      src/main/java/com/fdkk/fdkkmeta/dto/RotateDto.java
  11. 16 0
      src/main/java/com/fdkk/fdkkmeta/dto/RouteDto.java
  12. 23 0
      src/main/java/com/fdkk/fdkkmeta/dto/UserOnlineDto.java
  13. 14 0
      src/main/java/com/fdkk/fdkkmeta/po/PointPO.java
  14. 19 0
      src/main/java/com/fdkk/fdkkmeta/po/RoutePO.java
  15. 1192 0
      src/main/java/com/fdkk/fdkkmeta/redis/RedisCache.java
  16. 30 0
      src/main/java/com/fdkk/fdkkmeta/socketIO/ServerRunner.java
  17. 351 0
      src/main/java/com/fdkk/fdkkmeta/socketIO/SocketIoServer.java
  18. 35 0
      src/main/java/com/fdkk/fdkkmeta/socketIO/SocketIoServerMapUtil.java
  19. 31 0
      src/main/java/com/fdkk/fdkkmeta/task/FFmpegTask.java
  20. 97 0
      src/main/java/com/fdkk/fdkkmeta/test/test.java
  21. 166 0
      src/main/java/com/fdkk/fdkkmeta/util/FileUtils.java
  22. 36 0
      src/main/java/com/fdkk/fdkkmeta/util/FpsUtil.java
  23. 154 0
      src/main/java/com/fdkk/fdkkmeta/util/GenerateUserSig.java
  24. 26 0
      src/main/java/com/fdkk/fdkkmeta/util/TrtcUtil.java
  25. 41 0
      src/main/java/com/fdkk/fdkkmeta/util/blobUtil.java
  26. 207 0
      src/main/java/com/fdkk/fdkkmeta/util/kesar/AStar.java
  27. 36 0
      src/main/java/com/fdkk/fdkkmeta/util/kesar/Coord.java
  28. 178 0
      src/main/java/com/fdkk/fdkkmeta/util/kesar/GetRoute.java
  29. 29 0
      src/main/java/com/fdkk/fdkkmeta/util/kesar/MapInfo.java
  30. 57 0
      src/main/java/com/fdkk/fdkkmeta/util/kesar/Node.java
  31. 34 0
      src/main/resources/application-dev.yml
  32. 34 0
      src/main/resources/application-uat.yml
  33. 5 0
      src/main/resources/application.yml
  34. 25 0
      src/test/java/com/fdkk/fdkkmeta/FdkkMetaApplicationTests.java
  35. 132 0
      startJar.sh

+ 34 - 0
.gitignore

@@ -0,0 +1,34 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+!/.idea/

+ 118 - 0
pom.xml

@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.6.5</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.fdkk</groupId>
+    <artifactId>fdkk-meta</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>fdkk-meta</name>
+    <description>fdkk-meta</description>
+    <packaging>jar</packaging>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <hutool.version>5.7.7</hutool.version>
+        <socketio.version>1.7.19</socketio.version>
+        <fastjson.version>1.2.79</fastjson.version>
+        <tls.version>2.0</tls.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+            <dependency>
+                <groupId>com.github.tencentyun</groupId>
+                <artifactId>tls-sig-api-v2</artifactId>
+                <version>${tls.version}</version>
+            </dependency>
+        <dependency>
+            <groupId>com.corundumstudio.socketio</groupId>
+            <artifactId>netty-socketio</artifactId>
+            <version>${socketio.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>${hutool.version}</version>
+        </dependency>
+        <!-- 阿里JSON解析器 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/ws.schild/jave-nativebin-linux64 -->
+
+        <dependency>
+            <groupId>com.lmax</groupId>
+            <artifactId>disruptor</artifactId>
+            <version>3.3.4</version>
+        </dependency>
+        <!--集成Redis-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!--redis连接池 start-->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+        <!--redis连接池 end-->
+    </dependencies>
+
+
+    <build>
+
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>false</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>

+ 18 - 0
src/main/java/com/fdkk/fdkkmeta/FdkkMetaApplication.java

@@ -0,0 +1,18 @@
+package com.fdkk.fdkkmeta;
+
+import com.fdkk.fdkkmeta.config.TrtcConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableScheduling
+public class FdkkMetaApplication {
+
+
+    public static void main(String[] args) {
+        SpringApplication.run(FdkkMetaApplication.class, args);
+    }
+
+}

+ 72 - 0
src/main/java/com/fdkk/fdkkmeta/config/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,72 @@
+package com.fdkk.fdkkmeta.config;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import org.springframework.util.Assert;
+
+import java.nio.charset.Charset;
+
+/**
+ * Redis使用FastJson序列化
+ *
+ * @author fdkk
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+    @SuppressWarnings("unused")
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+    static
+    {
+        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+    }
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
+    {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException
+    {
+        if (t == null)
+        {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException
+    {
+        if (bytes == null || bytes.length <= 0)
+        {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz);
+    }
+
+    public void setObjectMapper(ObjectMapper objectMapper)
+    {
+        Assert.notNull(objectMapper, "'objectMapper' must not be null");
+        this.objectMapper = objectMapper;
+    }
+
+    protected JavaType getJavaType(Class<?> clazz)
+    {
+        return TypeFactory.defaultInstance().constructType(clazz);
+    }
+}

+ 53 - 0
src/main/java/com/fdkk/fdkkmeta/config/RedisConfig.java

@@ -0,0 +1,53 @@
+package com.fdkk.fdkkmeta.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * redis配置
+ *
+ * @author fdkk
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig
+{
+    @Bean
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
+        {
+            RedisTemplate<String, Object> template = new RedisTemplate<>();
+            template.setConnectionFactory(lettuceConnectionFactory);
+
+            FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+            mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+            serializer.setObjectMapper(mapper);
+
+            // 使用StringRedisSerializer来序列化和反序列化redis的key值
+            template.setKeySerializer(new StringRedisSerializer());
+            template.setValueSerializer(serializer);
+
+            // Hash的key也采用StringRedisSerializer的序列化方式
+            template.setHashKeySerializer(new StringRedisSerializer());
+            template.setHashValueSerializer(serializer);
+
+            template.afterPropertiesSet();
+            return template;
+        }
+
+    }}

+ 71 - 0
src/main/java/com/fdkk/fdkkmeta/config/SocketIOConfig.java

@@ -0,0 +1,71 @@
+package com.fdkk.fdkkmeta.config;
+
+import com.corundumstudio.socketio.SocketConfig;
+import com.corundumstudio.socketio.SocketIOServer;
+import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 功能描述
+ *
+ * @author: zyu
+ * @description:
+ * @date: 2019/4/23 10:40
+ */
+@Configuration
+public class SocketIOConfig {
+
+    @Value("${socketio.host}")
+    private String host;
+
+    @Value("${socketio.port}")
+    private Integer port;
+
+    @Value("${socketio.bossCount}")
+    private int bossCount;
+
+    @Value("${socketio.workCount}")
+    private int workCount;
+
+    @Value("${socketio.allowCustomRequests}")
+    private boolean allowCustomRequests;
+
+    @Value("${socketio.upgradeTimeout}")
+    private int upgradeTimeout;
+
+    @Value("${socketio.pingTimeout}")
+    private int pingTimeout;
+
+    @Value("${socketio.pingInterval}")
+    private int pingInterval;
+
+    /**
+     * 以下配置在上面的application.properties中已经注明
+     *
+     * @return
+     */
+    @Bean
+    public SocketIOServer socketIOServer() {
+        SocketConfig socketConfig = new SocketConfig();
+        socketConfig.setTcpNoDelay(true);
+        socketConfig.setSoLinger(0);
+        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
+        config.setSocketConfig(socketConfig);
+        config.setHostname(host);
+        config.setPort(port);
+        config.setBossThreads(bossCount);
+        config.setWorkerThreads(workCount);
+        config.setAllowCustomRequests(allowCustomRequests);
+        config.setUpgradeTimeout(upgradeTimeout);
+        config.setPingTimeout(pingTimeout);
+        config.setPingInterval(pingInterval);
+        return new SocketIOServer(config);
+    }
+
+    @Bean
+    public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
+        return new SpringAnnotationScanner(socketServer);
+    }
+}

+ 19 - 0
src/main/java/com/fdkk/fdkkmeta/config/TrtcConfig.java

@@ -0,0 +1,19 @@
+package com.fdkk.fdkkmeta.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "trtc")
+public class TrtcConfig {
+
+    private String rtmpHost;
+
+
+}

+ 26 - 0
src/main/java/com/fdkk/fdkkmeta/dto/BaseDto.java

@@ -0,0 +1,26 @@
+package com.fdkk.fdkkmeta.dto;
+
+import com.fdkk.fdkkmeta.po.PointPO;
+import javafx.geometry.Point3D;
+import lombok.*;
+
+/**
+ * Created by Xiewj on 2021/7/29 0029 12:07
+ */
+@Data
+public abstract class BaseDto {
+
+    private String sceneCode;
+
+    private String roomId;
+
+    private String userId;
+
+    private String sessionId;
+
+    private String videoPath;
+
+    private PointPO point;
+
+
+}

+ 24 - 0
src/main/java/com/fdkk/fdkkmeta/dto/PushDto.java

@@ -0,0 +1,24 @@
+package com.fdkk.fdkkmeta.dto;
+
+import cn.hutool.core.util.URLUtil;
+import javafx.geometry.Point3D;
+import lombok.*;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Xiewj on 2021/7/29 0029 12:07
+ */
+@Data
+@ToString
+@AllArgsConstructor
+@NoArgsConstructor
+public class PushDto  extends BaseDto{
+
+    private List<String> videoList;
+
+
+}

+ 20 - 0
src/main/java/com/fdkk/fdkkmeta/dto/RotateDto.java

@@ -0,0 +1,20 @@
+package com.fdkk.fdkkmeta.dto;
+
+import lombok.*;
+
+import java.util.List;
+
+/**
+ * Created by Xiewj on 2021/7/29 0029 12:07
+ */
+@Data
+public class RotateDto extends BaseDto{
+
+    private String sangle;
+
+    private String eangle;
+
+    //TREU 反 false 正
+    private Boolean reverses;
+
+}

+ 16 - 0
src/main/java/com/fdkk/fdkkmeta/dto/RouteDto.java

@@ -0,0 +1,16 @@
+package com.fdkk.fdkkmeta.dto;
+
+import com.fdkk.fdkkmeta.po.PointPO;
+import javafx.geometry.Point3D;
+import lombok.Data;
+
+/**
+ * Created by Xiewj on 2021/7/29 0029 12:07
+ */
+@Data
+public class RouteDto extends BaseDto{
+
+    private PointPO s_location;
+
+    private PointPO e_location;
+}

+ 23 - 0
src/main/java/com/fdkk/fdkkmeta/dto/UserOnlineDto.java

@@ -0,0 +1,23 @@
+package com.fdkk.fdkkmeta.dto;
+
+import lombok.*;
+
+/**
+ * Created by Xiewj on 2021/7/29 0029 12:07
+ */
+@Data
+@ToString
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class UserOnlineDto {
+
+    private String sceneCode;
+
+    private String roomId;
+
+    private String userId;
+
+    private String pid;
+
+}

+ 14 - 0
src/main/java/com/fdkk/fdkkmeta/po/PointPO.java

@@ -0,0 +1,14 @@
+package com.fdkk.fdkkmeta.po;
+
+import lombok.Data;
+
+/**
+ * @author Xiewj
+ * @date 2021/11/29
+ */
+@Data
+public class PointPO {
+   private Double x;
+   private Double y;
+   private Double z;
+}

+ 19 - 0
src/main/java/com/fdkk/fdkkmeta/po/RoutePO.java

@@ -0,0 +1,19 @@
+package com.fdkk.fdkkmeta.po;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author Xiewj
+ * @date 2021/11/29
+ */
+@Data
+public class RoutePO {
+    private Double x;
+    private Double y;
+    private Double z;
+    public Double weight;
+    private List<Integer> ids;
+    private int id;
+}

Різницю між файлами не показано, бо вона завелика
+ 1192 - 0
src/main/java/com/fdkk/fdkkmeta/redis/RedisCache.java


+ 30 - 0
src/main/java/com/fdkk/fdkkmeta/socketIO/ServerRunner.java

@@ -0,0 +1,30 @@
+package com.fdkk.fdkkmeta.socketIO;
+
+import com.corundumstudio.socketio.SocketIOServer;
+import com.fdkk.fdkkmeta.config.TrtcConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Xiewj
+ * @date 2022/3/15
+ */
+@Component
+@Order(value = 1)
+public class ServerRunner implements CommandLineRunner {
+    private final SocketIOServer server;
+
+
+    @Autowired
+    public ServerRunner(SocketIOServer server) {
+        this.server = server;
+    }
+
+    @Override
+    public void run(String... args) throws Exception {
+        server.start();
+        System.out.println("socket.io启动成功!");
+    }
+}

+ 351 - 0
src/main/java/com/fdkk/fdkkmeta/socketIO/SocketIoServer.java

@@ -0,0 +1,351 @@
+package com.fdkk.fdkkmeta.socketIO;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.io.file.FileWriter;
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.RuntimeUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.corundumstudio.socketio.AckRequest;
+import com.corundumstudio.socketio.SocketIOClient;
+import com.corundumstudio.socketio.SocketIOServer;
+import com.corundumstudio.socketio.annotation.OnConnect;
+import com.corundumstudio.socketio.annotation.OnDisconnect;
+import com.corundumstudio.socketio.annotation.OnEvent;
+import com.fdkk.fdkkmeta.dto.PushDto;
+import com.fdkk.fdkkmeta.dto.RotateDto;
+import com.fdkk.fdkkmeta.dto.RouteDto;
+import com.fdkk.fdkkmeta.po.RoutePO;
+import com.fdkk.fdkkmeta.redis.RedisCache;
+import com.fdkk.fdkkmeta.util.FpsUtil;
+import com.fdkk.fdkkmeta.util.GenerateUserSig;
+import com.fdkk.fdkkmeta.util.TrtcUtil;
+import com.fdkk.fdkkmeta.util.kesar.GetRoute;
+import com.fdkk.fdkkmeta.util.kesar.MapInfo;
+import javafx.geometry.Point3D;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Xiewj
+ * @date 2022/3/16
+ */
+@Component
+@Slf4j
+public class SocketIoServer {
+
+    private static SocketIOServer socketIoServer;
+
+    @Autowired
+    TrtcUtil trtcUtil;
+    @Autowired
+    RedisCache redisCache;
+    // 获取推送消息接收入口
+    @OnEvent(value = "pushVideo_test")
+    public void pushVideo_test (SocketIOClient client, AckRequest ackRequest, PushDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("pushVideo-接收到客户端消息:{}", JSON.toJSONString(param));
+         byte[] bytes = IoUtil.readBytes(new FileInputStream("/home/webrtc/videofile/"+param.getVideoPath()+".mp4"));
+        client.sendEvent("pushVideo_test", bytes);
+    }
+
+    // 获取推送消息接收入口
+    @OnEvent(value = "getRoute")
+    public void getRoute (SocketIOClient client, AckRequest ackRequest, RouteDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("getRoute-接收到客户端消息:{}", JSON.toJSONString(param));
+        JSONArray maps = GetRoute.getRoute("/home/webrtc/scenefreespacefile/target_freespace.json", param);
+        pushMessageToUser("getRoute",param.getUserId(),maps);
+        client.sendEvent("getRoute",maps);
+    }
+
+
+    // getVideo获取推送消息接收入口
+    @OnEvent(value = "getVideo")
+    public void getVideo (SocketIOClient client, AckRequest ackRequest, PushDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("getVideo-接收到客户端消息:{}", JSON.toJSONString(param));
+        StringBuilder videoPath=new StringBuilder();
+        if (param.getVideoList().size()>0){
+            for (String s : param.getVideoList()) {
+                videoPath.append(s.replaceAll("/","_"));
+            }
+        }else {
+            log.info("getVideo-VideoList-0");
+            return;
+        }
+
+//        String key=param.getSceneCode()+":" + "r"+param.getRoomId()+"u"+ param.getUserId()+":"+videoPath;
+        String key=param.getSceneCode()+":"+videoPath;
+        String filePath="/home/webrtc/sceneUserFile/"+param.getSceneCode()+"/" +key+".txt";
+        String outfilePath="/home/webrtc/sceneUserFile/"+param.getSceneCode()+"/" +key+".mp4";
+
+        if (redisCache.hasKey(key)){
+            byte[] bytes = redisCache.getCacheObject(key);
+            pushMessageToUser("getSocketVideo",param.getUserId(),bytes);
+            log.info("getVideo-redis-pushMessageToUser");
+        }else {
+            if (FileUtil.exist(outfilePath)){
+                byte[] bytes = IoUtil.readBytes(new FileInputStream(outfilePath));
+                pushMessageToUser("getSocketVideo",param.getUserId(),bytes);
+                redisCache.setCacheObject(key,bytes);
+            }else {
+                String token = redisCache.tryLock("getVideo:" + key, 1000 * 60 * 2);
+                if (token != null){
+
+                    FileWriter writer = new FileWriter(filePath);
+                    Set<String> fileList=new HashSet<>();
+                    for (String s : param.getVideoList()) {
+                        fileList.add("file '/home/webrtc/videofile/"+param.getSceneCode()+"/"+s+".mp4'");
+                    }
+                    writer.writeLines(fileList,false);
+
+                    Process exec = RuntimeUtil.exec("/home/webrtc/socket-pushvideos.sh",
+                            filePath, outfilePath
+                    );
+                    exec.waitFor();
+                    byte[] bytes = IoUtil.readBytes(new FileInputStream(outfilePath));
+                    pushMessageToUser("getSocketVideo",param.getUserId(),bytes);
+                    redisCache.setCacheObject(key,bytes);
+                    log.info("getVideo-{} {} {}","/home/webrtc/socket-pushvideos.sh",
+                            filePath,outfilePath);
+                }
+                redisCache.unlock("getVideo:"+key, token);
+            }
+        }
+
+        client.sendEvent("getVideo",param);
+
+
+
+    }
+    // 获取推送消息接收入口
+    @OnEvent(value = "getRotateVideo")
+    public void getRotateVideo (SocketIOClient client, AckRequest ackRequest, RotateDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("getRotateVideo-接收到客户端消息:{}", JSON.toJSONString(param));
+        String key=param.getSceneCode()+":" + param.getVideoPath().replaceAll("/","_")+":"+param.getSangle()+"-"+param.getEangle()+"-"+param.getReverses();
+        String outfilePath = "/home/webrtc/sceneUserFile/"+param.getSceneCode()+"/" + key + "rotate.mp4";
+
+        if (redisCache.hasKey(key)) {
+            byte[] bytes = redisCache.getCacheObject(key);
+            pushMessageToUser("getSocketVideo", param.getUserId(), bytes);
+            log.info("getRotateVideo-redis-pushMessageToUser");
+        }else {
+            if (FileUtil.exist(outfilePath)){
+                byte[] bytes = IoUtil.readBytes(new FileInputStream(outfilePath));
+                pushMessageToUser("getSocketVideo",param.getUserId(),bytes);
+                redisCache.setCacheObject(key,bytes);
+            }else {
+                String token = redisCache.tryLock("getRotateVideo:" + key, 1000 * 60 * 2);
+                if (token != null) {
+                    String sangle = param.getSangle();
+                    String eangle = param.getEangle();
+                    String reverses = param.getReverses().toString();
+                    String videoPath = param.getVideoPath();
+                    log.info("{}{}{}[}", sangle, eangle, reverses, videoPath);
+                    Process exec = RuntimeUtil.exec("/home/webrtc/socket-pushvideo-rotate.sh",
+                            "/home/webrtc/videofile/" + videoPath,
+                            FpsUtil.getDateFormat(sangle),
+                            FpsUtil.getDateFormat(eangle),
+                            reverses, outfilePath
+                    );
+                    exec.waitFor();
+                    byte[] bytes = IoUtil.readBytes(new FileInputStream(outfilePath));
+                    pushMessageToUser("getSocketVideo", param.getUserId(), bytes);
+                    redisCache.setCacheObject(key,bytes);
+                    log.info("getRotateVideo-{} {} {} {} {} {}", "/home/webrtc/socket-pushvideo-rotate.sh",
+                            "/home/webrtc/videofile/"+param.getSceneCode()+"/" + videoPath,
+                            FpsUtil.getDateFormat(sangle),
+                            FpsUtil.getDateFormat(eangle),
+                            reverses, outfilePath);
+                }
+                redisCache.unlock("getRotateVideo:" + key, token);
+            }
+        }
+        client.sendEvent("getRotateVideo",param);
+
+    }
+
+
+    // 获取推送消息接收入口
+    @OnEvent(value = "pushVideo")
+    public void pushVideo (SocketIOClient client, AckRequest ackRequest, PushDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("pushVideo-接收到客户端消息:{}", JSON.toJSONString(param));
+        //TODO 调用命令去推送流
+        String key="r:"+param.getRoomId()+"u:"+param.getUserId();
+        log.info("user-key,{}",key);
+        String videoStreamUrl=param.getSceneCode()+"/" + "r"+param.getRoomId()+"u"+ param.getUserId()+"s"+param.getSessionId();
+        //先通知前端需要接收
+        client.sendEvent("getVideo",videoStreamUrl);
+
+        String filePath="/home/webrtc/sceneUserFile/"+videoStreamUrl+".txt";
+
+        FileWriter writer = new FileWriter(filePath);
+        List<String> fileList=new ArrayList<>();
+        for (String s : param.getVideoList()) {
+            fileList.add("file '/home/webrtc/videofile/"+s+".mp4'");
+        }
+        writer.writeLines(fileList,false);
+
+        ThreadUtil.execAsync(() -> RuntimeUtil.execForStr("/home/webrtc/pushvideos.sh",
+                "rtmp://127.0.0.1:1935/"+videoStreamUrl,
+                filePath));
+        log.info("pushVideo-{},{},{}","/home/webrtc/pushvideo.sh",
+                "rtmp://127.0.0.1:1935/"+videoStreamUrl,
+                filePath);
+    }
+
+    // 获取推送消息接收入口
+    @OnEvent(value = "rotate")
+    public void rotate (SocketIOClient client, AckRequest ackRequest, RotateDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("rotate-接收到客户端消息:{}", JSON.toJSONString(param));
+        //TODO 调用命令去推送流
+        String key="r:"+param.getRoomId()+"u:"+param.getUserId();
+        log.info("user-key,{}",key);
+        //先通知前端需要接收
+        String videoStreamUrl=param.getSceneCode()+"/" + "r"+param.getRoomId()+"u"+ param.getUserId()+"s"+param.getSessionId();
+        client.sendEvent("getVideo",videoStreamUrl);
+        String sangle = param.getSangle();
+        String eangle = param.getEangle();
+        String reverses = param.getReverses().toString();
+        String videoPath=param.getVideoPath();
+
+        log.info("{}{}{}[}",sangle,eangle,reverses,videoPath);
+
+        ThreadUtil.execAsync(() -> RuntimeUtil.execForStr("/home/webrtc/pushvideo-rotate.sh",
+                "rtmp://127.0.0.1:1935/" + videoStreamUrl,
+                "/home/webrtc/videofile/"+videoPath,
+                FpsUtil.getDateFormat(sangle),
+                FpsUtil.getDateFormat(eangle),
+                reverses
+                )
+
+        );
+        log.info("rotate-{} {} {} {} {} {}","/home/webrtc/pushvideo-rotate.sh",
+                "rtmp://127.0.0.1:1935/" + videoStreamUrl,
+                "/home/webrtc/videofile/"+videoPath,
+                FpsUtil.getDateFormat(sangle),
+                FpsUtil.getDateFormat(eangle),
+                reverses);
+    }
+
+    // 获取推送消息接收入口
+    @OnEvent(value = "getPush")
+    public void getPush(SocketIOClient client, AckRequest ackRequest, PushDto param) throws IOException, InterruptedException {
+        SocketIoServer.log.info("接收到客户端消息:{}", JSON.toJSONString(param));
+        //TODO 调用命令去推送流
+        String pushURl = trtcUtil.getPushURl(param);
+        SocketIoServer.log.info("转换URL:{}", pushURl);
+        String key="r:"+param.getRoomId()+"u:"+param.getUserId();
+        log.info("user-key,{}",key);
+        //创建线程
+        //判断当前用户是否开启推流线程
+        if (!redisCache.hasKey(key)){
+            String userId = param.getUserId();
+            String pid = "123123";
+            log.info("pid{}",pid);
+        }
+//        client.sendEvent("getPush", pushURl);
+    }
+    /**
+     * 加入房间
+     * */
+    @OnEvent(value = "joinRoom")
+    public void onJoinRoomEvent(SocketIOClient client, AckRequest request, PushDto data) {
+        client.joinRoom(data.getSceneCode());
+        String key="point:"+data.getSceneCode()+":r:"+data.getRoomId()+"u:"+data.getUserId();
+        redisCache.setCacheObject(key, data);
+
+    }
+    /**
+     * 离开房间
+     * */
+    @OnEvent(value = "leaveRoom")
+    public void onLeaveRoomEvent(SocketIOClient client, AckRequest request, PushDto data) {
+        client.leaveRoom(data.getSceneCode());
+        String key="point:"+data.getSceneCode()+":r:"+data.getRoomId()+"u:"+data.getUserId();
+        redisCache.delete(key);
+
+    }
+    /**
+     * 获取当前房间里面所有人的点位
+     * */
+    @OnEvent(value = "roomPoint")
+    public void getRoomPointEvent(SocketIOClient client, AckRequest request, PushDto data) {
+        Set<Object> keys = redisCache.hKeys("point:" + data.getSceneCode() + "*");
+        List<PushDto> points=new ArrayList<>();
+        for (Object key : keys) {
+            String realKey=String.valueOf(key);
+            PushDto pushDto = redisCache.getCacheObject(realKey);
+            points.add(pushDto);
+        }
+        client.sendEvent("roomPoint",points);
+    }
+
+    @Autowired
+    public SocketIoServer(SocketIOServer server) {
+        SocketIoServer.socketIoServer = server;
+    }
+
+    @OnConnect
+    public void onConnect(SocketIOClient client) {
+        // TODO Auto-generated method stub
+        String sa = client.getRemoteAddress().toString();
+        String clientIp = sa.substring(1, sa.indexOf(":"));// 获取设备ip
+        SocketIoServer.log.info(clientIp + "-------------------------" + "客户端已连接" + clientIp);
+        String userId = getParamsByClient(client);
+        if (userId != null) {
+            SocketIoServer.log.info("userId"+userId);
+            SocketIoServer.log.info("SessionId:  " + client.getSessionId());
+            SocketIoServer.log.info("RemoteAddress:  " + client.getRemoteAddress());
+            SocketIoServer.log.info("Transport:  " + client.getTransport());
+            SocketIoServerMapUtil.put(userId, client);
+            client.sendEvent("getSign", GenerateUserSig.genTestUserSig(userId));
+        }
+    }
+
+    @OnDisconnect
+    public void onDisconnect(SocketIOClient client) {
+        // TODO Auto-generated method stub
+        String sa = client.getRemoteAddress().toString();
+        String clientIp = sa.substring(1, sa.indexOf(":"));// 获取设备ip
+        SocketIoServer.log.info(clientIp + "-------------------------" + "客户端已断开连接");
+        String userId = getParamsByClient(client);
+        if (userId != null) {
+            SocketIoServerMapUtil.remove(userId);
+            System.out.println("断开连接: " + userId);
+            System.out.println("断开连接: " + client.getSessionId());
+            client.disconnect();
+        }
+    }
+
+    /**
+     * 此方法为获取client连接中的参数,可根据需求更改
+     *
+     * @param client
+     * @return
+     */
+    private String getParamsByClient(SocketIOClient client) {
+        // 从请求的连接中拿出参数(这里的loginUserNum必须是唯一标识)
+        Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
+        List<String> list = params.get("userId");
+        if (list != null && list.size() > 0) {
+            return list.get(0);
+        }
+        return null;
+    }
+//
+    public void pushMessageToUser(String pushEvent,String userId,Object o) {
+        if (StrUtil.isNotBlank(userId)) {
+            SocketIOClient client = SocketIoServerMapUtil.get(userId);
+            if (client != null) {
+                client.sendEvent(pushEvent,o);
+            }
+        }
+    }
+}

+ 35 - 0
src/main/java/com/fdkk/fdkkmeta/socketIO/SocketIoServerMapUtil.java

@@ -0,0 +1,35 @@
+package com.fdkk.fdkkmeta.socketIO;
+
+import com.corundumstudio.socketio.SocketIOClient;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author Xiewj
+ * @date 2022/3/15
+ */
+public class SocketIoServerMapUtil {
+    private static final ConcurrentMap<String, SocketIOClient> webSocketMap = new ConcurrentHashMap<>();
+
+    public static void put(String key, SocketIOClient SocketIOClient) {
+        SocketIoServerMapUtil.webSocketMap.put(key, SocketIOClient);
+    }
+
+    public static SocketIOClient get(String key) {
+        return SocketIoServerMapUtil.webSocketMap.get(key);
+    }
+
+    public static void remove(String key) {
+        SocketIoServerMapUtil.webSocketMap.remove(key);
+    }
+
+    public static Collection<SocketIOClient> getValues() {
+        return SocketIoServerMapUtil.webSocketMap.values();
+    }
+
+    public static ConcurrentMap<String, SocketIOClient> getWebSocketMap() {
+        return SocketIoServerMapUtil.webSocketMap;
+    }
+}

+ 31 - 0
src/main/java/com/fdkk/fdkkmeta/task/FFmpegTask.java

@@ -0,0 +1,31 @@
+package com.fdkk.fdkkmeta.task;
+
+import cn.hutool.core.date.DateUtil;
+import com.fdkk.fdkkmeta.redis.RedisCache;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Xiewj
+ * @date 2022/3/30
+ */
+@Component
+@Slf4j
+public class FFmpegTask {
+   @Autowired
+   RedisCache redisCache;
+
+//   @Scheduled(initialDelay=1000, fixedDelay=2000)
+   public void checkFFmpegByPid(){
+      Set<String> allScene = redisCache.getMembers("allScene");
+      for (String sceneCode : allScene) {
+          Set<String> allPid = redisCache.getMembers("scene:"+sceneCode);
+            log.info("allpid{}",allPid);
+      }
+   }
+}

+ 97 - 0
src/main/java/com/fdkk/fdkkmeta/test/test.java

@@ -0,0 +1,97 @@
+package com.fdkk.fdkkmeta.test;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.file.FileWriter;
+import cn.hutool.core.util.URLUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkk.fdkkmeta.po.RoutePO;
+import com.fdkk.fdkkmeta.util.FileUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Xiewj
+ * @date 2022/3/29
+ */
+public class test {
+//    public static void main(String[] args) throws IOException {
+//        int d=6;
+//        int fps=2 % d;
+//        if (fps!=0){
+//            fps=2/d+1;
+//        }
+//
+//        System.out.println(fps);
+//
+//    }
+    public static void main(String[] args) throws IOException {
+        String path="C:\\Users\\4DAGE\\Downloads\\final_freespace(1).csv";
+        createdPointsJson(path);
+        creatTargetJson(path);
+    }
+
+    private static void createdPointsJson(String path) {
+        List<String> list = FileUtils.readFileByLines2(path);
+        JSONArray array=new JSONArray();
+        FileWriter writer=new FileWriter("D:\\video\\points.json");
+        for (int i = 0; i < list.size(); i++) {
+            JSONObject jsonObject=new JSONObject();
+            String[] s = list.get(i).split(" ");
+            jsonObject.put("id",i );
+            JSONObject position=new JSONObject();
+            position.put("x",Double.valueOf(s[0]));
+            position.put("y",Double.valueOf(s[1]));
+            position.put("z",Double.valueOf(s[2]));
+            jsonObject.put("position",position);
+            JSONObject rotation=new JSONObject();
+            rotation.put("x",0.0);
+            rotation.put("y",0.0);
+            rotation.put("z",0.0);
+            rotation.put("w",1.0);
+            jsonObject.put("rotation",rotation);
+            List<String> strings = Arrays.asList(s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11]);
+            List<Integer> contact = strings.stream().filter(a -> !a.equals("-1")).map(a->{
+                return Integer.parseInt(a)-1;
+            }).collect(Collectors.toList());
+            jsonObject.put("contact",contact);
+            array.add(jsonObject);
+        }
+        writer.write(array.toJSONString());
+    }
+
+    private static void creatTargetJson(String path) {
+        List<String> list = FileUtils.readFileByLines2(path);
+        List<String> collect = new ArrayList<>();
+        FileWriter writer=new FileWriter("D:\\video\\target_freespace.json");
+        for (int i = 0; i < list.size(); i++) {
+            RoutePO po = new RoutePO();
+            String[] s = list.get(i).split(" ");
+            po.setId(i );
+            if (s.length == 12) {
+                double[] oldPoint = {Double.valueOf(s[0]), Double.valueOf(s[1]), Double.valueOf(s[2])};
+                po.setX(oldPoint[0]);
+                po.setY(oldPoint[1]);
+                po.setZ(oldPoint[2]);
+                po.setWeight(Double.parseDouble(s[3]));
+                List<String> strings = Arrays.asList(s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11]);
+                List<Integer> contact = strings.stream().map(a->{
+                    if (Integer.parseInt(a)!=-1){
+                        return Integer.parseInt(a)-1;
+                    }
+                    return Integer.parseInt(a);
+                }).collect(Collectors.toList());
+                po.setIds(contact);
+            }
+            collect.add(JSON.toJSONString(po));
+        }
+        writer.writeLines(collect);
+    }
+}

+ 166 - 0
src/main/java/com/fdkk/fdkkmeta/util/FileUtils.java

@@ -0,0 +1,166 @@
+package com.fdkk.fdkkmeta.util;
+
+import cn.hutool.core.io.IoUtil;
+import com.alibaba.fastjson.util.IOUtils;
+import org.springframework.util.MimeTypeUtils;
+import org.yaml.snakeyaml.util.ArrayUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 文件处理工具类
+ *
+ * @author fdkk
+ */
+public class FileUtils {
+    private static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+    /**
+     * 输出指定文件的byte数组
+     *
+     * @param filePath 文件路径
+     * @param os       输出流
+     * @return
+     */
+    public static void writeBytes(String filePath, OutputStream os) throws IOException {
+        FileInputStream fis = null;
+        try {
+            File file = new File(filePath);
+            if (!file.exists()) {
+                throw new FileNotFoundException(filePath);
+            }
+            fis = new FileInputStream(file);
+            byte[] b = new byte[1024];
+            int length;
+            while ((length = fis.read(b)) > 0) {
+                os.write(b, 0, length);
+            }
+        } catch (IOException e) {
+            throw e;
+        } finally {
+            IOUtils.close(os);
+            IOUtils.close(fis);
+        }
+    }
+
+
+    /**
+     * 删除文件
+     *
+     * @param filePath 文件
+     * @return
+     */
+    public static boolean deleteFile(String filePath) {
+        boolean flag = false;
+        File file = new File(filePath);
+        // 路径为文件且不为空则进行删除
+        if (file.isFile() && file.exists()) {
+            file.delete();
+            flag = true;
+        }
+        return flag;
+    }
+
+    /**
+     * 文件名称验证
+     *
+     * @param filename 文件名称
+     * @return true 正常 false 非法
+     */
+    public static boolean isValidFilename(String filename) {
+        return filename.matches(FileUtils.FILENAME_PATTERN);
+    }
+
+
+    public static List<String> readFileByLines2(String path) {
+        File f = new File(path);
+        if (!f.exists()) {
+            return null;
+        }
+
+        FileReader reader = null;
+        BufferedReader br = null;
+        try {
+            // read file content from file
+            reader = new FileReader(path);
+            br = new BufferedReader(reader);
+
+            String str = null;
+            List<String> result = new ArrayList<String>();
+            while ((str = br.readLine()) != null) {
+                result.add(str);
+            }
+
+
+            return result;
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            IoUtil.close(reader);
+            IoUtil.close(br);
+        }
+        return null;
+    }
+
+
+
+    /**
+     * 下载文件名重新编码
+     *
+     * @param response     响应对象
+     * @param realFileName 真实文件名
+     * @return
+     */
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
+        String percentEncodedFileName = FileUtils.percentEncode(realFileName);
+
+        StringBuilder contentDispositionValue = new StringBuilder();
+        contentDispositionValue.append("attachment; filename=")
+                .append(percentEncodedFileName)
+                .append(";")
+                .append("filename*=")
+                .append("utf-8''")
+                .append(percentEncodedFileName);
+
+        response.setHeader("Content-disposition", contentDispositionValue.toString());
+        response.setHeader("download-filename", percentEncodedFileName);
+    }
+
+    /**
+     * 百分号编码工具方法
+     *
+     * @param s 需要百分号编码的字符串
+     * @return 百分号编码后的字符串
+     */
+    private static String percentEncode(String s) throws UnsupportedEncodingException {
+        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+        return encode.replaceAll("\\+", "%20");
+    }
+
+    /**
+     * 获取图像后缀
+     *
+     * @param photoByte 图像数据
+     * @return 后缀名
+     */
+    private static String getFileExtendName(byte[] photoByte) {
+        String strFileExtendName = "jpg";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
+            strFileExtendName = "gif";
+        } else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
+            strFileExtendName = "jpg";
+        } else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
+            strFileExtendName = "bmp";
+        } else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
+            strFileExtendName = "png";
+        }
+        return strFileExtendName;
+    }
+}

+ 36 - 0
src/main/java/com/fdkk/fdkkmeta/util/FpsUtil.java

@@ -0,0 +1,36 @@
+package com.fdkk.fdkkmeta.util;
+
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+/**
+ * @author Xiewj
+ * @date 2022/4/1
+ */
+public class FpsUtil {
+
+   static final int oneFps=6;
+
+   public static String getFpsFormat(String measure){
+      int measureInt=Integer.parseInt(measure);
+      int fps=measureInt % oneFps;
+      if (fps!=0){
+          fps=measureInt/oneFps+1;
+      }else {
+         fps=measureInt/oneFps;
+      }
+      return Integer.toString(fps);
+   }
+   static final double oneMeasureTime=180d;
+
+   public static String getDateFormat(String measure){
+      double v =  (1000d/oneMeasureTime)*Double.parseDouble(measure);
+      return String.valueOf(v)+"ms";
+   }
+
+   public static void main(String[] args) {
+      String dateFormat = getDateFormat("97");
+      System.out.println(dateFormat);
+   }
+
+}

+ 154 - 0
src/main/java/com/fdkk/fdkkmeta/util/GenerateUserSig.java

@@ -0,0 +1,154 @@
+package com.fdkk.fdkkmeta.util;
+
+import com.tencentyun.TLSSigAPIv2;
+import org.springframework.stereotype.Component;
+
+@Component
+public class GenerateUserSig {
+
+    /**
+     * 配置为CDN发布、混流的域名
+     *
+     */
+
+    /**
+     * Domain name for CDN publishing and stream mixing
+     */
+    public static final String  CDN_DOMAIN_NAME = "PLACEHOLDER";
+
+    /**
+     * CDN发布功能 混流bizId
+     */
+
+    /**
+     * `bizId` for CDN publishing and stream mixing
+     */
+    public static final int BIZID = 99027;
+
+    /**
+     * CDN发布功能 混流appId
+     */
+
+    /**
+     * `appId` for CDN publishing and stream mixing
+     */
+    public static final int APPID = 1302178016;
+
+    /**
+     * 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
+     *
+     * 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ) 创建应用,即可看到 SDKAppId,
+     * 它是腾讯云用于区分客户的唯一标识。
+     */
+
+    /**
+     * Tencent Cloud `SDKAppID`. Set it to the `SDKAppID` of your account.
+     *
+     * You can view your `SDKAppID` after creating an application in the [TRTC console](https://console.cloud.tencent.com/rav).
+     * `SDKAppID` uniquely identifies a Tencent Cloud account.
+     */
+    public static final int SDKAPPID = 1400653314;
+
+    /**
+     * 签名过期时间,建议不要设置的过短
+     * <p>
+     * 时间单位:秒
+     * 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
+     */
+
+    /**
+     * Signature validity period, which should not be set too short
+     * <p>
+     * Unit: second
+     * Default value: 604800 (7 days)
+     */
+    private static final int EXPIRETIME = 604800;
+
+
+    /**
+     * 计算签名用的加密密钥,获取步骤如下:
+     *
+     * step1. 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ),如果还没有应用就创建一个,
+     * step2. 单击应用信息,并进一步找到“快速上手”部分。
+     * step3. 点击“复制密钥”按钮,复制密钥,请将其拷贝并复制到如下的变量中
+     *
+     * 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
+     * 文档:https://cloud.tencent.com/document/product/647/17275#Server
+     */
+
+    /**
+     * Follow the steps below to obtain the key required for UserSig calculation.
+     *
+     * Step 1. Log in to the [TRTC console](https://console.cloud.tencent.com/rav), and create an application if you don’t have one.
+     * Step 2. Find your application, click “Application Info”, and click the “Quick Start” tab.
+     * Step 3. Copy and paste the key to the code, as shown below.
+     *
+     * Note: this method is for testing only. Before commercial launch, please migrate the UserSig calculation code and key to your backend server to prevent key disclosure and traffic stealing.
+     * Reference: https://cloud.tencent.com/document/product/647/17275#Server
+     */
+    public static final String SECRETKEY = "1e44713ccae3d69c3594fa1ad64188faa5ec669495593777339dcc697973c9e9";
+
+    /**
+     * 计算 UserSig 签名
+     *
+     * 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密。
+     *
+     * @note: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
+     *
+     * 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
+     * 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
+     * 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
+     *
+     * 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
+     * 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
+     *
+     * 文档:https://cloud.tencent.com/document/product/647/17275#Server
+     */
+
+    /**
+     * Calculating UserSig
+     *
+     * The asymmetric encryption algorithm HMAC-SHA256 is used in the function to calculate UserSig based on `SDKAppID`, `UserID`, and `EXPIRETIME`.
+     *
+     * @note: do not use the code below in your commercial app. This is because:
+     *
+     * The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial apps.
+     * `SECRETKEY` in client code can be easily decompiled and reversed, especially on web.
+     * Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
+     *
+     * The correct method is to deploy the `UserSig` calculation code on your project server so that your app can request from your server a `UserSig` that is calculated whenever one is needed.
+     * Given that it is more difficult to hack a server than a client app, server-end calculation can better protect your key.
+     *
+     * Reference: https://cloud.tencent.com/document/product/647/17275#Server
+     */
+    public static String genTestUserSig(String userId) {
+        return GenTLSSignature(SDKAPPID, userId, EXPIRETIME, SECRETKEY);
+    }
+
+    /**
+     * 生成 tls 票据
+     *
+     * @param sdkappid    应用的 appid
+     * @param userId      用户 id
+     * @param expire      有效期,单位是秒
+     * @param userbuf     默认填写null
+     * @param priKeyContent 生成 tls 票据使用的私钥内容
+     * @return 如果出错,会返回为空,或者有异常打印,成功返回有效的票据
+     */
+
+    /**
+     * Generating a TLS Ticket
+     *
+     * @param sdkappid    `appid` of your application
+     * @param userId      User ID
+     * @param expire      Validity period, in seconds
+     * @param priKeyContent Private key required for generating a TLS ticket
+     * @return If an error occurs, an empty string will be returned or exceptions printed. If the operation succeeds, a valid ticket will be returned.
+     */
+    private static String GenTLSSignature(long sdkappid, String userId, long expire, String priKeyContent) {
+        TLSSigAPIv2 api = new TLSSigAPIv2(sdkappid, SECRETKEY);
+        return api.genUserSig(userId,expire);
+    }
+
+
+}

+ 26 - 0
src/main/java/com/fdkk/fdkkmeta/util/TrtcUtil.java

@@ -0,0 +1,26 @@
+package com.fdkk.fdkkmeta.util;
+
+import cn.hutool.core.util.URLUtil;
+import com.fdkk.fdkkmeta.config.TrtcConfig;
+import com.fdkk.fdkkmeta.dto.PushDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Xiewj
+ * @date 2022/3/29
+ */
+@Component
+public class TrtcUtil {
+   @Autowired
+   TrtcConfig trtcConfig;
+
+   public String getPushURl(PushDto dto){
+
+      return trtcConfig.getRtmpHost()+dto.getRoomId();
+   }
+}

+ 41 - 0
src/main/java/com/fdkk/fdkkmeta/util/blobUtil.java

@@ -0,0 +1,41 @@
+//package com.fdkk.fdkkmeta.util;
+//
+//import java.io.*;
+//import java.text.SimpleDateFormat;
+//import java.util.TimeZone;
+//
+///**
+// * @author Xiewj
+// * @date 2022/4/1
+// */
+//public class blobUtil {
+//
+//   static final double oneMeasureTime=180d;
+//
+//   public static String getDateFormat(String measure) throws FileNotFoundException {
+//      //加载文件的位置
+//      File file = new File("C:\\Users\\Administrator\\Desktop\\one\\1.mp4");
+//      //获取文件名
+//
+//      FileInputStream fis = null;
+//      FileOutputStream outputStream = new FileOutputStream("a.txt");
+//      try {
+//         //获取response输出流
+//         fis = new FileInputStream(file);
+//         byte[] buffer = new byte[1024];
+//         int len;
+//         while ((len = fis.read(buffer)) != -1) {
+//            // 输出文件
+//            outputStream.write(buffer,0,len);
+//         }
+//      } catch (Exception e) {
+//      }
+//
+//   }
+//
+//   public static void main(String[] args) {
+//      String dateFormat = getDateFormat("360");
+//      System.out.println(dateFormat);
+//   }
+//
+//}

+ 207 - 0
src/main/java/com/fdkk/fdkkmeta/util/kesar/AStar.java

@@ -0,0 +1,207 @@
+package com.fdkk.fdkkmeta.util.kesar;
+
+import com.fdkk.fdkkmeta.po.RoutePO;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.*;
+
+/**
+ * ClassName: AStar
+ *
+ * @author kesar
+ * @Description: A星算法
+ */
+@Slf4j
+public class AStar {
+    public final static int BAR = 1; // 障碍值
+    public final static int PATH = 2; // 路径
+    private final static double DIRECT_VALUE = 10; // 横竖移动代价
+    private final static double OBLIQUE_VALUE = 14; // 斜移动代价
+
+    private final Queue<Node> openList = new PriorityQueue<Node>(); //  优先队列(升序)
+    private final Map<Integer, Node> closeMap = new HashMap<>();
+
+    /**
+     * 开始算法
+     */
+    public List<Node> start(MapInfo mapInfo) {
+        if (mapInfo == null) {
+            return null;
+        }
+        // clean
+        openList.clear();
+        closeMap.clear();
+        // 开始算法
+        openList.add(mapInfo.start);
+        List<Node> nodes = moveNodes(mapInfo);
+        AStar.log.info("nodes{}", nodes.size());
+//        List<Node> floyd = floyd(nodes, mapInfo);
+//        AStar.log.info("floyd{}", floyd.size());
+        openList.clear();
+        closeMap.clear();
+        mapInfo.maps.clear();
+        return nodes;
+    }
+
+    private List<Node> floyd(List<Node> nodeList, MapInfo mapInfo) {
+        if (nodeList == null) {
+            return null;
+        }
+        List<Node> newPath = new ArrayList<>();
+
+        int size = nodeList.size();
+        if (size > 2) {
+            newPath.add(nodeList.get(0));
+            Node Node1;
+            Node Node2;
+            Node Node3;
+            //删除共线的点
+            for (int i = 1; i < size - 2; i++) {
+                Node1 = nodeList.get(i);
+                Node2 = nodeList.get(i + 1);
+                Node3 = nodeList.get(i + 2);
+                if ((Node2.coord.x - Node1.coord.x) == (Node3.coord.x - Node2.coord.x) && (Node2.coord.y - Node1.coord.y) == (Node3.coord.y - Node2.coord.y)) {
+                    //成线
+                    continue;
+                } else {
+                    newPath.add(nodeList.get(i));
+                }
+            }
+            nodeList.clear();
+        }
+        return newPath;
+    }
+
+    /**
+     * 移动当前结点
+     */
+    private List<Node> moveNodes(MapInfo mapInfo) {
+        while (!openList.isEmpty()) {
+            if (isCoordInClose(mapInfo.end.id)) {
+                List<Node> list = drawPath(mapInfo.maps, mapInfo.end);
+                return list;
+            }
+            Node current = openList.poll();
+            closeMap.put(current.id, current);
+            addNeighborNodeInOpen(mapInfo, current);
+        }
+        return null;
+    }
+
+    /**
+     * 在二维数组中绘制路径
+     */
+    private List<Node> drawPath(Map<Integer, RoutePO> maps, Node end) {
+        if (end == null || maps == null) {
+            return null;
+        }
+        List<Node> list = new ArrayList<Node>();
+        while (end != null) {
+            list.add(end);
+            end = end.parent;
+        }
+        return list;
+    }
+
+    /**
+     * 添加所有邻结点到open表
+     */
+    private void addNeighborNodeInOpen(MapInfo mapInfo, Node current) {
+        int id = current.id;
+        RoutePO routePO = mapInfo.maps.get(id);
+        List<Integer> linkedIds = routePO.getIds();
+        for (int i = 0; i < linkedIds.size(); ++i) {
+            if (linkedIds.get(i)!=-1) {
+                continue;
+            }
+            int linkedId = Integer.valueOf(linkedIds.get(i));
+            //是否在close表里
+            if (canAddNodeToOpen(mapInfo, linkedId)) {
+                Node end = mapInfo.end;
+
+                Double val = AStar.DIRECT_VALUE;
+                if (i > 3) {
+                    val = AStar.OBLIQUE_VALUE;
+                }
+                //乘以点位权重,距离漫游点的就大,优先选择漫游点区域
+                Double G = current.G + val * current.weight; // 计算邻结点的G值
+                Node child = findNodeInOpen(linkedId);
+                if (child == null) {
+                    Double H = calcH1(end.coord, current.coord);
+                    if (isEndNode(end.id, linkedId)) {
+                        child = end;
+                        child.G = G;
+                        child.H = H;
+                    } else {
+                        RoutePO neighItem = mapInfo.maps.get(linkedId);
+                        child = new Node(linkedId, neighItem.getWeight(),
+                                new Coord(neighItem.getX(), neighItem.getY(), neighItem.getZ()), null, G, H, neighItem.getIds());
+                    }
+                    child.parent = current;
+                    openList.add(child);
+                } else if (child.G > G) {
+                    child.G = G;
+                    child.parent = current;
+                    openList.add(child);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * 从Open列表中查找结点
+     */
+    private Node findNodeInOpen(int id) {
+        if (openList.isEmpty()) {
+            return null;
+        }
+        for (Node node : openList) {
+            if (node.id == id) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * 计算两点之间的距离
+     */
+    public Double calcH(Coord end, Coord coord) {
+        return Math.sqrt(Math.pow(end.x - coord.x, 2) + Math.pow(end.y - coord.y, 2)+ Math.pow(end.z - coord.z, 2));
+    }
+
+    /**
+     * 计算两点之间的距离
+     */
+    public Double calcH1(Coord end, Coord coord) {
+        return AStar.DIRECT_VALUE * (Math.sqrt(Math.pow(end.x - coord.x, 2) + Math.pow(end.y - coord.y, 2) + Math.pow(end.z - coord.z, 2)));
+    }
+
+    /**
+     * 判断结点是否是最终结点
+     */
+    private boolean isEndNode(int endId, int id) {
+        return endId == id;
+    }
+
+    /**
+     * 鍒ゆ柇缁撶偣鑳藉惁鏀惧叆Open鍒楄〃
+     */
+    private boolean canAddNodeToOpen(MapInfo mapInfo, int id) {
+
+        // 判断结点是否存在close表
+        return !isCoordInClose(id);
+    }
+
+    /**
+     * 鍒ゆ柇鍧愭爣鏄惁鍦╟lose琛ㄤ腑
+     */
+    private boolean isCoordInClose(int id) {
+        if (closeMap.isEmpty()) {
+            return false;
+        }
+        return closeMap.containsKey(id);
+    }
+}

+ 36 - 0
src/main/java/com/fdkk/fdkkmeta/util/kesar/Coord.java

@@ -0,0 +1,36 @@
+package com.fdkk.fdkkmeta.util.kesar;
+/**
+ *
+ * ClassName: Coord
+ *
+ * @Description: 坐标
+ * @author kesar
+ */
+public class Coord
+{
+
+	public Double x;
+	public Double y;
+	public Double z;
+
+	public Coord(Double x, Double y,Double z)
+	{
+		this.x = x;
+		this.y = y;
+		this.z = z;
+	}
+
+	@Override
+	public boolean equals(Object obj)
+	{
+		if (obj == null) {
+			return false;
+		}
+		if (obj instanceof Coord)
+		{
+			Coord c = (Coord) obj;
+			return x == c.x && y == c.y;
+		}
+		return false;
+	}
+}

+ 178 - 0
src/main/java/com/fdkk/fdkkmeta/util/kesar/GetRoute.java

@@ -0,0 +1,178 @@
+package com.fdkk.fdkkmeta.util.kesar;
+
+import cn.hutool.core.io.LineHandler;
+import cn.hutool.core.io.file.FileReader;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkk.fdkkmeta.dto.RouteDto;
+import com.fdkk.fdkkmeta.po.RoutePO;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class GetRoute {
+
+
+    private static final String inputFilePath = "E:\\test\\project\\age_laser\\routeMap.txt";
+
+
+    private static final Double startX = 5.358192084229412;
+    private static final Double startY = -7.905951689748807;
+    private static final Double startZ = -1.3145928255248511;
+
+    private static final Double endX = -2.143694831230416;
+    private static final Double endY = -3.3754012098200965;
+    private static final Double endZ = -1.1803865408990568;
+
+    private static RoutePO minStartId = null;
+    private static RoutePO minEndId = null;
+
+    private static Node start = null;
+    private static Node end = null;
+    private static final AStar g_AStar = new AStar();
+
+
+    /**
+     * 读取文件,获取文件内容
+     * target_freespace.json
+     * <p>
+     * list 是routeMap的结果集
+     *
+     * @return
+     */
+    public static JSONArray getRoute(String initPath, RouteDto dto) {
+        try {
+            Map<Integer, RoutePO> maps = GetRoute.readMap(initPath, dto);
+            MapInfo info = new MapInfo(maps, GetRoute.start, GetRoute.end);
+            List<Node> path = GetRoute.g_AStar.start(info);
+            List<Integer> ids = new LinkedList<>();
+            for (Node node : path) {
+                ids.add(node.id);
+            }
+            GetRoute.log.info("棋盘获取路线点-所有点{}", JSON.toJSONString(ids));
+            JSONArray jsonArray = GetRoute.convertFromPath(path, dto);
+            List<Integer> ids2 = new LinkedList<>();
+            for (Object o : jsonArray) {
+                JSONObject a = JSON.parseObject(JSONObject.toJSON(o).toString());
+                if (a.getInteger("id") != null) {
+                    ids2.add(a.getInteger("id"));
+                }
+            }
+            GetRoute.log.info(JSON.toJSONString(ids));
+            GetRoute.log.info(JSON.toJSONString(ids2));
+            return jsonArray;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    public static Map<Integer, RoutePO> readMap(String initPath, RouteDto dto)   {
+
+        Double startX = dto.getS_location().getX();
+        Double startY = dto.getS_location().getY();
+        Double startZ = dto.getS_location().getZ();
+
+        Double endX = dto.getE_location().getX();
+        Double endY =  dto.getE_location().getY();
+        Double endZ =  dto.getE_location().getZ();
+
+
+        Coord _start = new Coord(startX, startY, startZ);
+        Coord _end = new Coord(endX, endY, endZ);
+
+        final Double[] startDistance = {1000.0};
+        final Double[] endDistance = {1000.0};
+
+        FileReader fileReader = new FileReader(initPath);
+        Map<Integer, RoutePO> collect = new HashMap<>();
+        fileReader.readLines((LineHandler) s -> {
+            RoutePO po = JSON.toJavaObject(JSON.parseObject(s), RoutePO.class);
+            Coord coord = new Coord(Double.valueOf(po.getX()), Double.valueOf(po.getY()), Double.valueOf(po.getZ()));
+            Double _startDistance = GetRoute.g_AStar.calcH(_start, coord);
+            if (_startDistance < startDistance[0]) {
+                GetRoute.minStartId = po;
+                startDistance[0] = _startDistance;
+            }
+            Double _endDistance = GetRoute.g_AStar.calcH(_end, coord);
+            if (_endDistance < endDistance[0]) {
+                GetRoute.minEndId = po;
+                endDistance[0] = _endDistance;
+            }
+            collect.put(po.getId(), po);
+        });
+        GetRoute.log.info("数量: {}", collect.size());
+        GetRoute.log.info("棋盘获取路线点-开始点{},{}", _start.x, _start.y);
+        GetRoute.log.info("棋盘获取路线点-结束点{},{}", _end.x, _end.y);
+//        超过1.1米就找不到路径
+        if (startDistance[0] > 1.1 || endDistance[0] > 1.1) {
+            GetRoute.log.info("超过1.1米就找不到路径startDistance {},endDistance{}", startDistance[0], endDistance[0]);
+            GetRoute.log.info("开始最近距离{} ", startDistance[0]);
+            GetRoute.log.info("结束最近距离{}", endDistance[0]);
+            return null;
+        }
+
+        Coord startVirtualCoord = new Coord(GetRoute.minStartId.getX(), GetRoute.minStartId.getY(), GetRoute.minStartId.getZ());
+        Coord endVirtualCoord = new Coord(GetRoute.minEndId.getX(), GetRoute.minEndId.getY(), GetRoute.minEndId.getZ());
+        Double H = GetRoute.g_AStar.calcH1(startVirtualCoord, endVirtualCoord);
+        GetRoute.start = new Node(GetRoute.minStartId.getId(), 0.0, startVirtualCoord, null, 0.0, H, GetRoute.minStartId.getIds());
+        GetRoute.end = new Node(GetRoute.minEndId.getId(), 0.0, endVirtualCoord, null, 0.0, 0.0, GetRoute.minEndId.getIds());
+        GetRoute.log.info("开始最近距离{}", startDistance[0]);
+        GetRoute.log.info("结束最近距离{}", endDistance[0]);
+        GetRoute.log.info("开始最近点{}", GetRoute.minStartId);
+        GetRoute.log.info("结束最近点{}", GetRoute.minEndId);
+
+        return collect;
+    }
+
+
+    private static JSONArray convertFromPath(List<Node> mappath, RouteDto dto) {
+        double defaultdistance = 0.36;
+        if (mappath == null || mappath.size() == 0) {
+            return null;
+        }
+
+        Double startX = dto.getS_location().getX();
+        Double startY = dto.getS_location().getY();
+        Double startZ = dto.getS_location().getZ();
+
+        Double endX = dto.getE_location().getX();
+        Double endY =  dto.getE_location().getY();
+        Double endZ =  dto.getE_location().getZ();
+
+
+
+        JSONArray route = new JSONArray();
+
+        //起点不在path上,path的第一个点对应的是格子
+
+        JSONObject start = new JSONObject();
+        start.put("id", GetRoute.start.id);
+        start.put("location", GetRoute.start.coord);
+        route.add(start);
+
+        Double[] virtualEndPosition = new Double[3];
+        for (int i = 0; i < mappath.size(); ++i) {
+            Node node = mappath.get(i);
+            JSONObject item = new JSONObject();
+            item.put("location", node.coord);
+            item.put("id", node.id);
+            virtualEndPosition[0] = node.coord.x;
+            virtualEndPosition[1] = node.coord.y;
+            virtualEndPosition[2] = node.coord.z;
+            route.add(item);
+        }
+        JSONObject end = new JSONObject();
+        start.put("id", GetRoute.end.id);
+        end.put("location", GetRoute.end.coord);
+        route.add(end);
+        return route;
+    }
+
+
+
+}

+ 29 - 0
src/main/java/com/fdkk/fdkkmeta/util/kesar/MapInfo.java

@@ -0,0 +1,29 @@
+package com.fdkk.fdkkmeta.util.kesar;
+
+
+import com.fdkk.fdkkmeta.po.RoutePO;
+
+import java.util.Map;
+
+/**
+ *
+ * ClassName: MapInfo
+ * @Description: 包含地图所需的所有输入数据
+ * @author kesar
+ */
+public class MapInfo
+{
+
+	public Map<Integer, RoutePO>  maps;
+	public Node start; // 起始结点
+	public Node end; // 最终结点
+
+
+
+	public MapInfo(Map<Integer, RoutePO>  maps, Node start, Node end)
+	{
+		this.maps = maps;
+		this.start = start;
+		this.end = end;
+	}
+}

+ 57 - 0
src/main/java/com/fdkk/fdkkmeta/util/kesar/Node.java

@@ -0,0 +1,57 @@
+package com.fdkk.fdkkmeta.util.kesar;
+
+import java.util.List;
+
+/**
+ * ClassName: Node
+ *
+ * @author kesar
+ * @Description: 璺緞缁撶偣
+ */
+public class Node implements Comparable<Node> {
+    public int id;
+    Double weight;
+    public Coord coord; // 坐标
+    Node parent; // 父结点
+    Double G; // G:是个准确的值,是起点到当前结点的代价
+    Double H; // H:是个估值,当前结点到目的结点的估计代价
+    private List<Integer> linkID;
+
+    public List<Integer> getLinkID() {
+        return linkID;
+    }
+
+    public void setLinkID(List<Integer> linkID) {
+        this.linkID = linkID;
+    }
+
+    public Node(int id, Double weight, Coord coord, Node parent, Double g, Double h, List<Integer> linkID) {
+        this.id = id;
+        this.linkID = linkID;
+        this.weight = weight;
+        this.coord = coord;
+        this.parent = parent;
+        G = g;
+        H = h;
+    }
+
+    public Node(Coord coord, Node parent, int g, int h) {
+        this.coord = coord;
+        this.parent = parent;
+        G = (double) g;
+        H = (double) h;
+    }
+
+    @Override
+    public int compareTo(Node o) {
+        if (o == null) {
+            return -1;
+        }
+        if (G + H > o.G + o.H) {
+            return 1;
+        } else if (G + H < o.G + o.H) {
+            return -1;
+        }
+        return 0;
+    }
+}

+ 34 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,34 @@
+socketio:
+  allowCustomRequests: true
+  bossCount: 1
+  host: 192.168.0.152
+  maxFramePayloadLength: 1048576
+  maxHttpContentLength: 1048576
+  pingInterval: 25000
+  pingTimeout: 6000000
+  port: 9099
+  upgradeTimeout: 1000000
+  workCount: 100
+trtc:
+  rtmpHost: "rtmp://rtmp.rtc.qq.com/push/"
+server:
+  port: 9010
+  servlet:
+    context-path: /
+  tomcat:
+    uri-encoding: UTF-8
+    max-threads: 800
+    min-spare-threads: 30
+spring:
+  redis:
+    host: 127.0.0.1
+    port: 6379
+    database: 4
+    password: 1234
+    timeout: 60s
+    lettuce:
+      pool:
+        min-idle: 30
+        max-idle: 8
+        max-active: 8
+        max-wait: 10000

+ 34 - 0
src/main/resources/application-uat.yml

@@ -0,0 +1,34 @@
+socketio:
+  allowCustomRequests: true
+  bossCount: 1
+  host: 0.0.0.0
+  maxFramePayloadLength: 1048576
+  maxHttpContentLength: 1048576
+  pingInterval: 25000
+  pingTimeout: 6000000
+  port: 9099
+  upgradeTimeout: 1000000
+  workCount: 100
+trtc:
+  rtmpHost: "rtmp://rtmp.rtc.qq.com/push/"
+server:
+  port: 9010
+  servlet:
+    context-path: /
+  tomcat:
+    uri-encoding: UTF-8
+    max-threads: 800
+    min-spare-threads: 30
+spring:
+  redis:
+    host: 127.0.0.1
+    port: 6379
+    database: 4
+    password: sxz123321SxZ@
+    timeout: 60s
+    lettuce:
+      pool:
+        min-idle: 30
+        max-idle: 8
+        max-active: 8
+        max-wait: 10000

+ 5 - 0
src/main/resources/application.yml

@@ -0,0 +1,5 @@
+spring:
+  profiles:
+    active: dev
+  jackson:
+    time-zone: GMT+8

+ 25 - 0
src/test/java/com/fdkk/fdkkmeta/FdkkMetaApplicationTests.java

@@ -0,0 +1,25 @@
+package com.fdkk.fdkkmeta;
+
+import cn.hutool.core.io.IoUtil;
+import com.fdkk.fdkkmeta.config.TrtcConfig;
+import com.fdkk.fdkkmeta.redis.RedisCache;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+@SpringBootTest
+class FdkkMetaApplicationTests {
+    @Autowired
+    RedisCache redisService;
+    @Test
+    void contextLoads() throws FileNotFoundException {
+        byte[] bytes = IoUtil.readBytes(new FileInputStream("D:\\video\\o.mp4"));
+        redisService.setCacheObject("test",bytes);
+        byte[] test = redisService.getCacheObject("test");
+        System.out.println(test.length);
+    }
+
+}

+ 132 - 0
startJar.sh

@@ -0,0 +1,132 @@
+APP_NAME=
+APP_DEBUG=
+date=`date`
+usage() {
+    echo "case: sh run.sh [start|stop|restart|status|checkServer]"
+    echo "请类似这样执行 ./*.sh start prod  or  ./*sh restart prod"
+    exit 1
+}
+
+checkEnv(){
+      if [ -z "${APP_NAME}" ] || [ -z "${APP_DEBUG}" ]; then #判断pid是否为空
+           if [[ $1 = 'prod' ]];   then
+                  echo "prod config"
+                  APP_NAME=fdkk-meta-prod.jar
+                  APP_DEBUG=5527
+            elif  [[ $1 = 'uat' ]] ; then
+                  echo "uat config"
+                  APP_NAME=fdkk-meta-uat.jar
+                  APP_DEBUG=5010
+            fi
+     fi
+}
+
+# 判断当前服务是否已经启动的函数
+is_exist(){
+    checkEnv $1
+    pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' ` #根据ps 命令查询当前服务的进程号 赋值给pid"
+    if [ -z "${pid}" ]; then #判断pid是否为空
+        echo "pid 不存在"
+        return 1
+    else
+        echo "pid 存在"
+        return 0
+    fi
+}
+
+
+start(){
+    checkEnv $1
+    is_exist
+    if [ $? -eq "0" ]; then    # [$? -eq "0"] 说明pid不等于空 说明服务正在运行中,将进程号打印出来
+        echo "${APP_NAME} running. pid=${pid}"
+    else
+        nohup java -jar --spring.profiles.active=$1 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${APP_DEBUG} $APP_NAME --spring.profiles.active=$1  > logs.log 2>error.log &  # 说明pid为空
+        # 执行java -jar 命令启动服务
+        echo "${APP_NAME} started启动"
+    fi
+}
+
+
+stop(){
+    echo "执行 stop 方法"
+    checkEnv $1
+    is_exist
+    if [ $? -eq "0" ]; then    # [$? -eq "0"] 说明pid不等于空 说明服务正在运行中,将进程号杀死
+        kill -9 $pid
+        echo "${pid} stopped-停止"
+    else
+        echo "${APP_NAME} 没有运行"
+    fi
+}
+
+
+status(){
+    echo "执行 status 方法"
+    checkEnv $1
+    is_exist
+    if [ $? -eq "0" ]; then
+        echo "${APP_NAME} running-启动. Pid is ${pid}"
+    else
+        echo "${APP_NAME} 没有运行"
+    fi
+}
+
+checkServer(){
+    echo "执行 status 方法"
+    checkEnv $1
+    is_exist
+    if [ $? -eq "0" ]; then
+        echo "${APP_NAME} running-正在运行. Pid is ${pid}"
+        echo `date +%Y-%m-%d` `date +%H:%M:%S` ${APP_NAME} "running-正在运行. Pid is ${pid}" >> check.log
+        exit 0
+    else
+        echo "${APP_NAME} 没有运行,即将重启"
+        echo `date +%Y-%m-%d` `date +%H:%M:%S` ${APP_NAME} "没有运行,即将重启" >> check.log
+        restart  $1
+    fi
+}
+
+# 重启命令其实就是先执行关闭命令 再执行重启命令
+restart(){
+        echo "执行 restart 方法"
+        checkEnv $1
+        is_exist
+        if [ $? -eq "0" ]; then    # [$? -eq "0"] 说明pid不等于空 说明服务正在运行中,将进程号杀死
+            kill -9 $pid
+            echo "${pid} stopped-停止"
+        else
+            echo "${APP_NAME} 没有运行"
+        fi
+        sleep 5
+        is_exist
+        if [ $? -eq "0" ]; then    # [$? -eq "0"] 说明pid不等于空 说明服务正在运行中,将进程号打印出来
+            echo "${APP_NAME} running. pid=${pid}"
+        else
+            nohup java -jar  -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${APP_DEBUG} $APP_NAME --spring.profiles.active=$1  > logs.log 2>error.log &  # 说明pid为空 执行java -jar 命令启动服务
+            echo "${APP_NAME} started启动"
+        fi
+}
+
+
+# 这里的$1 取的是当前输入命令 的第二个参数 ./start.sh start
+case "$1" in
+    "start")
+        start $2
+        ;;
+    "stop")
+        stop $2
+        ;;
+    "status")
+        status $2
+        ;;
+    "restart")
+        restart $2
+        ;;
+    "checkServer")
+        checkServer $2
+        ;;
+    *)
+    usage
+    ;;
+esac