Commit 70091f29f2c3c3f974ffc2cc8f140db9f992ca0e
0 parents
初始提交
Showing
48 changed files
with
4698 additions
and
0 deletions
pom.xml
0 → 100644
| 1 | +++ a/pom.xml | |
| 1 | +<?xml version="1.0"?> | |
| 2 | +<project | |
| 3 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |
| 4 | + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
| 5 | + <modelVersion>4.0.0</modelVersion> | |
| 6 | + <parent> | |
| 7 | + <groupId>org.springframework.boot</groupId> | |
| 8 | + <artifactId>spring-boot-starter-parent</artifactId> | |
| 9 | + <version>1.5.10.RELEASE</version> | |
| 10 | + </parent> | |
| 11 | + | |
| 12 | + <groupId>com.genersoft</groupId> | |
| 13 | + <artifactId>wvp</artifactId> | |
| 14 | + <name>web video platform</name> | |
| 15 | + | |
| 16 | + <properties> | |
| 17 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
| 18 | + | |
| 19 | + <hystrix.version>1.5.12</hystrix.version> | |
| 20 | + <!-- 依赖版本 --> | |
| 21 | + <mapper.version>3.4.0</mapper.version> | |
| 22 | + <mybatis.version>3.3.1</mybatis.version> | |
| 23 | + <mybatis.spring.version>1.2.4</mybatis.spring.version> | |
| 24 | + <pagehelper.version>4.1.1</pagehelper.version> | |
| 25 | + <snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory> | |
| 26 | + <asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory> | |
| 27 | + <generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory> | |
| 28 | + <asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory> | |
| 29 | + <asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory> | |
| 30 | + <gson.version>2.8.0</gson.version> | |
| 31 | + <jedis.version>3.0.1</jedis.version> | |
| 32 | + <jsonlib.version>2.4</jsonlib.version> | |
| 33 | + </properties> | |
| 34 | + | |
| 35 | + <dependencies> | |
| 36 | + <dependency> | |
| 37 | + <groupId>org.springframework.boot</groupId> | |
| 38 | + <artifactId>spring-boot-starter-jdbc</artifactId> | |
| 39 | + </dependency> | |
| 40 | + <dependency> | |
| 41 | + <groupId>org.springframework.boot</groupId> | |
| 42 | + <artifactId>spring-boot-starter-undertow</artifactId> | |
| 43 | + </dependency> | |
| 44 | + <dependency> | |
| 45 | + <groupId>org.springframework.boot</groupId> | |
| 46 | + <artifactId>spring-boot-starter-web</artifactId> | |
| 47 | + </dependency> | |
| 48 | + <dependency> | |
| 49 | + <groupId>org.springframework</groupId> | |
| 50 | + <artifactId>spring-context</artifactId> | |
| 51 | + </dependency> | |
| 52 | + | |
| 53 | + | |
| 54 | + <!-- druid --> | |
| 55 | + <dependency> | |
| 56 | + <groupId>com.alibaba</groupId> | |
| 57 | + <artifactId>druid</artifactId> | |
| 58 | + <version>1.0.11</version> | |
| 59 | + </dependency> | |
| 60 | + <dependency> | |
| 61 | + <groupId>mysql</groupId> | |
| 62 | + <artifactId>mysql-connector-java</artifactId> | |
| 63 | + <version>5.1.30</version> | |
| 64 | + </dependency> | |
| 65 | + | |
| 66 | + <!--Mybatis --> | |
| 67 | + <dependency> | |
| 68 | + <groupId>org.mybatis</groupId> | |
| 69 | + <artifactId>mybatis</artifactId> | |
| 70 | + <version>${mybatis.version}</version> | |
| 71 | + </dependency> | |
| 72 | + <dependency> | |
| 73 | + <groupId>org.mybatis</groupId> | |
| 74 | + <artifactId>mybatis-spring</artifactId> | |
| 75 | + <version>${mybatis.spring.version}</version> | |
| 76 | + </dependency> | |
| 77 | + | |
| 78 | + <!--分页插件 --> | |
| 79 | + <dependency> | |
| 80 | + <groupId>com.github.pagehelper</groupId> | |
| 81 | + <artifactId>pagehelper</artifactId> | |
| 82 | + <version>${pagehelper.version}</version> | |
| 83 | + </dependency> | |
| 84 | + | |
| 85 | + <!--通用Mapper --> | |
| 86 | + <dependency> | |
| 87 | + <groupId>tk.mybatis</groupId> | |
| 88 | + <artifactId>mapper</artifactId> | |
| 89 | + <version>${mapper.version}</version> | |
| 90 | + </dependency> | |
| 91 | + <dependency> | |
| 92 | + <groupId>org.apache.commons</groupId> | |
| 93 | + <artifactId>commons-lang3</artifactId> | |
| 94 | + <version>3.4</version> | |
| 95 | + </dependency> | |
| 96 | + <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> | |
| 97 | + <dependency> | |
| 98 | + <groupId>com.alibaba</groupId> | |
| 99 | + <artifactId>fastjson</artifactId> | |
| 100 | + <version>1.2.33</version> | |
| 101 | + </dependency> | |
| 102 | + | |
| 103 | + <!--Swagger2 --> | |
| 104 | + <!--在线文档 --> | |
| 105 | + <dependency> | |
| 106 | + <groupId>io.springfox</groupId> | |
| 107 | + <artifactId>springfox-swagger2</artifactId> | |
| 108 | + <version>2.6.1</version> | |
| 109 | + </dependency> | |
| 110 | + <dependency> | |
| 111 | + <groupId>io.springfox</groupId> | |
| 112 | + <artifactId>springfox-swagger-ui</artifactId> | |
| 113 | + <version>2.6.1</version> | |
| 114 | + </dependency> | |
| 115 | + | |
| 116 | + <!-- 日志相关 --> | |
| 117 | + <dependency> | |
| 118 | + <groupId>org.springframework.boot</groupId> | |
| 119 | + <artifactId>spring-boot-starter-aop</artifactId> | |
| 120 | + </dependency> | |
| 121 | + | |
| 122 | + <dependency> | |
| 123 | + <groupId>javax.sip</groupId> | |
| 124 | + <artifactId>jain-sip-ri</artifactId> | |
| 125 | + <version>1.3.0-91</version> | |
| 126 | + <scope>provided</scope> | |
| 127 | + </dependency> | |
| 128 | + <dependency> | |
| 129 | + <groupId>org.dom4j</groupId> | |
| 130 | + <artifactId>dom4j</artifactId> | |
| 131 | + <version>2.1.1</version> | |
| 132 | + </dependency> | |
| 133 | + <dependency> | |
| 134 | + <groupId>com.google.code.gson</groupId> | |
| 135 | + <artifactId>gson</artifactId> | |
| 136 | + </dependency> | |
| 137 | + <dependency> | |
| 138 | + <groupId>org.springframework.data</groupId> | |
| 139 | + <artifactId>spring-data-redis</artifactId> | |
| 140 | + <version>1.8.4.RELEASE</version> | |
| 141 | + </dependency> | |
| 142 | + <dependency> | |
| 143 | + <groupId>redis.clients</groupId> | |
| 144 | + <artifactId>jedis</artifactId> | |
| 145 | + <version>2.9.0</version> | |
| 146 | + </dependency> | |
| 147 | + | |
| 148 | + </dependencies> | |
| 149 | + | |
| 150 | + <build> | |
| 151 | + <plugins> | |
| 152 | + | |
| 153 | + <plugin> | |
| 154 | + <groupId>org.springframework.boot</groupId> | |
| 155 | + <artifactId>spring-boot-maven-plugin</artifactId> | |
| 156 | + </plugin> | |
| 157 | + <plugin> | |
| 158 | + <groupId>org.apache.maven.plugins</groupId> | |
| 159 | + <artifactId>maven-compiler-plugin</artifactId> | |
| 160 | + <configuration> | |
| 161 | + <source>1.8</source> | |
| 162 | + <target>1.8</target> | |
| 163 | + </configuration> | |
| 164 | + </plugin> | |
| 165 | + | |
| 166 | + <plugin> | |
| 167 | + <groupId>org.apache.maven.plugins</groupId> | |
| 168 | + <artifactId>maven-surefire-plugin</artifactId> | |
| 169 | + </plugin> | |
| 170 | + | |
| 171 | + </plugins> | |
| 172 | + </build> | |
| 173 | +</project> | ... | ... |
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java | |
| 1 | +package com.genersoft.iot.vmp; | |
| 2 | + | |
| 3 | +import java.util.logging.LogManager; | |
| 4 | + | |
| 5 | +import org.springframework.boot.SpringApplication; | |
| 6 | +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | |
| 7 | +import org.springframework.boot.autoconfigure.SpringBootApplication; | |
| 8 | + | |
| 9 | +@SpringBootApplication | |
| 10 | +//@EnableEurekaClient | |
| 11 | +//@EnableTransactionManagement | |
| 12 | +//@EnableFeignClients(basePackages = { "com.genersoft.iot.vmp", "org.integrain" }) | |
| 13 | +//@ServletComponentScan("com.genersoft.iot.vmp") | |
| 14 | +@EnableAutoConfiguration | |
| 15 | +public class VManageBootstrap extends LogManager { | |
| 16 | + public static void main(String[] args) { | |
| 17 | + SpringApplication.run(VManageBootstrap.class, args); | |
| 18 | + } | |
| 19 | + | |
| 20 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java | |
| 1 | +package com.genersoft.iot.vmp.common; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @Description:TODO(这里用一句话描述这个类的作用) | |
| 5 | + * @author: songww | |
| 6 | + * @date: 2019年5月30日 下午3:04:04 | |
| 7 | + * | |
| 8 | + */ | |
| 9 | +public class VideoManagerConstants { | |
| 10 | + | |
| 11 | + public static final String CACHEKEY_PREFIX = "VMP_deviceId_"; | |
| 12 | + | |
| 13 | + public static final String KEEPLIVEKEY_PREFIX = "VMP_keeplive_"; | |
| 14 | + | |
| 15 | + public static final String EVENT_ONLINE_REGISTER = "1"; | |
| 16 | + | |
| 17 | + public static final String EVENT_ONLINE_KEEPLIVE = "2"; | |
| 18 | + | |
| 19 | + public static final String EVENT_OUTLINE_UNREGISTER = "1"; | |
| 20 | + | |
| 21 | + public static final String EVENT_OUTLINE_TIMEOUT = "2"; | |
| 22 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java | |
| 1 | +package com.genersoft.iot.vmp.conf; | |
| 2 | + | |
| 3 | +import org.springframework.cache.annotation.CachingConfigurerSupport; | |
| 4 | +import org.springframework.context.annotation.Bean; | |
| 5 | +import org.springframework.context.annotation.Configuration; | |
| 6 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
| 7 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 8 | +import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 9 | +import org.springframework.data.redis.serializer.StringRedisSerializer; | |
| 10 | + | |
| 11 | +import com.alibaba.fastjson.parser.ParserConfig; | |
| 12 | +import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * @Description:Redis中间件配置类 | |
| 16 | + * @author: songww | |
| 17 | + * @date: 2019年5月30日 上午10:58:25 | |
| 18 | + * | |
| 19 | + */ | |
| 20 | +@Configuration | |
| 21 | +// @EnableCaching | |
| 22 | +public class RedisConfig extends CachingConfigurerSupport { | |
| 23 | + | |
| 24 | + @Bean("redisTemplate") | |
| 25 | + public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | |
| 26 | + RedisTemplate<Object, Object> template = new RedisTemplate<>(); | |
| 27 | + template.setConnectionFactory(redisConnectionFactory); | |
| 28 | + ParserConfig.getGlobalInstance().setAutoTypeSupport(true); | |
| 29 | + FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<Object>(Object.class); | |
| 30 | + // value值的序列化采用fastJsonRedisSerializer | |
| 31 | + template.setValueSerializer(serializer); | |
| 32 | + template.setHashValueSerializer(serializer); | |
| 33 | + // key的序列化采用StringRedisSerializer | |
| 34 | + template.setKeySerializer(new StringRedisSerializer()); | |
| 35 | + template.setHashKeySerializer(new StringRedisSerializer()); | |
| 36 | + | |
| 37 | + template.setConnectionFactory(redisConnectionFactory); | |
| 38 | + return template; | |
| 39 | + } | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器 | |
| 43 | + * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理 | |
| 44 | + * | |
| 45 | + * @param connectionFactory | |
| 46 | + * @param listenerAdapter | |
| 47 | + * @return | |
| 48 | + */ | |
| 49 | + @Bean | |
| 50 | + RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { | |
| 51 | + | |
| 52 | + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); | |
| 53 | + container.setConnectionFactory(connectionFactory); | |
| 54 | + return container; | |
| 55 | + } | |
| 56 | +// @Bean | |
| 57 | +// RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, | |
| 58 | +// MessageListenerAdapter listenerAdapter) { | |
| 59 | +// | |
| 60 | +// RedisMessageListenerContainer container = new RedisMessageListenerContainer(); | |
| 61 | +// container.setConnectionFactory(connectionFactory); | |
| 62 | +// // 订阅了一个叫通道 | |
| 63 | +// container.addMessageListener(listenerAdapter, new PatternTopic(VideoManagerConstants.KEEPLIVEKEY_PREFIX+"*")); | |
| 64 | +// // 这个container 可以添加多个 messageListener | |
| 65 | +// return container; | |
| 66 | +// } | |
| 67 | + | |
| 68 | +// /** | |
| 69 | +// * 消息监听器适配器,绑定消息处理器,利用反射技术调用消息处理器的业务方法 | |
| 70 | +// * @param receiver | |
| 71 | +// * @return | |
| 72 | +// */ | |
| 73 | +// @Bean | |
| 74 | +// MessageListenerAdapter listenerAdapter(MessageReceiver receiver) { | |
| 75 | +// //这个地方 是给messageListenerAdapter 传入一个消息接受的处理器,利用反射的方法调用“receiveMessage” | |
| 76 | +// //也有好几个重载方法,这边默认调用处理器的方法 叫handleMessage 可以自己到源码里面看 | |
| 77 | +// return new MessageListenerAdapter(receiver, "receiveMessage"); | |
| 78 | +// } | |
| 79 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java | |
| 1 | +package com.genersoft.iot.vmp.conf; | |
| 2 | + | |
| 3 | +import org.springframework.beans.factory.annotation.Value; | |
| 4 | +import org.springframework.context.annotation.Configuration; | |
| 5 | + | |
| 6 | +@Configuration | |
| 7 | +public class SipConfig { | |
| 8 | + | |
| 9 | + @Value("${sip.ip}") | |
| 10 | + String sipIp; | |
| 11 | + @Value("${sip.port}") | |
| 12 | + Integer sipPort; | |
| 13 | + @Value("${sip.domain}") | |
| 14 | + String sipDomain; | |
| 15 | + @Value("${sip.password}") | |
| 16 | + String sipPassword; | |
| 17 | + @Value("${media.ip}") | |
| 18 | + String mediaIp; | |
| 19 | + | |
| 20 | + @Value("${media.port}") | |
| 21 | + Integer mediaPort; | |
| 22 | + | |
| 23 | + @Value("${sip.ptz.speed:50}") | |
| 24 | + Integer speed; | |
| 25 | + | |
| 26 | + public String getSipIp() { | |
| 27 | + return sipIp; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public void setSipIp(String sipIp) { | |
| 31 | + this.sipIp = sipIp; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public Integer getSipPort() { | |
| 35 | + return sipPort; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public void setSipPort(Integer sipPort) { | |
| 39 | + this.sipPort = sipPort; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public String getSipDomain() { | |
| 43 | + return sipDomain; | |
| 44 | + } | |
| 45 | + | |
| 46 | + public void setSipDomain(String sipDomain) { | |
| 47 | + this.sipDomain = sipDomain; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public String getSipPassword() { | |
| 51 | + return sipPassword; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public void setSipPassword(String sipPassword) { | |
| 55 | + this.sipPassword = sipPassword; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public String getMediaIp() { | |
| 59 | + return mediaIp; | |
| 60 | + } | |
| 61 | + | |
| 62 | + public void setMediaIp(String mediaIp) { | |
| 63 | + this.mediaIp = mediaIp; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public Integer getMediaPort() { | |
| 67 | + return mediaPort; | |
| 68 | + } | |
| 69 | + | |
| 70 | + public void setMediaPort(Integer mediaPort) { | |
| 71 | + this.mediaPort = mediaPort; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public Integer getSpeed() { | |
| 75 | + return speed; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public void setSpeed(Integer speed) { | |
| 79 | + this.speed = speed; | |
| 80 | + } | |
| 81 | + | |
| 82 | + | |
| 83 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/conf/VManagerConfig.java | |
| 1 | +package com.genersoft.iot.vmp.conf; | |
| 2 | + | |
| 3 | +import org.springframework.beans.factory.annotation.Value; | |
| 4 | +import org.springframework.context.annotation.Configuration; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @Description:TODO(这里用一句话描述这个类的作用) | |
| 8 | + * @author: songww | |
| 9 | + * @date: 2020年5月6日 下午2:46:00 | |
| 10 | + */ | |
| 11 | +@Configuration("vmConfig") | |
| 12 | +public class VManagerConfig { | |
| 13 | + | |
| 14 | + @Value("${spring.application.database:redis}") | |
| 15 | + private String database; | |
| 16 | + | |
| 17 | + public String getDatabase() { | |
| 18 | + return database; | |
| 19 | + } | |
| 20 | + | |
| 21 | + public void setDatabase(String database) { | |
| 22 | + this.database = database; | |
| 23 | + } | |
| 24 | + | |
| 25 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181; | |
| 2 | + | |
| 3 | +import java.util.Properties; | |
| 4 | + | |
| 5 | +import javax.sip.DialogTerminatedEvent; | |
| 6 | +import javax.sip.IOExceptionEvent; | |
| 7 | +import javax.sip.ListeningPoint; | |
| 8 | +import javax.sip.RequestEvent; | |
| 9 | +import javax.sip.ResponseEvent; | |
| 10 | +import javax.sip.ServerTransaction; | |
| 11 | +import javax.sip.SipFactory; | |
| 12 | +import javax.sip.SipListener; | |
| 13 | +import javax.sip.SipProvider; | |
| 14 | +import javax.sip.SipStack; | |
| 15 | +import javax.sip.TimeoutEvent; | |
| 16 | +import javax.sip.TransactionAlreadyExistsException; | |
| 17 | +import javax.sip.TransactionTerminatedEvent; | |
| 18 | +import javax.sip.TransactionUnavailableException; | |
| 19 | +import javax.sip.address.AddressFactory; | |
| 20 | +import javax.sip.header.HeaderFactory; | |
| 21 | +import javax.sip.header.ViaHeader; | |
| 22 | +import javax.sip.message.MessageFactory; | |
| 23 | +import javax.sip.message.Request; | |
| 24 | +import javax.sip.message.Response; | |
| 25 | + | |
| 26 | +import org.slf4j.Logger; | |
| 27 | +import org.slf4j.LoggerFactory; | |
| 28 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 29 | +import org.springframework.context.annotation.Bean; | |
| 30 | +import org.springframework.stereotype.Component; | |
| 31 | + | |
| 32 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 33 | +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory; | |
| 34 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 35 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | |
| 36 | + | |
| 37 | +import gov.nist.javax.sip.SipStackImpl; | |
| 38 | + | |
| 39 | +@Component | |
| 40 | +public class SipLayer implements SipListener{ | |
| 41 | + | |
| 42 | + private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); | |
| 43 | + | |
| 44 | + @Autowired | |
| 45 | + private SipConfig config; | |
| 46 | + | |
| 47 | + private SipProvider tcpSipProvider; | |
| 48 | + | |
| 49 | + private SipProvider udpSipProvider; | |
| 50 | + | |
| 51 | + @Autowired | |
| 52 | + private SIPProcessorFactory processorFactory; | |
| 53 | + | |
| 54 | + private SipStack sipStack; | |
| 55 | + | |
| 56 | + private AddressFactory addressFactory; | |
| 57 | + private HeaderFactory headerFactory; | |
| 58 | + private MessageFactory messageFactory; | |
| 59 | + | |
| 60 | + @Bean | |
| 61 | + private boolean initSipServer() throws Exception { | |
| 62 | + SipFactory sipFactory = SipFactory.getInstance(); | |
| 63 | + sipFactory.setPathName("gov.nist"); | |
| 64 | + headerFactory = sipFactory.createHeaderFactory(); | |
| 65 | + addressFactory = sipFactory.createAddressFactory(); | |
| 66 | + messageFactory = sipFactory.createMessageFactory(); | |
| 67 | + | |
| 68 | + Properties properties = new Properties(); | |
| 69 | + properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); | |
| 70 | + properties.setProperty("javax.sip.IP_ADDRESS", config.getSipIp()); | |
| 71 | + /** | |
| 72 | + * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = | |
| 73 | + * 0; public static final int TRACE_MESSAGES = 16; public static final int | |
| 74 | + * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32; | |
| 75 | + */ | |
| 76 | + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "16"); | |
| 77 | + properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log"); | |
| 78 | + properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log"); | |
| 79 | + sipStack = (SipStackImpl) sipFactory.createSipStack(properties); | |
| 80 | + | |
| 81 | + try { | |
| 82 | + startTcpListener(); | |
| 83 | + startUdpListener(); | |
| 84 | + } catch (Exception e) { | |
| 85 | + logger.error("Sip Server 启动失败! port {"+config.getSipPort()+"}"); | |
| 86 | + e.printStackTrace(); | |
| 87 | + throw e; | |
| 88 | + } | |
| 89 | + logger.info("Sip Server 启动成功 port {"+config.getSipPort()+"}"); | |
| 90 | + return true; | |
| 91 | + } | |
| 92 | + | |
| 93 | + private void startTcpListener() throws Exception { | |
| 94 | + ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "TCP"); | |
| 95 | + tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint); | |
| 96 | + tcpSipProvider.addSipListener(this); | |
| 97 | + } | |
| 98 | + | |
| 99 | + private void startUdpListener() throws Exception { | |
| 100 | + ListeningPoint udpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "UDP"); | |
| 101 | + udpSipProvider = sipStack.createSipProvider(udpListeningPoint); | |
| 102 | + udpSipProvider.addSipListener(this); | |
| 103 | + } | |
| 104 | + | |
| 105 | + /** | |
| 106 | + * SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a | |
| 107 | + * new request arrives. | |
| 108 | + */ | |
| 109 | + @Override | |
| 110 | + public void processRequest(RequestEvent evt) { | |
| 111 | + ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt); | |
| 112 | + processor.process(evt, this, getServerTransaction(evt)); | |
| 113 | + } | |
| 114 | + | |
| 115 | + @Override | |
| 116 | + public void processResponse(ResponseEvent evt) { | |
| 117 | + Response response = evt.getResponse(); | |
| 118 | + int status = response.getStatusCode(); | |
| 119 | + if ((status >= 200) && (status < 300)) { // Success! | |
| 120 | + ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); | |
| 121 | + processor.process(evt,this,config); | |
| 122 | + } else { | |
| 123 | + logger.warn("接收到失败的response响应!status:"+status+",message:"+response.getContent().toString()); | |
| 124 | + } | |
| 125 | + //trying不会回复 | |
| 126 | + if(status == Response.TRYING){ | |
| 127 | + | |
| 128 | + } | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * <p>Title: processTimeout</p> | |
| 133 | + * <p>Description: </p> | |
| 134 | + * @param timeoutEvent | |
| 135 | + */ | |
| 136 | + @Override | |
| 137 | + public void processTimeout(TimeoutEvent timeoutEvent) { | |
| 138 | + // TODO Auto-generated method stub | |
| 139 | + | |
| 140 | + } | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * <p>Title: processIOException</p> | |
| 144 | + * <p>Description: </p> | |
| 145 | + * @param exceptionEvent | |
| 146 | + */ | |
| 147 | + @Override | |
| 148 | + public void processIOException(IOExceptionEvent exceptionEvent) { | |
| 149 | + // TODO Auto-generated method stub | |
| 150 | + | |
| 151 | + } | |
| 152 | + | |
| 153 | + /** | |
| 154 | + * <p>Title: processTransactionTerminated</p> | |
| 155 | + * <p>Description: </p> | |
| 156 | + * @param transactionTerminatedEvent | |
| 157 | + */ | |
| 158 | + @Override | |
| 159 | + public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { | |
| 160 | + // TODO Auto-generated method stub | |
| 161 | + | |
| 162 | + } | |
| 163 | + | |
| 164 | + /** | |
| 165 | + * <p>Title: processDialogTerminated</p> | |
| 166 | + * <p>Description: </p> | |
| 167 | + * @param dialogTerminatedEvent | |
| 168 | + */ | |
| 169 | + @Override | |
| 170 | + public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { | |
| 171 | + // TODO Auto-generated method stub | |
| 172 | + | |
| 173 | + } | |
| 174 | + | |
| 175 | + private ServerTransaction getServerTransaction(RequestEvent evt) { | |
| 176 | + Request request = evt.getRequest(); | |
| 177 | + ServerTransaction serverTransaction = evt.getServerTransaction(); | |
| 178 | + // 判断TCP还是UDP | |
| 179 | + boolean isTcp = false; | |
| 180 | + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | |
| 181 | + String transport = reqViaHeader.getTransport(); | |
| 182 | + if (transport.equals("TCP")) { | |
| 183 | + isTcp = true; | |
| 184 | + } | |
| 185 | + | |
| 186 | + if (serverTransaction == null) { | |
| 187 | + try { | |
| 188 | + if (isTcp) { | |
| 189 | + serverTransaction = tcpSipProvider.getNewServerTransaction(request); | |
| 190 | + } else { | |
| 191 | + serverTransaction = udpSipProvider.getNewServerTransaction(request); | |
| 192 | + } | |
| 193 | + } catch (TransactionAlreadyExistsException e) { | |
| 194 | + e.printStackTrace(); | |
| 195 | + } catch (TransactionUnavailableException e) { | |
| 196 | + e.printStackTrace(); | |
| 197 | + } | |
| 198 | + } | |
| 199 | + return serverTransaction; | |
| 200 | + } | |
| 201 | + | |
| 202 | + | |
| 203 | + public AddressFactory getAddressFactory() { | |
| 204 | + return addressFactory; | |
| 205 | + } | |
| 206 | + | |
| 207 | + public HeaderFactory getHeaderFactory() { | |
| 208 | + return headerFactory; | |
| 209 | + } | |
| 210 | + | |
| 211 | + public MessageFactory getMessageFactory() { | |
| 212 | + return messageFactory; | |
| 213 | + } | |
| 214 | + | |
| 215 | + public SipProvider getTcpSipProvider() { | |
| 216 | + return tcpSipProvider; | |
| 217 | + } | |
| 218 | + | |
| 219 | + public SipProvider getUdpSipProvider() { | |
| 220 | + return udpSipProvider; | |
| 221 | + } | |
| 222 | + | |
| 223 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java | |
| 1 | +/* | |
| 2 | +* Conditions Of Use | |
| 3 | +* | |
| 4 | +* This software was developed by employees of the National Institute of | |
| 5 | +* Standards and Technology (NIST), an agency of the Federal Government. | |
| 6 | +* Pursuant to title 15 Untied States Code Section 105, works of NIST | |
| 7 | +* employees are not subject to copyright protection in the United States | |
| 8 | +* and are considered to be in the public domain. As a result, a formal | |
| 9 | +* license is not needed to use the software. | |
| 10 | +* | |
| 11 | +* This software is provided by NIST as a service and is expressly | |
| 12 | +* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED | |
| 13 | +* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF | |
| 14 | +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT | |
| 15 | +* AND DATA ACCURACY. NIST does not warrant or make any representations | |
| 16 | +* regarding the use of the software or the results thereof, including but | |
| 17 | +* not limited to the correctness, accuracy, reliability or usefulness of | |
| 18 | +* the software. | |
| 19 | +* | |
| 20 | +* Permission to use this software is contingent upon your acceptance | |
| 21 | +* of the terms of this agreement | |
| 22 | +* | |
| 23 | +* . | |
| 24 | +* | |
| 25 | +*/ | |
| 26 | +package com.genersoft.iot.vmp.gb28181.auth; | |
| 27 | + | |
| 28 | +import java.security.MessageDigest; | |
| 29 | +import java.security.NoSuchAlgorithmException; | |
| 30 | +import java.util.Date; | |
| 31 | +import java.util.Random; | |
| 32 | + | |
| 33 | +import javax.sip.address.URI; | |
| 34 | +import javax.sip.header.AuthorizationHeader; | |
| 35 | +import javax.sip.header.HeaderFactory; | |
| 36 | +import javax.sip.header.WWWAuthenticateHeader; | |
| 37 | +import javax.sip.message.Request; | |
| 38 | +import javax.sip.message.Response; | |
| 39 | + | |
| 40 | +import gov.nist.core.InternalErrorHandler; | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * Implements the HTTP digest authentication method server side functionality. | |
| 44 | + * | |
| 45 | + * @author M. Ranganathan | |
| 46 | + * @author Marc Bednarek | |
| 47 | + */ | |
| 48 | + | |
| 49 | +public class DigestServerAuthenticationHelper { | |
| 50 | + | |
| 51 | + private MessageDigest messageDigest; | |
| 52 | + | |
| 53 | + public static final String DEFAULT_ALGORITHM = "MD5"; | |
| 54 | + public static final String DEFAULT_SCHEME = "Digest"; | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + /** to hex converter */ | |
| 60 | + private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6', | |
| 61 | + '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * Default constructor. | |
| 65 | + * @throws NoSuchAlgorithmException | |
| 66 | + */ | |
| 67 | + public DigestServerAuthenticationHelper() | |
| 68 | + throws NoSuchAlgorithmException { | |
| 69 | + messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM); | |
| 70 | + } | |
| 71 | + | |
| 72 | + public static String toHexString(byte b[]) { | |
| 73 | + int pos = 0; | |
| 74 | + char[] c = new char[b.length * 2]; | |
| 75 | + for (int i = 0; i < b.length; i++) { | |
| 76 | + c[pos++] = toHex[(b[i] >> 4) & 0x0F]; | |
| 77 | + c[pos++] = toHex[b[i] & 0x0f]; | |
| 78 | + } | |
| 79 | + return new String(c); | |
| 80 | + } | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * Generate the challenge string. | |
| 84 | + * | |
| 85 | + * @return a generated nonce. | |
| 86 | + */ | |
| 87 | + private String generateNonce() { | |
| 88 | + // Get the time of day and run MD5 over it. | |
| 89 | + Date date = new Date(); | |
| 90 | + long time = date.getTime(); | |
| 91 | + Random rand = new Random(); | |
| 92 | + long pad = rand.nextLong(); | |
| 93 | + String nonceString = (new Long(time)).toString() | |
| 94 | + + (new Long(pad)).toString(); | |
| 95 | + byte mdbytes[] = messageDigest.digest(nonceString.getBytes()); | |
| 96 | + // Convert the mdbytes array into a hex string. | |
| 97 | + return toHexString(mdbytes); | |
| 98 | + } | |
| 99 | + | |
| 100 | + public Response generateChallenge(HeaderFactory headerFactory, Response response, String realm) { | |
| 101 | + try { | |
| 102 | + WWWAuthenticateHeader proxyAuthenticate = headerFactory | |
| 103 | + .createWWWAuthenticateHeader(DEFAULT_SCHEME); | |
| 104 | + proxyAuthenticate.setParameter("realm", realm); | |
| 105 | + proxyAuthenticate.setParameter("nonce", generateNonce()); | |
| 106 | + proxyAuthenticate.setParameter("opaque", ""); | |
| 107 | + proxyAuthenticate.setParameter("stale", "FALSE"); | |
| 108 | + proxyAuthenticate.setParameter("algorithm", DEFAULT_ALGORITHM); | |
| 109 | + response.setHeader(proxyAuthenticate); | |
| 110 | + } catch (Exception ex) { | |
| 111 | + InternalErrorHandler.handleException(ex); | |
| 112 | + } | |
| 113 | + return response; | |
| 114 | + } | |
| 115 | + /** | |
| 116 | + * Authenticate the inbound request. | |
| 117 | + * | |
| 118 | + * @param request - the request to authenticate. | |
| 119 | + * @param hashedPassword -- the MD5 hashed string of username:realm:plaintext password. | |
| 120 | + * | |
| 121 | + * @return true if authentication succeded and false otherwise. | |
| 122 | + */ | |
| 123 | + public boolean doAuthenticateHashedPassword(Request request, String hashedPassword) { | |
| 124 | + AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | |
| 125 | + if ( authHeader == null ) return false; | |
| 126 | + String realm = authHeader.getRealm(); | |
| 127 | + String username = authHeader.getUsername(); | |
| 128 | + | |
| 129 | + if ( username == null || realm == null ) { | |
| 130 | + return false; | |
| 131 | + } | |
| 132 | + | |
| 133 | + String nonce = authHeader.getNonce(); | |
| 134 | + URI uri = authHeader.getURI(); | |
| 135 | + if (uri == null) { | |
| 136 | + return false; | |
| 137 | + } | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + String A2 = request.getMethod().toUpperCase() + ":" + uri.toString(); | |
| 142 | + String HA1 = hashedPassword; | |
| 143 | + | |
| 144 | + | |
| 145 | + byte[] mdbytes = messageDigest.digest(A2.getBytes()); | |
| 146 | + String HA2 = toHexString(mdbytes); | |
| 147 | + | |
| 148 | + String cnonce = authHeader.getCNonce(); | |
| 149 | + String KD = HA1 + ":" + nonce; | |
| 150 | + if (cnonce != null) { | |
| 151 | + KD += ":" + cnonce; | |
| 152 | + } | |
| 153 | + KD += ":" + HA2; | |
| 154 | + mdbytes = messageDigest.digest(KD.getBytes()); | |
| 155 | + String mdString = toHexString(mdbytes); | |
| 156 | + String response = authHeader.getResponse(); | |
| 157 | + | |
| 158 | + | |
| 159 | + return mdString.equals(response); | |
| 160 | + } | |
| 161 | + | |
| 162 | + /** | |
| 163 | + * Authenticate the inbound request given plain text password. | |
| 164 | + * | |
| 165 | + * @param request - the request to authenticate. | |
| 166 | + * @param pass -- the plain text password. | |
| 167 | + * | |
| 168 | + * @return true if authentication succeded and false otherwise. | |
| 169 | + */ | |
| 170 | + public boolean doAuthenticatePlainTextPassword(Request request, String pass) { | |
| 171 | + AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | |
| 172 | + if ( authHeader == null ) return false; | |
| 173 | + String realm = authHeader.getRealm(); | |
| 174 | + String username = authHeader.getUsername(); | |
| 175 | + | |
| 176 | + | |
| 177 | + if ( username == null || realm == null ) { | |
| 178 | + return false; | |
| 179 | + } | |
| 180 | + | |
| 181 | + | |
| 182 | + String nonce = authHeader.getNonce(); | |
| 183 | + URI uri = authHeader.getURI(); | |
| 184 | + if (uri == null) { | |
| 185 | + return false; | |
| 186 | + } | |
| 187 | + | |
| 188 | + | |
| 189 | + String A1 = username + ":" + realm + ":" + pass; | |
| 190 | + String A2 = request.getMethod().toUpperCase() + ":" + uri.toString(); | |
| 191 | + byte mdbytes[] = messageDigest.digest(A1.getBytes()); | |
| 192 | + String HA1 = toHexString(mdbytes); | |
| 193 | + | |
| 194 | + | |
| 195 | + mdbytes = messageDigest.digest(A2.getBytes()); | |
| 196 | + String HA2 = toHexString(mdbytes); | |
| 197 | + | |
| 198 | + String cnonce = authHeader.getCNonce(); | |
| 199 | + String KD = HA1 + ":" + nonce; | |
| 200 | + if (cnonce != null) { | |
| 201 | + KD += ":" + cnonce; | |
| 202 | + } | |
| 203 | + KD += ":" + HA2; | |
| 204 | + mdbytes = messageDigest.digest(KD.getBytes()); | |
| 205 | + String mdString = toHexString(mdbytes); | |
| 206 | + String response = authHeader.getResponse(); | |
| 207 | + return mdString.equals(response); | |
| 208 | + | |
| 209 | + } | |
| 210 | + | |
| 211 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | +import java.util.Map; | |
| 4 | + | |
| 5 | + | |
| 6 | +public class Device { | |
| 7 | + | |
| 8 | + /** | |
| 9 | + * 设备Id | |
| 10 | + */ | |
| 11 | + private String deviceId; | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * 设备名 | |
| 15 | + */ | |
| 16 | + private String name; | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 生产厂商 | |
| 20 | + */ | |
| 21 | + private String manufacturer; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 型号 | |
| 25 | + */ | |
| 26 | + private String model; | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 固件版本 | |
| 30 | + */ | |
| 31 | + private String firmware; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 传输协议 | |
| 35 | + * UDP/TCP | |
| 36 | + */ | |
| 37 | + private String transport; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * wan地址 | |
| 41 | + */ | |
| 42 | + private Host host; | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * 在线 | |
| 46 | + */ | |
| 47 | + private int online; | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * 通道列表 | |
| 51 | + */ | |
| 52 | + private Map<String,DeviceChannel> channelMap; | |
| 53 | + | |
| 54 | + | |
| 55 | + public String getDeviceId() { | |
| 56 | + return deviceId; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public void setDeviceId(String deviceId) { | |
| 60 | + this.deviceId = deviceId; | |
| 61 | + } | |
| 62 | + | |
| 63 | + public String getName() { | |
| 64 | + return name; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public void setName(String name) { | |
| 68 | + this.name = name; | |
| 69 | + } | |
| 70 | + | |
| 71 | + public String getTransport() { | |
| 72 | + return transport; | |
| 73 | + } | |
| 74 | + | |
| 75 | + public void setTransport(String transport) { | |
| 76 | + this.transport = transport; | |
| 77 | + } | |
| 78 | + | |
| 79 | + public Host getHost() { | |
| 80 | + return host; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public void setHost(Host host) { | |
| 84 | + this.host = host; | |
| 85 | + } | |
| 86 | + | |
| 87 | + public Map<String, DeviceChannel> getChannelMap() { | |
| 88 | + return channelMap; | |
| 89 | + } | |
| 90 | + | |
| 91 | + public void setChannelMap(Map<String, DeviceChannel> channelMap) { | |
| 92 | + this.channelMap = channelMap; | |
| 93 | + } | |
| 94 | + | |
| 95 | + public String getManufacturer() { | |
| 96 | + return manufacturer; | |
| 97 | + } | |
| 98 | + | |
| 99 | + public void setManufacturer(String manufacturer) { | |
| 100 | + this.manufacturer = manufacturer; | |
| 101 | + } | |
| 102 | + | |
| 103 | + public String getModel() { | |
| 104 | + return model; | |
| 105 | + } | |
| 106 | + | |
| 107 | + public void setModel(String model) { | |
| 108 | + this.model = model; | |
| 109 | + } | |
| 110 | + | |
| 111 | + public String getFirmware() { | |
| 112 | + return firmware; | |
| 113 | + } | |
| 114 | + | |
| 115 | + public void setFirmware(String firmware) { | |
| 116 | + this.firmware = firmware; | |
| 117 | + } | |
| 118 | + | |
| 119 | + public int getOnline() { | |
| 120 | + return online; | |
| 121 | + } | |
| 122 | + | |
| 123 | + public void setOnline(int online) { | |
| 124 | + this.online = online; | |
| 125 | + } | |
| 126 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | +public class DeviceAlarm { | |
| 4 | + | |
| 5 | + /** | |
| 6 | + * 设备Id | |
| 7 | + */ | |
| 8 | + private String deviceId; | |
| 9 | + | |
| 10 | + /** | |
| 11 | + * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情- | |
| 12 | + */ | |
| 13 | + private String alarmPriorit; | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警, | |
| 17 | + * 7其他报警;可以为直接组合如12为电话报警或 设备报警- | |
| 18 | + */ | |
| 19 | + private String alarmMethod; | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 报警时间 | |
| 23 | + */ | |
| 24 | + private String alarmTime; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 报警内容描述 | |
| 28 | + */ | |
| 29 | + private String alarmDescription; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 经度 | |
| 33 | + */ | |
| 34 | + private double longitude; | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 纬度 | |
| 38 | + */ | |
| 39 | + private double latitude; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * 报警类型 | |
| 43 | + */ | |
| 44 | + private String alarmType; | |
| 45 | + | |
| 46 | + public String getDeviceId() { | |
| 47 | + return deviceId; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public void setDeviceId(String deviceId) { | |
| 51 | + this.deviceId = deviceId; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public String getAlarmPriorit() { | |
| 55 | + return alarmPriorit; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public void setAlarmPriorit(String alarmPriorit) { | |
| 59 | + this.alarmPriorit = alarmPriorit; | |
| 60 | + } | |
| 61 | + | |
| 62 | + public String getAlarmMethod() { | |
| 63 | + return alarmMethod; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public void setAlarmMethod(String alarmMethod) { | |
| 67 | + this.alarmMethod = alarmMethod; | |
| 68 | + } | |
| 69 | + | |
| 70 | + public String getAlarmTime() { | |
| 71 | + return alarmTime; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public void setAlarmTime(String alarmTime) { | |
| 75 | + this.alarmTime = alarmTime; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public String getAlarmDescription() { | |
| 79 | + return alarmDescription; | |
| 80 | + } | |
| 81 | + | |
| 82 | + public void setAlarmDescription(String alarmDescription) { | |
| 83 | + this.alarmDescription = alarmDescription; | |
| 84 | + } | |
| 85 | + | |
| 86 | + public double getLongitude() { | |
| 87 | + return longitude; | |
| 88 | + } | |
| 89 | + | |
| 90 | + public void setLongitude(double longitude) { | |
| 91 | + this.longitude = longitude; | |
| 92 | + } | |
| 93 | + | |
| 94 | + public double getLatitude() { | |
| 95 | + return latitude; | |
| 96 | + } | |
| 97 | + | |
| 98 | + public void setLatitude(double latitude) { | |
| 99 | + this.latitude = latitude; | |
| 100 | + } | |
| 101 | + | |
| 102 | + public String getAlarmType() { | |
| 103 | + return alarmType; | |
| 104 | + } | |
| 105 | + | |
| 106 | + public void setAlarmType(String alarmType) { | |
| 107 | + this.alarmType = alarmType; | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | +public class DeviceChannel { | |
| 4 | + | |
| 5 | + /** | |
| 6 | + * 通道id | |
| 7 | + */ | |
| 8 | + private String channelId; | |
| 9 | + | |
| 10 | + /** | |
| 11 | + * 通道名 | |
| 12 | + */ | |
| 13 | + private String name; | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 生产厂商 | |
| 17 | + */ | |
| 18 | + private String manufacture; | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 型号 | |
| 22 | + */ | |
| 23 | + private String model; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 设备归属 | |
| 27 | + */ | |
| 28 | + private String owner; | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 行政区域 | |
| 32 | + */ | |
| 33 | + private String civilCode; | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 警区 | |
| 37 | + */ | |
| 38 | + private String block; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 安装地址 | |
| 42 | + */ | |
| 43 | + private String address; | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 是否有子设备 1有, 0没有 | |
| 47 | + */ | |
| 48 | + private int parental; | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 父级id | |
| 52 | + */ | |
| 53 | + private String parentId; | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * 信令安全模式 缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式 | |
| 57 | + */ | |
| 58 | + private int safetyWay; | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式 | |
| 62 | + */ | |
| 63 | + private int registerWay; | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 证书序列号 | |
| 67 | + */ | |
| 68 | + private String certNum; | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * 证书有效标识 缺省为0;证书有效标识:0:无效1: 有效 | |
| 72 | + */ | |
| 73 | + private int certifiable; | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * 证书无效原因码 | |
| 77 | + */ | |
| 78 | + private int errCode; | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 证书终止有效期 | |
| 82 | + */ | |
| 83 | + private String endTime; | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 保密属性 缺省为0; 0:不涉密, 1:涉密 | |
| 87 | + */ | |
| 88 | + private String secrecy; | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * IP地址 | |
| 92 | + */ | |
| 93 | + private String ipAddress; | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * 端口号 | |
| 97 | + */ | |
| 98 | + private int port; | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * 密码 | |
| 102 | + */ | |
| 103 | + private String password; | |
| 104 | + | |
| 105 | + /** | |
| 106 | + * 在线/离线 | |
| 107 | + * 1在线,0离线 | |
| 108 | + * 默认在线 | |
| 109 | + * 信令: | |
| 110 | + * <Status>ON</Status> | |
| 111 | + * <Status>OFF</Status> | |
| 112 | + * 遇到过NVR下的IPC下发信令可以推流, 但是 Status 响应 OFF | |
| 113 | + */ | |
| 114 | + private int status; | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * 经度 | |
| 118 | + */ | |
| 119 | + private double longitude; | |
| 120 | + | |
| 121 | + /** | |
| 122 | + * 纬度 | |
| 123 | + */ | |
| 124 | + private double latitude; | |
| 125 | + | |
| 126 | + public String getChannelId() { | |
| 127 | + return channelId; | |
| 128 | + } | |
| 129 | + | |
| 130 | + public void setChannelId(String channelId) { | |
| 131 | + this.channelId = channelId; | |
| 132 | + } | |
| 133 | + | |
| 134 | + public String getName() { | |
| 135 | + return name; | |
| 136 | + } | |
| 137 | + | |
| 138 | + public void setName(String name) { | |
| 139 | + this.name = name; | |
| 140 | + } | |
| 141 | + | |
| 142 | + public int getStatus() { | |
| 143 | + return status; | |
| 144 | + } | |
| 145 | + | |
| 146 | + public void setStatus(int status) { | |
| 147 | + this.status = status; | |
| 148 | + } | |
| 149 | + | |
| 150 | + public String getManufacture() { | |
| 151 | + return manufacture; | |
| 152 | + } | |
| 153 | + | |
| 154 | + public void setManufacture(String manufacture) { | |
| 155 | + this.manufacture = manufacture; | |
| 156 | + } | |
| 157 | + | |
| 158 | + public String getModel() { | |
| 159 | + return model; | |
| 160 | + } | |
| 161 | + | |
| 162 | + public void setModel(String model) { | |
| 163 | + this.model = model; | |
| 164 | + } | |
| 165 | + | |
| 166 | + public String getOwner() { | |
| 167 | + return owner; | |
| 168 | + } | |
| 169 | + | |
| 170 | + public void setOwner(String owner) { | |
| 171 | + this.owner = owner; | |
| 172 | + } | |
| 173 | + | |
| 174 | + public String getCivilCode() { | |
| 175 | + return civilCode; | |
| 176 | + } | |
| 177 | + | |
| 178 | + public void setCivilCode(String civilCode) { | |
| 179 | + this.civilCode = civilCode; | |
| 180 | + } | |
| 181 | + | |
| 182 | + public String getBlock() { | |
| 183 | + return block; | |
| 184 | + } | |
| 185 | + | |
| 186 | + public void setBlock(String block) { | |
| 187 | + this.block = block; | |
| 188 | + } | |
| 189 | + | |
| 190 | + public String getAddress() { | |
| 191 | + return address; | |
| 192 | + } | |
| 193 | + | |
| 194 | + public void setAddress(String address) { | |
| 195 | + this.address = address; | |
| 196 | + } | |
| 197 | + | |
| 198 | + public int getParental() { | |
| 199 | + return parental; | |
| 200 | + } | |
| 201 | + | |
| 202 | + public void setParental(int parental) { | |
| 203 | + this.parental = parental; | |
| 204 | + } | |
| 205 | + | |
| 206 | + public String getParentId() { | |
| 207 | + return parentId; | |
| 208 | + } | |
| 209 | + | |
| 210 | + public void setParentId(String parentId) { | |
| 211 | + this.parentId = parentId; | |
| 212 | + } | |
| 213 | + | |
| 214 | + public int getSafetyWay() { | |
| 215 | + return safetyWay; | |
| 216 | + } | |
| 217 | + | |
| 218 | + public void setSafetyWay(int safetyWay) { | |
| 219 | + this.safetyWay = safetyWay; | |
| 220 | + } | |
| 221 | + | |
| 222 | + public int getRegisterWay() { | |
| 223 | + return registerWay; | |
| 224 | + } | |
| 225 | + | |
| 226 | + public void setRegisterWay(int registerWay) { | |
| 227 | + this.registerWay = registerWay; | |
| 228 | + } | |
| 229 | + | |
| 230 | + public String getCertNum() { | |
| 231 | + return certNum; | |
| 232 | + } | |
| 233 | + | |
| 234 | + public void setCertNum(String certNum) { | |
| 235 | + this.certNum = certNum; | |
| 236 | + } | |
| 237 | + | |
| 238 | + public int getCertifiable() { | |
| 239 | + return certifiable; | |
| 240 | + } | |
| 241 | + | |
| 242 | + public void setCertifiable(int certifiable) { | |
| 243 | + this.certifiable = certifiable; | |
| 244 | + } | |
| 245 | + | |
| 246 | + public int getErrCode() { | |
| 247 | + return errCode; | |
| 248 | + } | |
| 249 | + | |
| 250 | + public void setErrCode(int errCode) { | |
| 251 | + this.errCode = errCode; | |
| 252 | + } | |
| 253 | + | |
| 254 | + public String getEndTime() { | |
| 255 | + return endTime; | |
| 256 | + } | |
| 257 | + | |
| 258 | + public void setEndTime(String endTime) { | |
| 259 | + this.endTime = endTime; | |
| 260 | + } | |
| 261 | + | |
| 262 | + public String getSecrecy() { | |
| 263 | + return secrecy; | |
| 264 | + } | |
| 265 | + | |
| 266 | + public void setSecrecy(String secrecy) { | |
| 267 | + this.secrecy = secrecy; | |
| 268 | + } | |
| 269 | + | |
| 270 | + public String getIpAddress() { | |
| 271 | + return ipAddress; | |
| 272 | + } | |
| 273 | + | |
| 274 | + public void setIpAddress(String ipAddress) { | |
| 275 | + this.ipAddress = ipAddress; | |
| 276 | + } | |
| 277 | + | |
| 278 | + public int getPort() { | |
| 279 | + return port; | |
| 280 | + } | |
| 281 | + | |
| 282 | + public void setPort(int port) { | |
| 283 | + this.port = port; | |
| 284 | + } | |
| 285 | + | |
| 286 | + public String getPassword() { | |
| 287 | + return password; | |
| 288 | + } | |
| 289 | + | |
| 290 | + public void setPassword(String password) { | |
| 291 | + this.password = password; | |
| 292 | + } | |
| 293 | + | |
| 294 | + public double getLongitude() { | |
| 295 | + return longitude; | |
| 296 | + } | |
| 297 | + | |
| 298 | + public void setLongitude(double longitude) { | |
| 299 | + this.longitude = longitude; | |
| 300 | + } | |
| 301 | + | |
| 302 | + public double getLatitude() { | |
| 303 | + return latitude; | |
| 304 | + } | |
| 305 | + | |
| 306 | + public void setLatitude(double latitude) { | |
| 307 | + this.latitude = latitude; | |
| 308 | + } | |
| 309 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Host.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Host.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | +public class Host { | |
| 4 | + | |
| 5 | + private String ip; | |
| 6 | + private int port; | |
| 7 | + private String address; | |
| 8 | + | |
| 9 | + public String getIp() { | |
| 10 | + return ip; | |
| 11 | + } | |
| 12 | + public void setIp(String ip) { | |
| 13 | + this.ip = ip; | |
| 14 | + } | |
| 15 | + public int getPort() { | |
| 16 | + return port; | |
| 17 | + } | |
| 18 | + public void setPort(int port) { | |
| 19 | + this.port = port; | |
| 20 | + } | |
| 21 | + public String getAddress() { | |
| 22 | + return address; | |
| 23 | + } | |
| 24 | + public void setAddress(String address) { | |
| 25 | + this.address = address; | |
| 26 | + } | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.event; | |
| 2 | + | |
| 3 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 4 | +import org.springframework.context.ApplicationEventPublisher; | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | + | |
| 7 | +import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.event.outline.OutlineEvent; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * @Description:Event事件通知推送器,支持推送在线事件、离线事件 | |
| 12 | + * @author: songww | |
| 13 | + * @date: 2020年5月6日 上午11:30:50 | |
| 14 | + */ | |
| 15 | +@Component | |
| 16 | +public class EventPublisher { | |
| 17 | + | |
| 18 | + @Autowired | |
| 19 | + private ApplicationEventPublisher applicationEventPublisher; | |
| 20 | + | |
| 21 | + public void onlineEventPublish(String deviceId, String from) { | |
| 22 | + OnlineEvent onEvent = new OnlineEvent(this); | |
| 23 | + onEvent.setDeviceId(deviceId); | |
| 24 | + onEvent.setFrom(from); | |
| 25 | + applicationEventPublisher.publishEvent(onEvent); | |
| 26 | + } | |
| 27 | + | |
| 28 | + public void outlineEventPublish(String deviceId, String from){ | |
| 29 | + OutlineEvent outEvent = new OutlineEvent(this); | |
| 30 | + outEvent.setDeviceId(deviceId); | |
| 31 | + outEvent.setFrom(from); | |
| 32 | + applicationEventPublisher.publishEvent(outEvent); | |
| 33 | + } | |
| 34 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.event.online; | |
| 2 | + | |
| 3 | +import org.springframework.context.ApplicationEvent; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @Description:TODO(这里用一句话描述这个类的作用) | |
| 7 | + * @author: songww | |
| 8 | + * @date: 2020年5月6日 上午11:32:56 | |
| 9 | + */ | |
| 10 | +public class OnlineEvent extends ApplicationEvent { | |
| 11 | + | |
| 12 | + /** | |
| 13 | + * @Title: OnlineEvent | |
| 14 | + * @Description: TODO(这里用一句话描述这个方法的作用) | |
| 15 | + * @param: @param source | |
| 16 | + * @throws | |
| 17 | + */ | |
| 18 | + public OnlineEvent(Object source) { | |
| 19 | + super(source); | |
| 20 | + } | |
| 21 | + | |
| 22 | + private String deviceId; | |
| 23 | + | |
| 24 | + private String from; | |
| 25 | + | |
| 26 | + public String getDeviceId() { | |
| 27 | + return deviceId; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public void setDeviceId(String deviceId) { | |
| 31 | + this.deviceId = deviceId; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public String getFrom() { | |
| 35 | + return from; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public void setFrom(String from) { | |
| 39 | + this.from = from; | |
| 40 | + } | |
| 41 | + | |
| 42 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.event.online; | |
| 2 | + | |
| 3 | +import org.slf4j.Logger; | |
| 4 | +import org.slf4j.LoggerFactory; | |
| 5 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 6 | +import org.springframework.context.ApplicationListener; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 10 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 11 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: | |
| 15 | + * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} | |
| 16 | + * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor} | |
| 17 | + * @author: songww | |
| 18 | + * @date: 2020年5月6日 下午1:51:23 | |
| 19 | + */ | |
| 20 | +@Component | |
| 21 | +public class OnlineEventListener implements ApplicationListener<OnlineEvent> { | |
| 22 | + | |
| 23 | + private final static Logger logger = LoggerFactory.getLogger(OnlineEventListener.class); | |
| 24 | + | |
| 25 | + @Autowired | |
| 26 | + private IVideoManagerStorager storager; | |
| 27 | + | |
| 28 | + @Autowired | |
| 29 | + private RedisUtil redis; | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public void onApplicationEvent(OnlineEvent event) { | |
| 33 | + | |
| 34 | + if (logger.isDebugEnabled()) { | |
| 35 | + logger.debug("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom()); | |
| 36 | + } | |
| 37 | + | |
| 38 | + String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + event.getDeviceId(); | |
| 39 | + boolean needUpdateStorager = false; | |
| 40 | + | |
| 41 | + switch (event.getFrom()) { | |
| 42 | + // 注册时触发的在线事件,先在redis中增加超时超时监听 | |
| 43 | + case VideoManagerConstants.EVENT_ONLINE_REGISTER: | |
| 44 | + // TODO 超时时间暂时写死为180秒 | |
| 45 | + redis.set(key, event.getDeviceId(), 180); | |
| 46 | + needUpdateStorager = true; | |
| 47 | + break; | |
| 48 | + // 设备主动发送心跳触发的离线事件 | |
| 49 | + case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE: | |
| 50 | + boolean exist = redis.hasKey(key); | |
| 51 | + // 先判断是否还存在,当设备先心跳超时后又发送心跳时,redis没有监听,需要增加 | |
| 52 | + if (!exist) { | |
| 53 | + needUpdateStorager = true; | |
| 54 | + redis.set(key, event.getDeviceId(), 180); | |
| 55 | + } else { | |
| 56 | + redis.expire(key, 180); | |
| 57 | + } | |
| 58 | + break; | |
| 59 | + } | |
| 60 | + | |
| 61 | + if (needUpdateStorager) { | |
| 62 | + // 处理离线监听 | |
| 63 | + storager.online(event.getDeviceId()); | |
| 64 | + } | |
| 65 | + } | |
| 66 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/KeepliveTimeoutListener.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/KeepliveTimeoutListener.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.event.outline; | |
| 2 | + | |
| 3 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 4 | +import org.springframework.data.redis.connection.Message; | |
| 5 | +import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; | |
| 6 | +import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 10 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 | |
| 14 | + * @author: songww | |
| 15 | + * @date: 2020年5月6日 上午11:35:46 | |
| 16 | + */ | |
| 17 | +@Component | |
| 18 | +public class KeepliveTimeoutListener extends KeyExpirationEventMessageListener { | |
| 19 | + | |
| 20 | + @Autowired | |
| 21 | + private EventPublisher publisher; | |
| 22 | + | |
| 23 | + public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer) { | |
| 24 | + super(listenerContainer); | |
| 25 | + } | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 监听失效的key,key格式为keeplive_deviceId | |
| 29 | + * @param message | |
| 30 | + * @param pattern | |
| 31 | + */ | |
| 32 | + @Override | |
| 33 | + public void onMessage(Message message, byte[] pattern) { | |
| 34 | + // 获取失效的key | |
| 35 | + String expiredKey = message.toString(); | |
| 36 | + if(!expiredKey.startsWith(VideoManagerConstants.KEEPLIVEKEY_PREFIX)){ | |
| 37 | + System.out.println("收到redis过期监听,但开头不是"+VideoManagerConstants.KEEPLIVEKEY_PREFIX+",忽略"); | |
| 38 | + return; | |
| 39 | + } | |
| 40 | + | |
| 41 | + String deviceId = expiredKey.substring(VideoManagerConstants.KEEPLIVEKEY_PREFIX.length(),expiredKey.length()); | |
| 42 | + publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_TIMEOUT); | |
| 43 | + } | |
| 44 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/OutlineEvent.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/OutlineEvent.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.event.outline; | |
| 2 | + | |
| 3 | +import org.springframework.context.ApplicationEvent; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @Description:TODO(这里用一句话描述这个类的作用) | |
| 7 | + * @author: songww | |
| 8 | + * @date: 2020年5月6日 上午11:33:13 | |
| 9 | + */ | |
| 10 | +public class OutlineEvent extends ApplicationEvent { | |
| 11 | + | |
| 12 | + /** | |
| 13 | + * @Title: OutlineEvent | |
| 14 | + * @Description: TODO(这里用一句话描述这个方法的作用) | |
| 15 | + * @param: @param source | |
| 16 | + * @throws | |
| 17 | + */ | |
| 18 | + public OutlineEvent(Object source) { | |
| 19 | + super(source); | |
| 20 | + } | |
| 21 | + | |
| 22 | + private String deviceId; | |
| 23 | + | |
| 24 | + private String from; | |
| 25 | + | |
| 26 | + public String getDeviceId() { | |
| 27 | + return deviceId; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public void setDeviceId(String deviceId) { | |
| 31 | + this.deviceId = deviceId; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public String getFrom() { | |
| 35 | + return from; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public void setFrom(String from) { | |
| 39 | + this.from = from; | |
| 40 | + } | |
| 41 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/OutlineEventListener.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/OutlineEventListener.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.event.outline; | |
| 2 | + | |
| 3 | +import org.slf4j.Logger; | |
| 4 | +import org.slf4j.LoggerFactory; | |
| 5 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 6 | +import org.springframework.context.ApplicationListener; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 10 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 11 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源: | |
| 15 | + * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} | |
| 16 | + * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.outline.OutlineEventListener} | |
| 17 | + * @author: songww | |
| 18 | + * @date: 2020年5月6日 下午1:51:23 | |
| 19 | + */ | |
| 20 | +@Component | |
| 21 | +public class OutlineEventListener implements ApplicationListener<OutlineEvent> { | |
| 22 | + | |
| 23 | + private final static Logger logger = LoggerFactory.getLogger(OutlineEventListener.class); | |
| 24 | + | |
| 25 | + @Autowired | |
| 26 | + private IVideoManagerStorager storager; | |
| 27 | + | |
| 28 | + @Autowired | |
| 29 | + private RedisUtil redis; | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public void onApplicationEvent(OutlineEvent event) { | |
| 33 | + | |
| 34 | + if (logger.isDebugEnabled()) { | |
| 35 | + logger.debug("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom()); | |
| 36 | + } | |
| 37 | + | |
| 38 | + String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + event.getDeviceId(); | |
| 39 | + | |
| 40 | + switch (event.getFrom()) { | |
| 41 | + // 心跳超时触发的离线事件,说明redis中已删除,无需处理 | |
| 42 | + case VideoManagerConstants.EVENT_OUTLINE_TIMEOUT: | |
| 43 | + break; | |
| 44 | + // 设备主动注销触发的离线事件,需要删除redis中的超时监听 | |
| 45 | + case VideoManagerConstants.EVENT_OUTLINE_UNREGISTER: | |
| 46 | + redis.del(key); | |
| 47 | + break; | |
| 48 | + default: | |
| 49 | + boolean exist = redis.hasKey(key); | |
| 50 | + if (exist) { | |
| 51 | + redis.del(key); | |
| 52 | + } | |
| 53 | + } | |
| 54 | + | |
| 55 | + // 处理离线监听 | |
| 56 | + storager.outline(event.getDeviceId()); | |
| 57 | + } | |
| 58 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit; | |
| 2 | + | |
| 3 | +import javax.sip.RequestEvent; | |
| 4 | +import javax.sip.ResponseEvent; | |
| 5 | +import javax.sip.header.CSeqHeader; | |
| 6 | +import javax.sip.message.Request; | |
| 7 | +import javax.sip.message.Response; | |
| 8 | + | |
| 9 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 10 | +import org.springframework.stereotype.Component; | |
| 11 | + | |
| 12 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.AckRequestProcessor; | |
| 14 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor; | |
| 15 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor; | |
| 16 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor; | |
| 17 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor; | |
| 18 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor; | |
| 19 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor; | |
| 20 | +import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor; | |
| 21 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | |
| 22 | +import com.genersoft.iot.vmp.gb28181.transmit.response.impl.ByeResponseProcessor; | |
| 23 | +import com.genersoft.iot.vmp.gb28181.transmit.response.impl.CancelResponseProcessor; | |
| 24 | +import com.genersoft.iot.vmp.gb28181.transmit.response.impl.InviteResponseProcessor; | |
| 25 | +import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcessor; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * @Description:TODO(这里用一句话描述这个类的作用) | |
| 29 | + * @author: songww | |
| 30 | + * @date: 2020年5月3日 下午4:24:37 | |
| 31 | + */ | |
| 32 | +@Component | |
| 33 | +public class SIPProcessorFactory { | |
| 34 | + | |
| 35 | + @Autowired | |
| 36 | + private InviteRequestProcessor inviteRequestProcessor; | |
| 37 | + | |
| 38 | + @Autowired | |
| 39 | + private RegisterRequestProcessor registerRequestProcessor; | |
| 40 | + | |
| 41 | + @Autowired | |
| 42 | + private SubscribeRequestProcessor subscribeRequestProcessor; | |
| 43 | + | |
| 44 | + @Autowired | |
| 45 | + private AckRequestProcessor ackRequestProcessor; | |
| 46 | + | |
| 47 | + @Autowired | |
| 48 | + private ByeRequestProcessor byeRequestProcessor; | |
| 49 | + | |
| 50 | + @Autowired | |
| 51 | + private CancelRequestProcessor cancelRequestProcessor; | |
| 52 | + | |
| 53 | + @Autowired | |
| 54 | + private MessageRequestProcessor messageRequestProcessor; | |
| 55 | + | |
| 56 | + @Autowired | |
| 57 | + private OtherRequestProcessor otherRequestProcessor; | |
| 58 | + | |
| 59 | + @Autowired | |
| 60 | + private InviteResponseProcessor inviteResponseProcessor; | |
| 61 | + | |
| 62 | + @Autowired | |
| 63 | + private ByeResponseProcessor byeResponseProcessor; | |
| 64 | + | |
| 65 | + @Autowired | |
| 66 | + private CancelResponseProcessor cancelResponseProcessor; | |
| 67 | + | |
| 68 | + @Autowired | |
| 69 | + private OtherResponseProcessor otherResponseProcessor; | |
| 70 | + | |
| 71 | + | |
| 72 | + public ISIPRequestProcessor createRequestProcessor(RequestEvent evt) { | |
| 73 | + Request request = evt.getRequest(); | |
| 74 | + String method = request.getMethod(); | |
| 75 | + | |
| 76 | + if (Request.INVITE.equals(method)) { | |
| 77 | + return inviteRequestProcessor; | |
| 78 | + } else if (Request.REGISTER.equals(method)) { | |
| 79 | + return registerRequestProcessor; | |
| 80 | + } else if (Request.SUBSCRIBE.equals(method)) { | |
| 81 | + return subscribeRequestProcessor; | |
| 82 | + } else if (Request.ACK.equals(method)) { | |
| 83 | + return ackRequestProcessor; | |
| 84 | + } else if (Request.BYE.equals(method)) { | |
| 85 | + return byeRequestProcessor; | |
| 86 | + } else if (Request.CANCEL.equals(method)) { | |
| 87 | + return cancelRequestProcessor; | |
| 88 | + } else if (Request.MESSAGE.equals(method)) { | |
| 89 | + return messageRequestProcessor; | |
| 90 | + } else { | |
| 91 | + return otherRequestProcessor; | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) { | |
| 96 | + Response response = evt.getResponse(); | |
| 97 | + CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); | |
| 98 | + String method = cseqHeader.getMethod(); | |
| 99 | + if(Request.INVITE.equals(method)){ | |
| 100 | + return inviteResponseProcessor; | |
| 101 | + } else if (Request.BYE.equals(method)) { | |
| 102 | + return byeResponseProcessor; | |
| 103 | + } else if (Request.CANCEL.equals(method)) { | |
| 104 | + return cancelResponseProcessor; | |
| 105 | + } else { | |
| 106 | + return otherResponseProcessor; | |
| 107 | + } | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.cmd; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @Description:设备能力接口,用于定义设备的控制、查询能力 | |
| 7 | + * @author: songww | |
| 8 | + * @date: 2020年5月3日 下午9:16:34 | |
| 9 | + */ | |
| 10 | +public interface ISIPCommander { | |
| 11 | + | |
| 12 | + /** | |
| 13 | + * 云台方向放控制,使用配置文件中的默认镜头移动速度 | |
| 14 | + * | |
| 15 | + * @param deviceId 控制设备 | |
| 16 | + * @param channelId 预览通道 | |
| 17 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 18 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 19 | + * @param moveSpeed 镜头移动速度 | |
| 20 | + */ | |
| 21 | + public boolean ptzdirectCmd(String deviceId,String channelId,int leftRight, int upDown); | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 云台方向放控制 | |
| 25 | + * | |
| 26 | + * @param deviceId 控制设备 | |
| 27 | + * @param channelId 预览通道 | |
| 28 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 29 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 30 | + * @param moveSpeed 镜头移动速度 | |
| 31 | + */ | |
| 32 | + public boolean ptzdirectCmd(String deviceId,String channelId,int leftRight, int upDown, int moveSpeed); | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 云台缩放控制,使用配置文件中的默认镜头缩放速度 | |
| 36 | + * | |
| 37 | + * @param deviceId 控制设备 | |
| 38 | + * @param channelId 预览通道 | |
| 39 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 40 | + */ | |
| 41 | + public boolean ptzZoomCmd(String deviceId,String channelId,int inOut); | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 云台缩放控制 | |
| 45 | + * | |
| 46 | + * @param deviceId 控制设备 | |
| 47 | + * @param channelId 预览通道 | |
| 48 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 49 | + * @param zoomSpeed 镜头缩放速度 | |
| 50 | + */ | |
| 51 | + public boolean ptzZoomCmd(String deviceId,String channelId,int inOut, int moveSpeed); | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 云台控制,支持方向与缩放控制 | |
| 55 | + * | |
| 56 | + * @param deviceId 控制设备 | |
| 57 | + * @param channelId 预览通道 | |
| 58 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 59 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 60 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 61 | + * @param moveSpeed 镜头移动速度 | |
| 62 | + * @param zoomSpeed 镜头缩放速度 | |
| 63 | + */ | |
| 64 | + public boolean ptzCmd(String deviceId,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed); | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * 请求预览视频流 | |
| 68 | + * | |
| 69 | + * @param deviceId 视频设备 | |
| 70 | + * @param channelId 预览通道 | |
| 71 | + */ | |
| 72 | + public String playStreamCmd(String deviceId,String channelId); | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * 语音广播 | |
| 76 | + * | |
| 77 | + * @param deviceId 视频设备 | |
| 78 | + * @param channelId 预览通道 | |
| 79 | + */ | |
| 80 | + public String audioBroadcastCmd(String deviceId,String channelId); | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * 音视频录像控制 | |
| 84 | + * | |
| 85 | + * @param deviceId 视频设备 | |
| 86 | + * @param channelId 预览通道 | |
| 87 | + */ | |
| 88 | + public String recordCmd(String deviceId,String channelId); | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * 报警布防/撤防命令 | |
| 92 | + * | |
| 93 | + * @param deviceId 视频设备 | |
| 94 | + */ | |
| 95 | + public String guardCmd(String deviceId); | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * 报警复位命令 | |
| 99 | + * | |
| 100 | + * @param deviceId 视频设备 | |
| 101 | + */ | |
| 102 | + public String alarmCmd(String deviceId); | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 | |
| 106 | + * | |
| 107 | + * @param deviceId 视频设备 | |
| 108 | + * @param channelId 预览通道 | |
| 109 | + */ | |
| 110 | + public String iFameCmd(String deviceId,String channelId); | |
| 111 | + | |
| 112 | + /** | |
| 113 | + * 看守位控制命令 | |
| 114 | + * | |
| 115 | + * @param deviceId 视频设备 | |
| 116 | + */ | |
| 117 | + public String homePositionCmd(String deviceId); | |
| 118 | + | |
| 119 | + /** | |
| 120 | + * 设备配置命令 | |
| 121 | + * | |
| 122 | + * @param deviceId 视频设备 | |
| 123 | + */ | |
| 124 | + public String deviceConfigCmd(String deviceId); | |
| 125 | + | |
| 126 | + | |
| 127 | + /** | |
| 128 | + * 查询设备状态 | |
| 129 | + * | |
| 130 | + * @param device 视频设备 | |
| 131 | + */ | |
| 132 | + public boolean deviceStatusQuery(Device device); | |
| 133 | + | |
| 134 | + /** | |
| 135 | + * 查询设备信息 | |
| 136 | + * | |
| 137 | + * @param device 视频设备 | |
| 138 | + * @return | |
| 139 | + */ | |
| 140 | + public boolean deviceInfoQuery(Device device); | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * 查询目录列表 | |
| 144 | + * | |
| 145 | + * @param device 视频设备 | |
| 146 | + */ | |
| 147 | + public boolean catalogQuery(Device device); | |
| 148 | + | |
| 149 | + /** | |
| 150 | + * 查询录像信息 | |
| 151 | + * | |
| 152 | + * @param device 视频设备 | |
| 153 | + */ | |
| 154 | + public boolean recordInfoQuery(Device device); | |
| 155 | + | |
| 156 | + /** | |
| 157 | + * 查询报警信息 | |
| 158 | + * | |
| 159 | + * @param device 视频设备 | |
| 160 | + */ | |
| 161 | + public boolean alarmInfoQuery(Device device); | |
| 162 | + | |
| 163 | + /** | |
| 164 | + * 查询设备配置 | |
| 165 | + * | |
| 166 | + * @param device 视频设备 | |
| 167 | + */ | |
| 168 | + public boolean configQuery(Device device); | |
| 169 | + | |
| 170 | + /** | |
| 171 | + * 查询设备预置位置 | |
| 172 | + * | |
| 173 | + * @param device 视频设备 | |
| 174 | + */ | |
| 175 | + public boolean presetQuery(Device device); | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * 查询移动设备位置数据 | |
| 179 | + * | |
| 180 | + * @param device 视频设备 | |
| 181 | + */ | |
| 182 | + public boolean mobilePostitionQuery(Device device); | |
| 183 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.cmd; | |
| 2 | + | |
| 3 | +import java.text.ParseException; | |
| 4 | +import java.util.ArrayList; | |
| 5 | + | |
| 6 | +import javax.sip.InvalidArgumentException; | |
| 7 | +import javax.sip.address.Address; | |
| 8 | +import javax.sip.address.SipURI; | |
| 9 | +import javax.sip.header.CSeqHeader; | |
| 10 | +import javax.sip.header.CallIdHeader; | |
| 11 | +import javax.sip.header.ContentTypeHeader; | |
| 12 | +import javax.sip.header.FromHeader; | |
| 13 | +import javax.sip.header.MaxForwardsHeader; | |
| 14 | +import javax.sip.header.ToHeader; | |
| 15 | +import javax.sip.header.ViaHeader; | |
| 16 | +import javax.sip.message.Request; | |
| 17 | + | |
| 18 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 19 | +import org.springframework.stereotype.Component; | |
| 20 | + | |
| 21 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 22 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 23 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 24 | +import com.genersoft.iot.vmp.gb28181.bean.Host; | |
| 25 | + | |
| 26 | +/** | |
| 27 | + * @Description:TODO(这里用一句话描述这个类的作用) | |
| 28 | + * @author: songww | |
| 29 | + * @date: 2020年5月6日 上午9:29:02 | |
| 30 | + */ | |
| 31 | +@Component | |
| 32 | +public class SIPRequestHeaderProvider { | |
| 33 | + | |
| 34 | + @Autowired | |
| 35 | + private SipLayer layer; | |
| 36 | + | |
| 37 | + @Autowired | |
| 38 | + private SipConfig config; | |
| 39 | + | |
| 40 | + public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException { | |
| 41 | + Request request = null; | |
| 42 | + Host host = device.getHost(); | |
| 43 | + // sipuri | |
| 44 | + SipURI requestURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress()); | |
| 45 | + // via | |
| 46 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 47 | + ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(config.getSipIp(), config.getSipPort(), | |
| 48 | + device.getTransport(), viaTag); | |
| 49 | + viaHeaders.add(viaHeader); | |
| 50 | + // from | |
| 51 | + SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), | |
| 52 | + config.getSipIp() + ":" + config.getSipPort()); | |
| 53 | + Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI); | |
| 54 | + FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); | |
| 55 | + // to | |
| 56 | + SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress()); | |
| 57 | + Address toAddress = layer.getAddressFactory().createAddress(toSipURI); | |
| 58 | + ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress, toTag); | |
| 59 | + // callid | |
| 60 | + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? layer.getTcpSipProvider().getNewCallId() | |
| 61 | + : layer.getUdpSipProvider().getNewCallId(); | |
| 62 | + // Forwards | |
| 63 | + MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70); | |
| 64 | + // ceq | |
| 65 | + CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.MESSAGE); | |
| 66 | + | |
| 67 | + request = layer.getMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, | |
| 68 | + toHeader, viaHeaders, maxForwards); | |
| 69 | + ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 70 | + request.setContent(content, contentTypeHeader); | |
| 71 | + return request; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException { | |
| 75 | + Request request = null; | |
| 76 | + Host host = device.getHost(); | |
| 77 | + //请求行 | |
| 78 | + SipURI requestLine = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress()); | |
| 79 | + //via | |
| 80 | + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | |
| 81 | + ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(config.getSipIp(), config.getSipPort(), device.getTransport(), viaTag); | |
| 82 | + viaHeader.setRPort(); | |
| 83 | + viaHeaders.add(viaHeader); | |
| 84 | + //from | |
| 85 | + SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),config.getSipIp()+":"+config.getSipPort()); | |
| 86 | + Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI); | |
| 87 | + FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack | |
| 88 | + //to | |
| 89 | + SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),host.getAddress()); | |
| 90 | + Address toAddress = layer.getAddressFactory().createAddress(toSipURI); | |
| 91 | + ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null); | |
| 92 | + | |
| 93 | + //callid | |
| 94 | + CallIdHeader callIdHeader = null; | |
| 95 | + if(device.getTransport().equals("TCP")) { | |
| 96 | + callIdHeader = layer.getTcpSipProvider().getNewCallId(); | |
| 97 | + } | |
| 98 | + if(device.getTransport().equals("UDP")) { | |
| 99 | + callIdHeader = layer.getUdpSipProvider().getNewCallId(); | |
| 100 | + } | |
| 101 | + | |
| 102 | + //Forwards | |
| 103 | + MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70); | |
| 104 | + //ceq | |
| 105 | + CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE); | |
| 106 | + request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); | |
| 107 | + ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP"); | |
| 108 | + request.setContent(content, contentTypeHeader); | |
| 109 | + return request; | |
| 110 | + } | |
| 111 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/PtzCmdHelper.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/PtzCmdHelper.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | |
| 2 | + | |
| 3 | +public class PtzCmdHelper { | |
| 4 | + /** | |
| 5 | + * | |
| 6 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 7 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 8 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 9 | + * @param moveSpeed 镜头移动速度 默认 0XFF (0-255) | |
| 10 | + * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255) | |
| 11 | + * @return | |
| 12 | + */ | |
| 13 | + //云台控制发送了消息,相机会一直执行,直到其他命令或者发送了停止命令,切记要考虑这个机制 | |
| 14 | + public static String create(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) { | |
| 15 | + int cmdCode = 0; | |
| 16 | + if (leftRight == 2) cmdCode|=0x01; // 右移 | |
| 17 | + else if(leftRight == 1) cmdCode|=0x02; // 左移 | |
| 18 | + if (upDown == 2) cmdCode|=0x04; // 下移 | |
| 19 | + else if(upDown == 1) cmdCode|=0x08; // 上移 | |
| 20 | + if (inOut == 2) cmdCode |= 0x10; // 放大 | |
| 21 | + else if(inOut == 1) cmdCode |= 0x20; // 缩小 | |
| 22 | + char[] szCmd = new char[16]; | |
| 23 | + String strTmp; | |
| 24 | + szCmd[0] = 'A'; //字节1 A5 | |
| 25 | + szCmd[1] = '5'; | |
| 26 | + szCmd[2] = '0'; //字节2 0F | |
| 27 | + szCmd[3] = 'F'; | |
| 28 | + szCmd[4] = '0'; //字节3 地址的低8位 | |
| 29 | + szCmd[5] = '1'; | |
| 30 | + strTmp = String.format("%02X", cmdCode); | |
| 31 | + szCmd[6] = strTmp.charAt(0); //字节4 控制码 | |
| 32 | + szCmd[7] = strTmp.charAt(1); | |
| 33 | + strTmp = String.format("%02X", moveSpeed); | |
| 34 | + szCmd[8] = strTmp.charAt(0); //字节5 水平控制速度 | |
| 35 | + szCmd[9] = strTmp.charAt(1); | |
| 36 | + szCmd[10] = strTmp.charAt(0); //字节6 垂直控制速度 | |
| 37 | + szCmd[11] = strTmp.charAt(1); | |
| 38 | + strTmp = String.format("%X", zoomSpeed); | |
| 39 | + szCmd[12] = strTmp.charAt(0); //字节7高4位 缩放控制速度 | |
| 40 | + szCmd[13] = '0'; //字节7低4位 地址的高4位 | |
| 41 | + //计算校验码 | |
| 42 | + int nCheck = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed << 4 & 0XF0)) % 0X100; | |
| 43 | + strTmp = String.format("%02X", nCheck); | |
| 44 | + szCmd[14] = strTmp.charAt(0); //字节8 校验码 | |
| 45 | + szCmd[15] = strTmp.charAt(1); | |
| 46 | + return String.valueOf(szCmd); | |
| 47 | + } | |
| 48 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; | |
| 2 | + | |
| 3 | +import java.text.ParseException; | |
| 4 | +import java.util.Random; | |
| 5 | + | |
| 6 | +import javax.sip.InvalidArgumentException; | |
| 7 | +import javax.sip.SipException; | |
| 8 | +import javax.sip.message.Request; | |
| 9 | + | |
| 10 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 11 | +import org.springframework.stereotype.Component; | |
| 12 | + | |
| 13 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 14 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 15 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 16 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | |
| 17 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; | |
| 18 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 19 | + | |
| 20 | +/** | |
| 21 | + * @Description:设备能力接口,用于定义设备的控制、查询能力 | |
| 22 | + * @author: songww | |
| 23 | + * @date: 2020年5月3日 下午9:22:48 | |
| 24 | + */ | |
| 25 | +@Component | |
| 26 | +public class SIPCommander implements ISIPCommander { | |
| 27 | + | |
| 28 | + @Autowired | |
| 29 | + private SipConfig config; | |
| 30 | + | |
| 31 | + @Autowired | |
| 32 | + private SIPRequestHeaderProvider headerProvider; | |
| 33 | + | |
| 34 | + @Autowired | |
| 35 | + private SipLayer sipLayer; | |
| 36 | + | |
| 37 | + @Autowired | |
| 38 | + private IVideoManagerStorager storager; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 云台方向放控制,使用配置文件中的默认镜头移动速度 | |
| 42 | + * | |
| 43 | + * @param deviceId 控制设备 | |
| 44 | + * @param channelId 预览通道 | |
| 45 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 46 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 47 | + * @param moveSpeed 镜头移动速度 | |
| 48 | + */ | |
| 49 | + @Override | |
| 50 | + public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown) { | |
| 51 | + return ptzCmd(deviceId, channelId, leftRight, upDown, 0, config.getSpeed(), 0); | |
| 52 | + } | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 云台方向放控制 | |
| 56 | + * | |
| 57 | + * @param deviceId 控制设备 | |
| 58 | + * @param channelId 预览通道 | |
| 59 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 60 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 61 | + * @param moveSpeed 镜头移动速度 | |
| 62 | + */ | |
| 63 | + @Override | |
| 64 | + public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown, int moveSpeed) { | |
| 65 | + return ptzCmd(deviceId, channelId, leftRight, upDown, 0, moveSpeed, 0); | |
| 66 | + } | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 云台缩放控制,使用配置文件中的默认镜头缩放速度 | |
| 70 | + * | |
| 71 | + * @param deviceId 控制设备 | |
| 72 | + * @param channelId 预览通道 | |
| 73 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 74 | + */ | |
| 75 | + @Override | |
| 76 | + public boolean ptzZoomCmd(String deviceId, String channelId, int inOut) { | |
| 77 | + return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, config.getSpeed()); | |
| 78 | + } | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 云台缩放控制 | |
| 82 | + * | |
| 83 | + * @param deviceId 控制设备 | |
| 84 | + * @param channelId 预览通道 | |
| 85 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 86 | + * @param zoomSpeed 镜头缩放速度 | |
| 87 | + */ | |
| 88 | + @Override | |
| 89 | + public boolean ptzZoomCmd(String deviceId, String channelId, int inOut, int zoomSpeed) { | |
| 90 | + return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, zoomSpeed); | |
| 91 | + } | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * 云台控制,支持方向与缩放控制 | |
| 95 | + * | |
| 96 | + * @param deviceId 控制设备 | |
| 97 | + * @param channelId 预览通道 | |
| 98 | + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 | |
| 99 | + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 | |
| 100 | + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 | |
| 101 | + * @param moveSpeed 镜头移动速度 | |
| 102 | + * @param zoomSpeed 镜头缩放速度 | |
| 103 | + */ | |
| 104 | + @Override | |
| 105 | + public boolean ptzCmd(String deviceId, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, | |
| 106 | + int zoomSpeed) { | |
| 107 | + try { | |
| 108 | + Device device = storager.queryVideoDevice(deviceId); | |
| 109 | + StringBuffer ptzXml = new StringBuffer(200); | |
| 110 | + ptzXml.append("<?xml version=\"1.0\" ?>"); | |
| 111 | + ptzXml.append("<Control>"); | |
| 112 | + ptzXml.append("<CmdType>DeviceControl</CmdType>"); | |
| 113 | + ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>"); | |
| 114 | + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>"); | |
| 115 | + ptzXml.append("<PTZCmd>" + PtzCmdHelper.create(leftRight, upDown, inOut, moveSpeed, zoomSpeed) + "</PTZCmd>"); | |
| 116 | + ptzXml.append("<Info>"); | |
| 117 | + ptzXml.append("</Info>"); | |
| 118 | + ptzXml.append("</Control>"); | |
| 119 | + | |
| 120 | + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag"); | |
| 121 | + | |
| 122 | + transmitRequest(device.getTransport(), request); | |
| 123 | + | |
| 124 | + return true; | |
| 125 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 126 | + e.printStackTrace(); | |
| 127 | + } | |
| 128 | + return false; | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * 请求预览视频流 | |
| 133 | + * | |
| 134 | + * @param deviceId 视频设备 | |
| 135 | + * @param channelId 预览通道 | |
| 136 | + */ | |
| 137 | + @Override | |
| 138 | + public String playStreamCmd(String deviceId, String channelId) { | |
| 139 | + try { | |
| 140 | + | |
| 141 | + Device device = storager.queryVideoDevice(deviceId); | |
| 142 | + | |
| 143 | + //生成ssrc标识数据流 10位数字 | |
| 144 | + String ssrc = ""; | |
| 145 | + Random random = new Random(); | |
| 146 | + // ZLMediaServer最大识别7FFFFFFF即2147483647,所以随机数不能超过这个数 | |
| 147 | + ssrc = String.valueOf(random.nextInt(2147483647)); | |
| 148 | + // | |
| 149 | + StringBuffer content = new StringBuffer(200); | |
| 150 | + content.append("v=0\r\n"); | |
| 151 | + content.append("o="+channelId+" 0 0 IN IP4 "+config.getSipIp()+"\r\n"); | |
| 152 | + content.append("s=Play\r\n"); | |
| 153 | + content.append("c=IN IP4 "+config.getMediaIp()+"\r\n"); | |
| 154 | + content.append("t=0 0\r\n"); | |
| 155 | + if(device.getTransport().equals("TCP")) { | |
| 156 | + content.append("m=video "+config.getMediaPort()+" TCP/RTP/AVP 96 98 97\r\n"); | |
| 157 | + } | |
| 158 | + if(device.getTransport().equals("UDP")) { | |
| 159 | + content.append("m=video "+config.getMediaPort()+" RTP/AVP 96 98 97\r\n"); | |
| 160 | + } | |
| 161 | + content.append("a=sendrecv\r\n"); | |
| 162 | + content.append("a=rtpmap:96 PS/90000\r\n"); | |
| 163 | + content.append("a=rtpmap:98 H264/90000\r\n"); | |
| 164 | + content.append("a=rtpmap:97 MPEG4/90000\r\n"); | |
| 165 | + if(device.getTransport().equals("TCP")){ | |
| 166 | + content.append("a=setup:passive\r\n"); | |
| 167 | + content.append("a=connection:new\r\n"); | |
| 168 | + } | |
| 169 | + content.append("y="+ssrc+"\r\n");//ssrc | |
| 170 | + | |
| 171 | + Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null); | |
| 172 | + | |
| 173 | + transmitRequest(device.getTransport(), request); | |
| 174 | + return ssrc; | |
| 175 | + } catch ( SipException | ParseException | InvalidArgumentException e) { | |
| 176 | + e.printStackTrace(); | |
| 177 | + return null; | |
| 178 | + } | |
| 179 | + } | |
| 180 | + | |
| 181 | + /** | |
| 182 | + * 语音广播 | |
| 183 | + * | |
| 184 | + * @param deviceId 视频设备 | |
| 185 | + * @param channelId 预览通道 | |
| 186 | + */ | |
| 187 | + @Override | |
| 188 | + public String audioBroadcastCmd(String deviceId, String channelId) { | |
| 189 | + // TODO Auto-generated method stub | |
| 190 | + return null; | |
| 191 | + } | |
| 192 | + | |
| 193 | + /** | |
| 194 | + * 音视频录像控制 | |
| 195 | + * | |
| 196 | + * @param deviceId 视频设备 | |
| 197 | + * @param channelId 预览通道 | |
| 198 | + */ | |
| 199 | + @Override | |
| 200 | + public String recordCmd(String deviceId, String channelId) { | |
| 201 | + // TODO Auto-generated method stub | |
| 202 | + return null; | |
| 203 | + } | |
| 204 | + | |
| 205 | + /** | |
| 206 | + * 报警布防/撤防命令 | |
| 207 | + * | |
| 208 | + * @param deviceId 视频设备 | |
| 209 | + */ | |
| 210 | + @Override | |
| 211 | + public String guardCmd(String deviceId) { | |
| 212 | + // TODO Auto-generated method stub | |
| 213 | + return null; | |
| 214 | + } | |
| 215 | + | |
| 216 | + /** | |
| 217 | + * 报警复位命令 | |
| 218 | + * | |
| 219 | + * @param deviceId 视频设备 | |
| 220 | + */ | |
| 221 | + @Override | |
| 222 | + public String alarmCmd(String deviceId) { | |
| 223 | + // TODO Auto-generated method stub | |
| 224 | + return null; | |
| 225 | + } | |
| 226 | + | |
| 227 | + /** | |
| 228 | + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 | |
| 229 | + * | |
| 230 | + * @param deviceId 视频设备 | |
| 231 | + * @param channelId 预览通道 | |
| 232 | + */ | |
| 233 | + @Override | |
| 234 | + public String iFameCmd(String deviceId, String channelId) { | |
| 235 | + // TODO Auto-generated method stub | |
| 236 | + return null; | |
| 237 | + } | |
| 238 | + | |
| 239 | + /** | |
| 240 | + * 看守位控制命令 | |
| 241 | + * | |
| 242 | + * @param deviceId 视频设备 | |
| 243 | + */ | |
| 244 | + @Override | |
| 245 | + public String homePositionCmd(String deviceId) { | |
| 246 | + // TODO Auto-generated method stub | |
| 247 | + return null; | |
| 248 | + } | |
| 249 | + | |
| 250 | + /** | |
| 251 | + * 设备配置命令 | |
| 252 | + * | |
| 253 | + * @param deviceId 视频设备 | |
| 254 | + */ | |
| 255 | + @Override | |
| 256 | + public String deviceConfigCmd(String deviceId) { | |
| 257 | + // TODO Auto-generated method stub | |
| 258 | + return null; | |
| 259 | + } | |
| 260 | + | |
| 261 | + /** | |
| 262 | + * 查询设备状态 | |
| 263 | + * | |
| 264 | + * @param device 视频设备 | |
| 265 | + */ | |
| 266 | + @Override | |
| 267 | + public boolean deviceStatusQuery(Device device) { | |
| 268 | + // TODO Auto-generated method stub | |
| 269 | + return false; | |
| 270 | + } | |
| 271 | + | |
| 272 | + /** | |
| 273 | + * 查询设备信息 | |
| 274 | + * | |
| 275 | + * @param device 视频设备 | |
| 276 | + */ | |
| 277 | + @Override | |
| 278 | + public boolean deviceInfoQuery(Device device) { | |
| 279 | + try { | |
| 280 | + StringBuffer catalogXml = new StringBuffer(200); | |
| 281 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>"); | |
| 282 | + catalogXml.append("<Query>"); | |
| 283 | + catalogXml.append("<CmdType>DeviceInfo</CmdType>"); | |
| 284 | + catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>"); | |
| 285 | + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>"); | |
| 286 | + catalogXml.append("</Query>"); | |
| 287 | + | |
| 288 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag"); | |
| 289 | + | |
| 290 | + transmitRequest(device.getTransport(), request); | |
| 291 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 292 | + e.printStackTrace(); | |
| 293 | + return false; | |
| 294 | + } | |
| 295 | + return true; | |
| 296 | + } | |
| 297 | + | |
| 298 | + /** | |
| 299 | + * 查询目录列表 | |
| 300 | + * | |
| 301 | + * @param device 视频设备 | |
| 302 | + */ | |
| 303 | + @Override | |
| 304 | + public boolean catalogQuery(Device device) { | |
| 305 | + try { | |
| 306 | + StringBuffer catalogXml = new StringBuffer(200); | |
| 307 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>"); | |
| 308 | + catalogXml.append("<Query>"); | |
| 309 | + catalogXml.append("<CmdType>Catalog</CmdType>"); | |
| 310 | + catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>"); | |
| 311 | + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>"); | |
| 312 | + catalogXml.append("</Query>"); | |
| 313 | + | |
| 314 | + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag"); | |
| 315 | + | |
| 316 | + transmitRequest(device.getTransport(), request); | |
| 317 | + | |
| 318 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 319 | + e.printStackTrace(); | |
| 320 | + return false; | |
| 321 | + } | |
| 322 | + return true; | |
| 323 | + } | |
| 324 | + | |
| 325 | + /** | |
| 326 | + * 查询录像信息 | |
| 327 | + * | |
| 328 | + * @param device 视频设备 | |
| 329 | + */ | |
| 330 | + @Override | |
| 331 | + public boolean recordInfoQuery(Device device) { | |
| 332 | + // TODO Auto-generated method stub | |
| 333 | + return false; | |
| 334 | + } | |
| 335 | + | |
| 336 | + /** | |
| 337 | + * 查询报警信息 | |
| 338 | + * | |
| 339 | + * @param device 视频设备 | |
| 340 | + */ | |
| 341 | + @Override | |
| 342 | + public boolean alarmInfoQuery(Device device) { | |
| 343 | + // TODO Auto-generated method stub | |
| 344 | + return false; | |
| 345 | + } | |
| 346 | + | |
| 347 | + /** | |
| 348 | + * 查询设备配置 | |
| 349 | + * | |
| 350 | + * @param device 视频设备 | |
| 351 | + */ | |
| 352 | + @Override | |
| 353 | + public boolean configQuery(Device device) { | |
| 354 | + // TODO Auto-generated method stub | |
| 355 | + return false; | |
| 356 | + } | |
| 357 | + | |
| 358 | + /** | |
| 359 | + * 查询设备预置位置 | |
| 360 | + * | |
| 361 | + * @param device 视频设备 | |
| 362 | + */ | |
| 363 | + @Override | |
| 364 | + public boolean presetQuery(Device device) { | |
| 365 | + // TODO Auto-generated method stub | |
| 366 | + return false; | |
| 367 | + } | |
| 368 | + | |
| 369 | + /** | |
| 370 | + * 查询移动设备位置数据 | |
| 371 | + * | |
| 372 | + * @param device 视频设备 | |
| 373 | + */ | |
| 374 | + @Override | |
| 375 | + public boolean mobilePostitionQuery(Device device) { | |
| 376 | + // TODO Auto-generated method stub | |
| 377 | + return false; | |
| 378 | + } | |
| 379 | + | |
| 380 | + private void transmitRequest(String transport, Request request) throws SipException { | |
| 381 | + if(transport.equals("TCP")) { | |
| 382 | + sipLayer.getTcpSipProvider().sendRequest(request); | |
| 383 | + } else if(transport.equals("UDP")) { | |
| 384 | + sipLayer.getUdpSipProvider().sendRequest(request); | |
| 385 | + } | |
| 386 | + } | |
| 387 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/ISIPRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/ISIPRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request; | |
| 2 | + | |
| 3 | +import javax.sip.RequestEvent; | |
| 4 | +import javax.sip.ServerTransaction; | |
| 5 | + | |
| 6 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * @Description:处理接收IPCamera发来的SIP协议请求消息 | |
| 10 | + * @author: songww | |
| 11 | + * @date: 2020年5月3日 下午4:42:22 | |
| 12 | + */ | |
| 13 | +public interface ISIPRequestProcessor { | |
| 14 | + | |
| 15 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction); | |
| 16 | + | |
| 17 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import javax.sip.Dialog; | |
| 4 | +import javax.sip.InvalidArgumentException; | |
| 5 | +import javax.sip.RequestEvent; | |
| 6 | +import javax.sip.ServerTransaction; | |
| 7 | +import javax.sip.SipException; | |
| 8 | +import javax.sip.message.Request; | |
| 9 | + | |
| 10 | +import org.springframework.stereotype.Component; | |
| 11 | + | |
| 12 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 14 | + | |
| 15 | +import gov.nist.javax.sip.header.CSeq; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * @Description:ACK请求处理器 | |
| 19 | + * @author: songww | |
| 20 | + * @date: 2020年5月3日 下午5:31:45 | |
| 21 | + */ | |
| 22 | +@Component | |
| 23 | +public class AckRequestProcessor implements ISIPRequestProcessor { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 处理 ACK请求 | |
| 27 | + * | |
| 28 | + * @param evt | |
| 29 | + * @param layer | |
| 30 | + * @param transaction | |
| 31 | + * @param config | |
| 32 | + */ | |
| 33 | + @Override | |
| 34 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 35 | + Request request = evt.getRequest(); | |
| 36 | + Dialog dialog = evt.getDialog(); | |
| 37 | + try { | |
| 38 | + Request ackRequest = null; | |
| 39 | + CSeq csReq = (CSeq) request.getHeader(CSeq.NAME); | |
| 40 | + ackRequest = dialog.createAck(csReq.getSeqNumber()); | |
| 41 | + dialog.sendAck(ackRequest); | |
| 42 | + System.out.println("send ack to callee:" + ackRequest.toString()); | |
| 43 | + } catch (SipException e) { | |
| 44 | + e.printStackTrace(); | |
| 45 | + } catch (InvalidArgumentException e) { | |
| 46 | + e.printStackTrace(); | |
| 47 | + } | |
| 48 | + | |
| 49 | + } | |
| 50 | + | |
| 51 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import javax.sip.RequestEvent; | |
| 4 | +import javax.sip.ServerTransaction; | |
| 5 | + | |
| 6 | +import org.springframework.stereotype.Component; | |
| 7 | + | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description: BYE请求处理器 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午5:32:05 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class ByeRequestProcessor implements ISIPRequestProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 处理BYE请求 | |
| 21 | + * | |
| 22 | + * @param evt | |
| 23 | + * @param layer | |
| 24 | + * @param transaction | |
| 25 | + * @param config | |
| 26 | + */ | |
| 27 | + @Override | |
| 28 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 29 | + // TODO Auto-generated method stub | |
| 30 | + | |
| 31 | + } | |
| 32 | + | |
| 33 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/CancelRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/CancelRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import javax.sip.RequestEvent; | |
| 4 | +import javax.sip.ServerTransaction; | |
| 5 | + | |
| 6 | +import org.springframework.stereotype.Component; | |
| 7 | + | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description:CANCEL请求处理器 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午5:32:23 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class CancelRequestProcessor implements ISIPRequestProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 处理CANCEL请求 | |
| 21 | + * | |
| 22 | + * @param evt | |
| 23 | + * @param layer | |
| 24 | + * @param transaction | |
| 25 | + * @param config | |
| 26 | + */ | |
| 27 | + @Override | |
| 28 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 29 | + // TODO Auto-generated method stub | |
| 30 | + | |
| 31 | + } | |
| 32 | + | |
| 33 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import javax.sip.RequestEvent; | |
| 4 | +import javax.sip.ServerTransaction; | |
| 5 | + | |
| 6 | +import org.springframework.stereotype.Component; | |
| 7 | + | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description:处理INVITE请求 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午4:43:52 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class InviteRequestProcessor implements ISIPRequestProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 处理invite请求 | |
| 21 | + * | |
| 22 | + * @param request | |
| 23 | + * 请求消息 | |
| 24 | + */ | |
| 25 | + @Override | |
| 26 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 27 | + // TODO Auto-generated method stub | |
| 28 | +// Request request = requestEvent.getRequest(); | |
| 29 | +// | |
| 30 | +// try { | |
| 31 | +// // 发送100 Trying | |
| 32 | +// ServerTransaction serverTransaction = getServerTransaction(requestEvent); | |
| 33 | +// // 查询目标地址 | |
| 34 | +// URI reqUri = request.getRequestURI(); | |
| 35 | +// URI contactURI = currUser.get(reqUri); | |
| 36 | +// | |
| 37 | +// System.out.println("processInvite rqStr=" + reqUri + " contact=" + contactURI); | |
| 38 | +// | |
| 39 | +// // 根据Request uri来路由,后续的响应消息通过VIA来路由 | |
| 40 | +// Request cliReq = messageFactory.createRequest(request.toString()); | |
| 41 | +// cliReq.setRequestURI(contactURI); | |
| 42 | +// | |
| 43 | +// HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory(); | |
| 44 | +// Via callerVia = (Via) request.getHeader(Via.NAME); | |
| 45 | +// Via via = (Via) headerFactory.createViaHeader(SIPMain.ip, SIPMain.port, "UDP", | |
| 46 | +// callerVia.getBranch() + "sipphone"); | |
| 47 | +// | |
| 48 | +// // FIXME 需要测试是否能够通过设置VIA头域来修改VIA头域值 | |
| 49 | +// cliReq.removeHeader(Via.NAME); | |
| 50 | +// cliReq.addHeader(via); | |
| 51 | +// | |
| 52 | +// // 更新contact的地址 | |
| 53 | +// ContactHeader contactHeader = headerFactory.createContactHeader(); | |
| 54 | +// Address address = SipFactory.getInstance().createAddressFactory() | |
| 55 | +// .createAddress("sip:sipsoft@" + SIPMain.ip + ":" + SIPMain.port); | |
| 56 | +// contactHeader.setAddress(address); | |
| 57 | +// contactHeader.setExpires(3600); | |
| 58 | +// cliReq.setHeader(contactHeader); | |
| 59 | +// | |
| 60 | +// clientTransactionId = sipProvider.getNewClientTransaction(cliReq); | |
| 61 | +// clientTransactionId.sendRequest(); | |
| 62 | +// | |
| 63 | +// System.out.println("processInvite clientTransactionId=" + clientTransactionId.toString()); | |
| 64 | +// | |
| 65 | +// System.out.println("send invite to callee: " + cliReq); | |
| 66 | +// } catch (TransactionUnavailableException e1) { | |
| 67 | +// e1.printStackTrace(); | |
| 68 | +// } catch (SipException e) { | |
| 69 | +// e.printStackTrace(); | |
| 70 | +// } catch (ParseException e) { | |
| 71 | +// e.printStackTrace(); | |
| 72 | +// } catch (Exception e) { | |
| 73 | +// e.printStackTrace(); | |
| 74 | +// } | |
| 75 | + } | |
| 76 | + | |
| 77 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import java.io.ByteArrayInputStream; | |
| 4 | +import java.text.ParseException; | |
| 5 | +import java.util.HashMap; | |
| 6 | +import java.util.Iterator; | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +import javax.sip.InvalidArgumentException; | |
| 10 | +import javax.sip.RequestEvent; | |
| 11 | +import javax.sip.ServerTransaction; | |
| 12 | +import javax.sip.SipException; | |
| 13 | +import javax.sip.message.Request; | |
| 14 | +import javax.sip.message.Response; | |
| 15 | + | |
| 16 | +import org.dom4j.Document; | |
| 17 | +import org.dom4j.DocumentException; | |
| 18 | +import org.dom4j.Element; | |
| 19 | +import org.dom4j.io.SAXReader; | |
| 20 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 21 | +import org.springframework.stereotype.Component; | |
| 22 | + | |
| 23 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 24 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 25 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 26 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | |
| 27 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 28 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 29 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 30 | +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | |
| 31 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 32 | + | |
| 33 | +/** | |
| 34 | + * @Description:MESSAGE请求处理器 | |
| 35 | + * @author: songww | |
| 36 | + * @date: 2020年5月3日 下午5:32:41 | |
| 37 | + */ | |
| 38 | +@Component | |
| 39 | +public class MessageRequestProcessor implements ISIPRequestProcessor { | |
| 40 | + | |
| 41 | + private ServerTransaction transaction; | |
| 42 | + | |
| 43 | + private SipLayer layer; | |
| 44 | + | |
| 45 | + @Autowired | |
| 46 | + private SIPCommander cmder; | |
| 47 | + | |
| 48 | + @Autowired | |
| 49 | + private IVideoManagerStorager storager; | |
| 50 | + | |
| 51 | + @Autowired | |
| 52 | + private EventPublisher publisher; | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 处理MESSAGE请求 | |
| 56 | + * | |
| 57 | + * @param evt | |
| 58 | + * @param layer | |
| 59 | + * @param transaction | |
| 60 | + */ | |
| 61 | + @Override | |
| 62 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 63 | + | |
| 64 | + this.layer = layer; | |
| 65 | + this.transaction = transaction; | |
| 66 | + | |
| 67 | + Request request = evt.getRequest(); | |
| 68 | + | |
| 69 | + if (new String(request.getRawContent()).contains("<CmdType>Keepalive</CmdType>")) { | |
| 70 | + processMessageKeepAlive(evt); | |
| 71 | + } else if (new String(request.getRawContent()).contains("<CmdType>Catalog</CmdType>")) { | |
| 72 | + processMessageCatalogList(evt); | |
| 73 | + } else if (new String(request.getRawContent()).contains("<CmdType>DeviceInfo</CmdType>")) { | |
| 74 | + processMessageDeviceInfo(evt); | |
| 75 | + } else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) { | |
| 76 | + processMessageAlarm(evt); | |
| 77 | + } | |
| 78 | + | |
| 79 | + } | |
| 80 | + | |
| 81 | + /*** | |
| 82 | + * 收到catalog设备目录列表请求 处理 | |
| 83 | + * @param evt | |
| 84 | + */ | |
| 85 | + private void processMessageCatalogList(RequestEvent evt) { | |
| 86 | + try { | |
| 87 | + Request request = evt.getRequest(); | |
| 88 | + SAXReader reader = new SAXReader(); | |
| 89 | + reader.setEncoding("GB2312"); | |
| 90 | + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | |
| 91 | + Element rootElement = xml.getRootElement(); | |
| 92 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 93 | + String deviceId = deviceIdElement.getText().toString(); | |
| 94 | + Element deviceListElement = rootElement.element("DeviceList"); | |
| 95 | + if (deviceListElement == null) { | |
| 96 | + return; | |
| 97 | + } | |
| 98 | + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); | |
| 99 | + if (deviceListIterator != null) { | |
| 100 | + Device device = storager.queryVideoDevice(deviceId); | |
| 101 | + if (device == null) { | |
| 102 | + return; | |
| 103 | + } | |
| 104 | + Map<String, DeviceChannel> channelMap = device.getChannelMap(); | |
| 105 | + if (channelMap == null) { | |
| 106 | + channelMap = new HashMap<String, DeviceChannel>(5); | |
| 107 | + device.setChannelMap(channelMap); | |
| 108 | + } | |
| 109 | + // 遍历DeviceList | |
| 110 | + while (deviceListIterator.hasNext()) { | |
| 111 | + Element itemDevice = deviceListIterator.next(); | |
| 112 | + Element channelDeviceElement = itemDevice.element("DeviceID"); | |
| 113 | + if (channelDeviceElement == null) { | |
| 114 | + continue; | |
| 115 | + } | |
| 116 | + String channelDeviceId = channelDeviceElement.getText().toString(); | |
| 117 | + Element channdelNameElement = itemDevice.element("Name"); | |
| 118 | + String channelName = channdelNameElement != null ? channdelNameElement.getText().toString() : ""; | |
| 119 | + Element statusElement = itemDevice.element("Status"); | |
| 120 | + String status = statusElement != null ? statusElement.getText().toString() : "ON"; | |
| 121 | + DeviceChannel deviceChannel = channelMap.containsKey(channelDeviceId) ? channelMap.get(channelDeviceId) : new DeviceChannel(); | |
| 122 | + deviceChannel.setName(channelName); | |
| 123 | + deviceChannel.setChannelId(channelDeviceId); | |
| 124 | + if(status.equals("ON")) { | |
| 125 | + deviceChannel.setStatus(1); | |
| 126 | + } | |
| 127 | + if(status.equals("OFF")) { | |
| 128 | + deviceChannel.setStatus(0); | |
| 129 | + } | |
| 130 | + | |
| 131 | + deviceChannel.setManufacture(XmlUtil.getText(itemDevice,"Manufacturer")); | |
| 132 | + deviceChannel.setModel(XmlUtil.getText(itemDevice,"Model")); | |
| 133 | + deviceChannel.setOwner(XmlUtil.getText(itemDevice,"Owner")); | |
| 134 | + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice,"CivilCode")); | |
| 135 | + deviceChannel.setBlock(XmlUtil.getText(itemDevice,"Block")); | |
| 136 | + deviceChannel.setAddress(XmlUtil.getText(itemDevice,"Address")); | |
| 137 | + deviceChannel.setParental(itemDevice.element("Parental") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"Parental"))); | |
| 138 | + deviceChannel.setParentId(XmlUtil.getText(itemDevice,"ParentId")); | |
| 139 | + deviceChannel.setSafetyWay(itemDevice.element("SafetyWay") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"SafetyWay"))); | |
| 140 | + deviceChannel.setRegisterWay(itemDevice.element("RegisterWay") == null? 1:Integer.parseInt(XmlUtil.getText(itemDevice,"RegisterWay"))); | |
| 141 | + deviceChannel.setCertNum(XmlUtil.getText(itemDevice,"CertNum")); | |
| 142 | + deviceChannel.setCertifiable(itemDevice.element("Certifiable") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"Certifiable"))); | |
| 143 | + deviceChannel.setErrCode(itemDevice.element("ErrCode") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"ErrCode"))); | |
| 144 | + deviceChannel.setEndTime(XmlUtil.getText(itemDevice,"EndTime")); | |
| 145 | + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice,"Secrecy")); | |
| 146 | + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice,"IPAddress")); | |
| 147 | + deviceChannel.setPort(itemDevice.element("Port") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"Port"))); | |
| 148 | + deviceChannel.setPassword(XmlUtil.getText(itemDevice,"Password")); | |
| 149 | + deviceChannel.setLongitude(itemDevice.element("Longitude") == null? 0.00:Double.parseDouble(XmlUtil.getText(itemDevice,"Longitude"))); | |
| 150 | + deviceChannel.setLatitude(itemDevice.element("Latitude") == null? 0.00:Double.parseDouble(XmlUtil.getText(itemDevice,"Latitude"))); | |
| 151 | + channelMap.put(channelDeviceId, deviceChannel); | |
| 152 | + } | |
| 153 | + // 更新 | |
| 154 | + storager.update(device); | |
| 155 | + } | |
| 156 | + } catch (DocumentException e) { | |
| 157 | + e.printStackTrace(); | |
| 158 | + } | |
| 159 | + } | |
| 160 | + | |
| 161 | + /*** | |
| 162 | + * 收到deviceInfo设备信息请求 处理 | |
| 163 | + * @param evt | |
| 164 | + */ | |
| 165 | + private void processMessageDeviceInfo(RequestEvent evt) { | |
| 166 | + try { | |
| 167 | + Request request = evt.getRequest(); | |
| 168 | + SAXReader reader = new SAXReader(); | |
| 169 | + // reader.setEncoding("GB2312"); | |
| 170 | + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | |
| 171 | + Element rootElement = xml.getRootElement(); | |
| 172 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 173 | + String deviceId = deviceIdElement.getText().toString(); | |
| 174 | + | |
| 175 | + Device device = storager.queryVideoDevice(deviceId); | |
| 176 | + if (device == null) { | |
| 177 | + return; | |
| 178 | + } | |
| 179 | + device.setName(XmlUtil.getText(rootElement,"DeviceName")); | |
| 180 | + device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer")); | |
| 181 | + device.setModel(XmlUtil.getText(rootElement,"Model")); | |
| 182 | + device.setFirmware(XmlUtil.getText(rootElement,"Firmware")); | |
| 183 | + storager.update(device); | |
| 184 | + cmder.catalogQuery(device); | |
| 185 | + } catch (DocumentException e) { | |
| 186 | + e.printStackTrace(); | |
| 187 | + } | |
| 188 | + } | |
| 189 | + | |
| 190 | + /*** | |
| 191 | + * 收到alarm设备报警信息 处理 | |
| 192 | + * @param evt | |
| 193 | + */ | |
| 194 | + private void processMessageAlarm(RequestEvent evt) { | |
| 195 | + try { | |
| 196 | + Request request = evt.getRequest(); | |
| 197 | + SAXReader reader = new SAXReader(); | |
| 198 | + // reader.setEncoding("GB2312"); | |
| 199 | + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | |
| 200 | + Element rootElement = xml.getRootElement(); | |
| 201 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 202 | + String deviceId = deviceIdElement.getText().toString(); | |
| 203 | + | |
| 204 | + Device device = storager.queryVideoDevice(deviceId); | |
| 205 | + if (device == null) { | |
| 206 | + return; | |
| 207 | + } | |
| 208 | + device.setName(XmlUtil.getText(rootElement,"DeviceName")); | |
| 209 | + device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer")); | |
| 210 | + device.setModel(XmlUtil.getText(rootElement,"Model")); | |
| 211 | + device.setFirmware(XmlUtil.getText(rootElement,"Firmware")); | |
| 212 | + storager.update(device); | |
| 213 | + cmder.catalogQuery(device); | |
| 214 | + } catch (DocumentException e) { | |
| 215 | + e.printStackTrace(); | |
| 216 | + } | |
| 217 | + } | |
| 218 | + | |
| 219 | + /*** | |
| 220 | + * 收到keepalive请求 处理 | |
| 221 | + * @param evt | |
| 222 | + */ | |
| 223 | + private void processMessageKeepAlive(RequestEvent evt){ | |
| 224 | + try { | |
| 225 | + Request request = evt.getRequest(); | |
| 226 | + Response response = layer.getMessageFactory().createResponse(Response.OK,request); | |
| 227 | + SAXReader reader = new SAXReader(); | |
| 228 | + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); | |
| 229 | + // reader.setEncoding("GB2312"); | |
| 230 | + Element rootElement = xml.getRootElement(); | |
| 231 | + Element deviceIdElement = rootElement.element("DeviceID"); | |
| 232 | + transaction.sendResponse(response); | |
| 233 | + publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); | |
| 234 | + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | |
| 235 | + e.printStackTrace(); | |
| 236 | + } | |
| 237 | + } | |
| 238 | + | |
| 239 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import javax.sip.RequestEvent; | |
| 4 | +import javax.sip.ServerTransaction; | |
| 5 | + | |
| 6 | +import org.springframework.stereotype.Component; | |
| 7 | + | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description:暂不支持的消息请求处理器 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午5:32:59 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class OtherRequestProcessor implements ISIPRequestProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * <p>Title: process</p> | |
| 21 | + * <p>Description: </p> | |
| 22 | + * @param evt | |
| 23 | + * @param layer | |
| 24 | + * @param transaction | |
| 25 | + * @param config | |
| 26 | + */ | |
| 27 | + @Override | |
| 28 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 29 | + System.out.println("no support the method! Method:" + evt.getRequest().getMethod()); | |
| 30 | + } | |
| 31 | + | |
| 32 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import java.security.NoSuchAlgorithmException; | |
| 4 | +import java.text.ParseException; | |
| 5 | +import java.util.Calendar; | |
| 6 | +import java.util.Locale; | |
| 7 | + | |
| 8 | +import javax.sip.InvalidArgumentException; | |
| 9 | +import javax.sip.RequestEvent; | |
| 10 | +import javax.sip.ServerTransaction; | |
| 11 | +import javax.sip.SipException; | |
| 12 | +import javax.sip.header.AuthorizationHeader; | |
| 13 | +import javax.sip.header.ContactHeader; | |
| 14 | +import javax.sip.header.ExpiresHeader; | |
| 15 | +import javax.sip.header.FromHeader; | |
| 16 | +import javax.sip.header.ViaHeader; | |
| 17 | +import javax.sip.message.Request; | |
| 18 | +import javax.sip.message.Response; | |
| 19 | + | |
| 20 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 21 | +import org.springframework.stereotype.Component; | |
| 22 | +import org.springframework.util.StringUtils; | |
| 23 | + | |
| 24 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 25 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 26 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 27 | +import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; | |
| 28 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 29 | +import com.genersoft.iot.vmp.gb28181.bean.Host; | |
| 30 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 31 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 32 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 33 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 34 | + | |
| 35 | +import gov.nist.javax.sip.address.AddressImpl; | |
| 36 | +import gov.nist.javax.sip.address.SipUri; | |
| 37 | +import gov.nist.javax.sip.header.Expires; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * @Description:收到注册请求 处理 | |
| 41 | + * @author: songww | |
| 42 | + * @date: 2020年5月3日 下午4:47:25 | |
| 43 | + */ | |
| 44 | +@Component | |
| 45 | +public class RegisterRequestProcessor implements ISIPRequestProcessor { | |
| 46 | + | |
| 47 | + @Autowired | |
| 48 | + private SipConfig config; | |
| 49 | + | |
| 50 | + @Autowired | |
| 51 | + private SIPCommander cmder; | |
| 52 | + | |
| 53 | + @Autowired | |
| 54 | + private IVideoManagerStorager storager; | |
| 55 | + | |
| 56 | + @Autowired | |
| 57 | + private EventPublisher publisher; | |
| 58 | + | |
| 59 | + /*** | |
| 60 | + * 收到注册请求 处理 | |
| 61 | + * | |
| 62 | + * @param request | |
| 63 | + * 请求消息 | |
| 64 | + */ | |
| 65 | + @Override | |
| 66 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 67 | + try { | |
| 68 | + System.out.println("收到注册请求,开始处理"); | |
| 69 | + Request request = evt.getRequest(); | |
| 70 | + | |
| 71 | + Response response = null; | |
| 72 | + boolean passwordCorrect = false; | |
| 73 | + // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功 | |
| 74 | + int registerFlag = 0; | |
| 75 | + Device device = null; | |
| 76 | + AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | |
| 77 | + // 校验密码是否正确 | |
| 78 | + if (authorhead != null) { | |
| 79 | + passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, | |
| 80 | + config.getSipPassword()); | |
| 81 | + } | |
| 82 | + | |
| 83 | + // 未携带授权头或者密码错误 回复401 | |
| 84 | + if (authorhead == null || !passwordCorrect) { | |
| 85 | + | |
| 86 | + if (authorhead == null) { | |
| 87 | + System.out.println("未携带授权头 回复401"); | |
| 88 | + } else if (!passwordCorrect) { | |
| 89 | + System.out.println("密码错误 回复401"); | |
| 90 | + } | |
| 91 | + response = layer.getMessageFactory().createResponse(Response.UNAUTHORIZED, request); | |
| 92 | + new DigestServerAuthenticationHelper().generateChallenge(layer.getHeaderFactory(), response, config.getSipDomain()); | |
| 93 | + } | |
| 94 | + // 携带授权头并且密码正确 | |
| 95 | + else if (passwordCorrect) { | |
| 96 | + response = layer.getMessageFactory().createResponse(Response.OK, request); | |
| 97 | + // 添加date头 | |
| 98 | + response.addHeader(layer.getHeaderFactory().createDateHeader(Calendar.getInstance(Locale.ENGLISH))); | |
| 99 | + ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); | |
| 100 | + // 添加Contact头 | |
| 101 | + response.addHeader(request.getHeader(ContactHeader.NAME)); | |
| 102 | + // 添加Expires头 | |
| 103 | + response.addHeader(request.getExpires()); | |
| 104 | + | |
| 105 | + // 1.获取到通信地址等信息,保存到Redis | |
| 106 | + FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); | |
| 107 | + ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | |
| 108 | + String received = viaHeader.getReceived(); | |
| 109 | + int rPort = viaHeader.getRPort(); | |
| 110 | + // 本地模拟设备 received 为空 rPort 为 -1 | |
| 111 | + // 解析本地地址替代 | |
| 112 | + if (StringUtils.isEmpty(received) || rPort == -1) { | |
| 113 | + received = viaHeader.getHost(); | |
| 114 | + rPort = viaHeader.getPort(); | |
| 115 | + } | |
| 116 | + // | |
| 117 | + Host host = new Host(); | |
| 118 | + host.setIp(received); | |
| 119 | + host.setPort(rPort); | |
| 120 | + host.setAddress(received.concat(":").concat(String.valueOf(rPort))); | |
| 121 | + AddressImpl address = (AddressImpl) fromHeader.getAddress(); | |
| 122 | + SipUri uri = (SipUri) address.getURI(); | |
| 123 | + String deviceId = uri.getUser(); | |
| 124 | + device = new Device(); | |
| 125 | + device.setDeviceId(deviceId); | |
| 126 | + device.setHost(host); | |
| 127 | + // 注销成功 | |
| 128 | + if (expiresHeader != null && expiresHeader.getExpires() == 0) { | |
| 129 | + registerFlag = 2; | |
| 130 | + } | |
| 131 | + // 注册成功 | |
| 132 | + else { | |
| 133 | + registerFlag = 1; | |
| 134 | + // 判断TCP还是UDP | |
| 135 | + boolean isTcp = false; | |
| 136 | + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | |
| 137 | + String transport = reqViaHeader.getTransport(); | |
| 138 | + if (transport.equals("TCP")) { | |
| 139 | + isTcp = true; | |
| 140 | + } | |
| 141 | + device.setTransport(isTcp ? "TCP" : "UDP"); | |
| 142 | + } | |
| 143 | + } | |
| 144 | + transaction.sendResponse(response); | |
| 145 | + // 注册成功 | |
| 146 | + // 保存到redis | |
| 147 | + // 下发catelog查询目录 | |
| 148 | + if (registerFlag == 1 && device != null) { | |
| 149 | + System.out.println("注册成功! deviceId:" + device.getDeviceId()); | |
| 150 | + storager.update(device); | |
| 151 | + publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER); | |
| 152 | + cmder.deviceInfoQuery(device); | |
| 153 | + } else if (registerFlag == 2) { | |
| 154 | + System.out.println("注销成功! deviceId:" + device.getDeviceId()); | |
| 155 | + publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); | |
| 156 | + } | |
| 157 | + } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { | |
| 158 | + e.printStackTrace(); | |
| 159 | + } | |
| 160 | + | |
| 161 | + } | |
| 162 | + | |
| 163 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/SubscribeRequestProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/SubscribeRequestProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.request.impl; | |
| 2 | + | |
| 3 | +import java.text.ParseException; | |
| 4 | + | |
| 5 | +import javax.sip.InvalidArgumentException; | |
| 6 | +import javax.sip.RequestEvent; | |
| 7 | +import javax.sip.ServerTransaction; | |
| 8 | +import javax.sip.SipException; | |
| 9 | +import javax.sip.header.ExpiresHeader; | |
| 10 | +import javax.sip.message.Request; | |
| 11 | +import javax.sip.message.Response; | |
| 12 | + | |
| 13 | +import org.springframework.stereotype.Component; | |
| 14 | + | |
| 15 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 16 | +import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; | |
| 17 | + | |
| 18 | +/** | |
| 19 | + * @Description:SUBSCRIBE请求处理器 | |
| 20 | + * @author: songww | |
| 21 | + * @date: 2020年5月3日 下午5:31:20 | |
| 22 | + */ | |
| 23 | +@Component | |
| 24 | +public class SubscribeRequestProcessor implements ISIPRequestProcessor { | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 处理SUBSCRIBE请求 | |
| 28 | + * | |
| 29 | + * @param evt | |
| 30 | + * @param layer | |
| 31 | + * @param transaction | |
| 32 | + * @param config | |
| 33 | + */ | |
| 34 | + @Override | |
| 35 | + public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { | |
| 36 | + Request request = evt.getRequest(); | |
| 37 | + | |
| 38 | + try { | |
| 39 | + Response response = null; | |
| 40 | + response = layer.getMessageFactory().createResponse(200, request); | |
| 41 | + if (response != null) { | |
| 42 | + ExpiresHeader expireHeader = layer.getHeaderFactory().createExpiresHeader(30); | |
| 43 | + response.setExpires(expireHeader); | |
| 44 | + } | |
| 45 | + System.out.println("response : " + response.toString()); | |
| 46 | + | |
| 47 | + if (transaction != null) { | |
| 48 | + transaction.sendResponse(response); | |
| 49 | + transaction.terminate(); | |
| 50 | + } else { | |
| 51 | + System.out.println("processRequest serverTransactionId is null."); | |
| 52 | + } | |
| 53 | + | |
| 54 | + } catch (ParseException e) { | |
| 55 | + e.printStackTrace(); | |
| 56 | + } catch (SipException e) { | |
| 57 | + e.printStackTrace(); | |
| 58 | + } catch (InvalidArgumentException e) { | |
| 59 | + e.printStackTrace(); | |
| 60 | + } | |
| 61 | + | |
| 62 | + } | |
| 63 | + | |
| 64 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/ISIPResponseProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.response; | |
| 2 | + | |
| 3 | +import javax.sip.ResponseEvent; | |
| 4 | + | |
| 5 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * @Description:处理接收IPCamera发来的SIP协议响应消息 | |
| 10 | + * @author: songww | |
| 11 | + * @date: 2020年5月3日 下午4:42:22 | |
| 12 | + */ | |
| 13 | +public interface ISIPResponseProcessor { | |
| 14 | + | |
| 15 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config); | |
| 16 | + | |
| 17 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/ByeResponseProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/ByeResponseProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.response.impl; | |
| 2 | + | |
| 3 | +import javax.sip.ResponseEvent; | |
| 4 | + | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | + | |
| 7 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description: BYE请求响应器 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午5:32:05 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class ByeResponseProcessor implements ISIPResponseProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 处理BYE响应 | |
| 21 | + * | |
| 22 | + * @param evt | |
| 23 | + * @param layer | |
| 24 | + * @param transaction | |
| 25 | + * @param config | |
| 26 | + */ | |
| 27 | + @Override | |
| 28 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { | |
| 29 | + // TODO Auto-generated method stub | |
| 30 | + | |
| 31 | + } | |
| 32 | + | |
| 33 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/CancelResponseProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/CancelResponseProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.response.impl; | |
| 2 | + | |
| 3 | +import javax.sip.ResponseEvent; | |
| 4 | + | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | + | |
| 7 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description:CANCEL响应处理器 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午5:32:23 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class CancelResponseProcessor implements ISIPResponseProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 处理CANCEL响应 | |
| 21 | + * | |
| 22 | + * @param evt | |
| 23 | + * @param layer | |
| 24 | + * @param transaction | |
| 25 | + * @param config | |
| 26 | + */ | |
| 27 | + @Override | |
| 28 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { | |
| 29 | + // TODO Auto-generated method stub | |
| 30 | + | |
| 31 | + } | |
| 32 | + | |
| 33 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.response.impl; | |
| 2 | + | |
| 3 | +import javax.sip.Dialog; | |
| 4 | +import javax.sip.InvalidArgumentException; | |
| 5 | +import javax.sip.ResponseEvent; | |
| 6 | +import javax.sip.SipException; | |
| 7 | +import javax.sip.message.Request; | |
| 8 | + | |
| 9 | +import org.springframework.stereotype.Component; | |
| 10 | + | |
| 11 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 12 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * @Description:处理INVITE响应 | |
| 17 | + * @author: songww | |
| 18 | + * @date: 2020年5月3日 下午4:43:52 | |
| 19 | + */ | |
| 20 | +@Component | |
| 21 | +public class InviteResponseProcessor implements ISIPResponseProcessor { | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 处理invite响应 | |
| 25 | + * | |
| 26 | + * @param request | |
| 27 | + * 响应消息 | |
| 28 | + */ | |
| 29 | + @Override | |
| 30 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { | |
| 31 | + try { | |
| 32 | + Dialog dialog = evt.getDialog(); | |
| 33 | + Request reqAck =dialog.createAck(1L); | |
| 34 | + dialog.sendAck(reqAck); | |
| 35 | + } catch (InvalidArgumentException | SipException e) { | |
| 36 | + e.printStackTrace(); | |
| 37 | + } | |
| 38 | + } | |
| 39 | + | |
| 40 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/OtherResponseProcessor.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/OtherResponseProcessor.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.response.impl; | |
| 2 | + | |
| 3 | +import javax.sip.ResponseEvent; | |
| 4 | + | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | + | |
| 7 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.SipLayer; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description:暂不支持的消息响应处理器 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月3日 下午5:32:59 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class OtherResponseProcessor implements ISIPResponseProcessor { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * <p>Title: process</p> | |
| 21 | + * <p>Description: </p> | |
| 22 | + * @param evt | |
| 23 | + * @param layer | |
| 24 | + * @param config | |
| 25 | + */ | |
| 26 | + @Override | |
| 27 | + public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { | |
| 28 | + // TODO Auto-generated method stub | |
| 29 | + | |
| 30 | + } | |
| 31 | + | |
| 32 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java | |
| 1 | +package com.genersoft.iot.vmp.gb28181.utils; | |
| 2 | + | |
| 3 | +import java.io.StringReader; | |
| 4 | +import java.util.ArrayList; | |
| 5 | +import java.util.HashMap; | |
| 6 | +import java.util.Iterator; | |
| 7 | +import java.util.List; | |
| 8 | +import java.util.Map; | |
| 9 | + | |
| 10 | +import org.dom4j.Attribute; | |
| 11 | +import org.dom4j.Document; | |
| 12 | +import org.dom4j.DocumentException; | |
| 13 | +import org.dom4j.Element; | |
| 14 | +import org.dom4j.io.SAXReader; | |
| 15 | +import org.slf4j.Logger; | |
| 16 | +import org.slf4j.LoggerFactory; | |
| 17 | + | |
| 18 | +/** | |
| 19 | + * 基于dom4j的工具包 | |
| 20 | + * | |
| 21 | + * | |
| 22 | + */ | |
| 23 | +public class XmlUtil | |
| 24 | +{ | |
| 25 | + /** | |
| 26 | + * 日志服务 | |
| 27 | + */ | |
| 28 | + private static Logger LOG = LoggerFactory.getLogger(XmlUtil.class); | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 解析XML为Document对象 | |
| 32 | + * | |
| 33 | + * @param xml | |
| 34 | + * 被解析的XMl | |
| 35 | + * @return Document | |
| 36 | + */ | |
| 37 | + public static Element parseXml(String xml) | |
| 38 | + { | |
| 39 | + Document document = null; | |
| 40 | + // | |
| 41 | + StringReader sr = new StringReader(xml); | |
| 42 | + SAXReader saxReader = new SAXReader(); | |
| 43 | + try | |
| 44 | + { | |
| 45 | + document = saxReader.read(sr); | |
| 46 | + } | |
| 47 | + catch (DocumentException e) | |
| 48 | + { | |
| 49 | + LOG.error("解析失败", e); | |
| 50 | + } | |
| 51 | + return null == document ? null : document.getRootElement(); | |
| 52 | + } | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 获取element对象的text的值 | |
| 56 | + * | |
| 57 | + * @param em | |
| 58 | + * 节点的对象 | |
| 59 | + * @param tag | |
| 60 | + * 节点的tag | |
| 61 | + * @return 节点 | |
| 62 | + */ | |
| 63 | + public static String getText(Element em, String tag) | |
| 64 | + { | |
| 65 | + if (null == em) | |
| 66 | + { | |
| 67 | + return null; | |
| 68 | + } | |
| 69 | + Element e = em.element(tag); | |
| 70 | + // | |
| 71 | + return null == e ? null : e.getText(); | |
| 72 | + } | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * 递归解析xml节点,适用于 多节点数据 | |
| 76 | + * | |
| 77 | + * @param node | |
| 78 | + * node | |
| 79 | + * @param nodeName | |
| 80 | + * nodeName | |
| 81 | + * @return List<Map<String, Object>> | |
| 82 | + */ | |
| 83 | + public static List<Map<String, Object>> listNodes(Element node, String nodeName) | |
| 84 | + { | |
| 85 | + if (null == node) | |
| 86 | + { | |
| 87 | + return null; | |
| 88 | + } | |
| 89 | + // 初始化返回 | |
| 90 | + List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>(); | |
| 91 | + // 首先获取当前节点的所有属性节点 | |
| 92 | + List<Attribute> list = node.attributes(); | |
| 93 | + | |
| 94 | + Map<String, Object> map = null; | |
| 95 | + // 遍历属性节点 | |
| 96 | + for (Attribute attribute : list) | |
| 97 | + { | |
| 98 | + if (nodeName.equals(node.getName())) | |
| 99 | + { | |
| 100 | + if (null == map) | |
| 101 | + { | |
| 102 | + map = new HashMap<String, Object>(); | |
| 103 | + listMap.add(map); | |
| 104 | + } | |
| 105 | + // 取到的节点属性放到map中 | |
| 106 | + map.put(attribute.getName(), attribute.getValue()); | |
| 107 | + } | |
| 108 | + | |
| 109 | + } | |
| 110 | + // 遍历当前节点下的所有节点 ,nodeName 要解析的节点名称 | |
| 111 | + // 使用递归 | |
| 112 | + Iterator<Element> iterator = node.elementIterator(); | |
| 113 | + while (iterator.hasNext()) | |
| 114 | + { | |
| 115 | + Element e = iterator.next(); | |
| 116 | + listMap.addAll(listNodes(e, nodeName)); | |
| 117 | + } | |
| 118 | + return listMap; | |
| 119 | + } | |
| 120 | + | |
| 121 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java | |
| 1 | +package com.genersoft.iot.vmp.storager; | |
| 2 | + | |
| 3 | +import java.util.List; | |
| 4 | + | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * @Description:视频设备数据存储接口 | |
| 9 | + * @author: songww | |
| 10 | + * @date: 2020年5月6日 下午2:14:31 | |
| 11 | + */ | |
| 12 | +public interface IVideoManagerStorager { | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 根据设备ID判断设备是否存在 | |
| 16 | + * | |
| 17 | + * @param deviceId 设备ID | |
| 18 | + * @return true:存在 false:不存在 | |
| 19 | + */ | |
| 20 | + public boolean exists(String deviceId); | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 视频设备创建 | |
| 24 | + * | |
| 25 | + * @param device 设备对象 | |
| 26 | + * @return true:创建成功 false:创建失败 | |
| 27 | + */ | |
| 28 | + public boolean create(Device device); | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 视频设备更新 | |
| 32 | + * | |
| 33 | + * @param device 设备对象 | |
| 34 | + * @return true:创建成功 false:创建失败 | |
| 35 | + */ | |
| 36 | + public boolean update(Device device); | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 获取设备 | |
| 40 | + * | |
| 41 | + * @param deviceId 设备ID | |
| 42 | + * @return DShadow 设备对象 | |
| 43 | + */ | |
| 44 | + public Device queryVideoDevice(String deviceId); | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * 获取多个设备 | |
| 48 | + * | |
| 49 | + * @param deviceIds 设备ID数组 | |
| 50 | + * @return List<Device> 设备对象数组 | |
| 51 | + */ | |
| 52 | + public List<Device> queryVideoDeviceList(String[] deviceIds); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 删除设备 | |
| 56 | + * | |
| 57 | + * @param deviceId 设备ID | |
| 58 | + * @return true:删除成功 false:删除失败 | |
| 59 | + */ | |
| 60 | + public boolean delete(String deviceId); | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 更新设备在线 | |
| 64 | + * | |
| 65 | + * @param deviceId 设备ID | |
| 66 | + * @return true:更新成功 false:更新失败 | |
| 67 | + */ | |
| 68 | + public boolean online(String deviceId); | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * 更新设备离线 | |
| 72 | + * | |
| 73 | + * @param deviceId 设备ID | |
| 74 | + * @return true:更新成功 false:更新失败 | |
| 75 | + */ | |
| 76 | + public boolean outline(String deviceId); | |
| 77 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/VideoManagerStoragerFactory.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/storager/VideoManagerStoragerFactory.java | |
| 1 | +package com.genersoft.iot.vmp.storager; | |
| 2 | + | |
| 3 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 4 | +import org.springframework.context.annotation.Bean; | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | + | |
| 7 | +import com.genersoft.iot.vmp.conf.VManagerConfig; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @Description:视频设备数据存储工厂,根据存储策略,返回对应的存储器 | |
| 11 | + * @author: songww | |
| 12 | + * @date: 2020年5月6日 下午2:15:16 | |
| 13 | + */ | |
| 14 | +@Component | |
| 15 | +public class VideoManagerStoragerFactory { | |
| 16 | + | |
| 17 | + @Autowired | |
| 18 | + private VManagerConfig vmConfig; | |
| 19 | + | |
| 20 | + @Autowired | |
| 21 | + private IVideoManagerStorager jdbcStorager; | |
| 22 | + | |
| 23 | + @Autowired | |
| 24 | + private IVideoManagerStorager redisStorager; | |
| 25 | + | |
| 26 | + @Bean("storager") | |
| 27 | + public IVideoManagerStorager getStorager() { | |
| 28 | + if ("redis".equals(vmConfig.getDatabase().toLowerCase())) { | |
| 29 | + return redisStorager; | |
| 30 | + } else if ("jdbc".equals(vmConfig.getDatabase().toLowerCase())) { | |
| 31 | + return jdbcStorager; | |
| 32 | + } | |
| 33 | + return redisStorager; | |
| 34 | + } | |
| 35 | + | |
| 36 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java | |
| 1 | +package com.genersoft.iot.vmp.storager.jdbc; | |
| 2 | + | |
| 3 | +import java.util.List; | |
| 4 | + | |
| 5 | +import org.springframework.stereotype.Component; | |
| 6 | +import org.springframework.stereotype.Service; | |
| 7 | + | |
| 8 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 10 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * @Description:视频设备数据存储-jdbc实现 | |
| 14 | + * @author: songww | |
| 15 | + * @date: 2020年5月6日 下午2:28:12 | |
| 16 | + */ | |
| 17 | +@Component("jdbcStorager") | |
| 18 | +public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager { | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 根据设备ID判断设备是否存在 | |
| 22 | + * | |
| 23 | + * @param deviceId 设备ID | |
| 24 | + * @return true:存在 false:不存在 | |
| 25 | + */ | |
| 26 | + @Override | |
| 27 | + public boolean exists(String deviceId) { | |
| 28 | + // TODO Auto-generated method stub | |
| 29 | + return false; | |
| 30 | + } | |
| 31 | + | |
| 32 | + /** | |
| 33 | + * 视频设备创建 | |
| 34 | + * | |
| 35 | + * @param device 设备对象 | |
| 36 | + * @return true:创建成功 false:创建失败 | |
| 37 | + */ | |
| 38 | + @Override | |
| 39 | + public boolean create(Device device) { | |
| 40 | + // TODO Auto-generated method stub | |
| 41 | + return false; | |
| 42 | + } | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * 视频设备更新 | |
| 46 | + * | |
| 47 | + * @param device 设备对象 | |
| 48 | + * @return true:更新成功 false:更新失败 | |
| 49 | + */ | |
| 50 | + @Override | |
| 51 | + public boolean update(Device device) { | |
| 52 | + // TODO Auto-generated method stub | |
| 53 | + return false; | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 获取设备 | |
| 58 | + * | |
| 59 | + * @param deviceId 设备ID | |
| 60 | + * @return Device 设备对象 | |
| 61 | + */ | |
| 62 | + @Override | |
| 63 | + public Device queryVideoDevice(String deviceId) { | |
| 64 | + // TODO Auto-generated method stub | |
| 65 | + return null; | |
| 66 | + } | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 获取多个设备 | |
| 70 | + * | |
| 71 | + * @param deviceIds 设备ID数组 | |
| 72 | + * @return List<Device> 设备对象数组 | |
| 73 | + */ | |
| 74 | + @Override | |
| 75 | + public List<Device> queryVideoDeviceList(String[] deviceIds) { | |
| 76 | + // TODO Auto-generated method stub | |
| 77 | + return null; | |
| 78 | + } | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 删除设备 | |
| 82 | + * | |
| 83 | + * @param deviceId 设备ID | |
| 84 | + * @return true:删除成功 false:删除失败 | |
| 85 | + */ | |
| 86 | + @Override | |
| 87 | + public boolean delete(String deviceId) { | |
| 88 | + // TODO Auto-generated method stub | |
| 89 | + return false; | |
| 90 | + } | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * 更新设备在线 | |
| 94 | + * | |
| 95 | + * @param deviceId 设备ID | |
| 96 | + * @return true:更新成功 false:更新失败 | |
| 97 | + */ | |
| 98 | + @Override | |
| 99 | + public boolean online(String deviceId) { | |
| 100 | + // TODO Auto-generated method stub | |
| 101 | + return false; | |
| 102 | + } | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * 更新设备离线 | |
| 106 | + * | |
| 107 | + * @param deviceId 设备ID | |
| 108 | + * @return true:更新成功 false:更新失败 | |
| 109 | + */ | |
| 110 | + @Override | |
| 111 | + public boolean outline(String deviceId) { | |
| 112 | + // TODO Auto-generated method stub | |
| 113 | + return false; | |
| 114 | + } | |
| 115 | + | |
| 116 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java | |
| 1 | +package com.genersoft.iot.vmp.storager.redis; | |
| 2 | + | |
| 3 | +import java.util.ArrayList; | |
| 4 | +import java.util.List; | |
| 5 | + | |
| 6 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 10 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 11 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 12 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * @Description:视频设备数据存储-redis实现 | |
| 16 | + * @author: songww | |
| 17 | + * @date: 2020年5月6日 下午2:31:42 | |
| 18 | + */ | |
| 19 | +@Component("redisStorager") | |
| 20 | +public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { | |
| 21 | + | |
| 22 | + @Autowired | |
| 23 | + private RedisUtil redis; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 根据设备ID判断设备是否存在 | |
| 27 | + * | |
| 28 | + * @param deviceId 设备ID | |
| 29 | + * @return true:存在 false:不存在 | |
| 30 | + */ | |
| 31 | + @Override | |
| 32 | + public boolean exists(String deviceId) { | |
| 33 | + return redis.hasKey(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); | |
| 34 | + } | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 视频设备创建 | |
| 38 | + * | |
| 39 | + * @param device 设备对象 | |
| 40 | + * @return true:创建成功 false:创建失败 | |
| 41 | + */ | |
| 42 | + @Override | |
| 43 | + public boolean create(Device device) { | |
| 44 | + return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device); | |
| 45 | + } | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 视频设备更新 | |
| 49 | + * | |
| 50 | + * @param device 设备对象 | |
| 51 | + * @return true:更新成功 false:更新失败 | |
| 52 | + */ | |
| 53 | + @Override | |
| 54 | + public boolean update(Device device) { | |
| 55 | + return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device); | |
| 56 | + } | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * 获取设备 | |
| 60 | + * | |
| 61 | + * @param deviceId 设备ID | |
| 62 | + * @return Device 设备对象 | |
| 63 | + */ | |
| 64 | + @Override | |
| 65 | + public Device queryVideoDevice(String deviceId) { | |
| 66 | + return (Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); | |
| 67 | + } | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * 获取多个设备 | |
| 71 | + * | |
| 72 | + * @param deviceIds 设备ID数组 | |
| 73 | + * @return List<Device> 设备对象数组 | |
| 74 | + */ | |
| 75 | + @Override | |
| 76 | + public List<Device> queryVideoDeviceList(String[] deviceIds) { | |
| 77 | + List<Device> devices = new ArrayList<>(); | |
| 78 | + if (deviceIds == null || deviceIds.length == 0) { | |
| 79 | + List<Object> deviceIdList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX+"*"); | |
| 80 | + for (int i = 0; i < deviceIdList.size(); i++) { | |
| 81 | + devices.add((Device)redis.get((String)deviceIdList.get(i))); | |
| 82 | + } | |
| 83 | + } else { | |
| 84 | + for (int i = 0; i < deviceIds.length; i++) { | |
| 85 | + devices.add((Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceIds[i])); | |
| 86 | + } | |
| 87 | + } | |
| 88 | + return devices; | |
| 89 | + } | |
| 90 | + | |
| 91 | + /** | |
| 92 | + * 删除设备 | |
| 93 | + * | |
| 94 | + * @param deviceId 设备ID | |
| 95 | + * @return true:删除成功 false:删除失败 | |
| 96 | + */ | |
| 97 | + @Override | |
| 98 | + public boolean delete(String deviceId) { | |
| 99 | + redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); | |
| 100 | + return true; | |
| 101 | + } | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * 更新设备在线 | |
| 105 | + * | |
| 106 | + * @param deviceId 设备ID | |
| 107 | + * @return true:更新成功 false:更新失败 | |
| 108 | + */ | |
| 109 | + @Override | |
| 110 | + public boolean online(String deviceId) { | |
| 111 | + Device device = (Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); | |
| 112 | + device.setOnline(1); | |
| 113 | + return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device); | |
| 114 | + } | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * 更新设备离线 | |
| 118 | + * | |
| 119 | + * @param deviceId 设备ID | |
| 120 | + * @return true:更新成功 false:更新失败 | |
| 121 | + */ | |
| 122 | + @Override | |
| 123 | + public boolean outline(String deviceId) { | |
| 124 | + Device device = (Device)redis.get(VideoManagerConstants.CACHEKEY_PREFIX+deviceId); | |
| 125 | + device.setOnline(0); | |
| 126 | + return redis.set(VideoManagerConstants.CACHEKEY_PREFIX+device.getDeviceId(), device); | |
| 127 | + } | |
| 128 | + | |
| 129 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/utils/redis/FastJsonRedisSerializer.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/utils/redis/FastJsonRedisSerializer.java | |
| 1 | +package com.genersoft.iot.vmp.utils.redis; | |
| 2 | + | |
| 3 | +import java.nio.charset.Charset; | |
| 4 | + | |
| 5 | +import org.springframework.data.redis.serializer.RedisSerializer; | |
| 6 | +import org.springframework.data.redis.serializer.SerializationException; | |
| 7 | + | |
| 8 | +import com.alibaba.fastjson.JSON; | |
| 9 | +import com.alibaba.fastjson.serializer.SerializerFeature; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @Description:使用fastjson实现redis的序列化 | |
| 13 | + * @author: songww | |
| 14 | + * @date: 2020年5月6日 下午8:40:11 | |
| 15 | + */ | |
| 16 | +public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { | |
| 17 | + | |
| 18 | + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); | |
| 19 | + | |
| 20 | + private Class<T> clazz; | |
| 21 | + | |
| 22 | + public FastJsonRedisSerializer(Class<T> clazz) { | |
| 23 | + super(); | |
| 24 | + this.clazz = clazz; | |
| 25 | + } | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public byte[] serialize(T t) throws SerializationException { | |
| 29 | + if (t == null) { | |
| 30 | + return new byte[0]; | |
| 31 | + } | |
| 32 | + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Override | |
| 36 | + public T deserialize(byte[] bytes) throws SerializationException { | |
| 37 | + if (bytes == null || bytes.length <= 0) { | |
| 38 | + return null; | |
| 39 | + } | |
| 40 | + String str = new String(bytes, DEFAULT_CHARSET); | |
| 41 | + return (T) JSON.parseObject(str, clazz); | |
| 42 | + } | |
| 43 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java | |
| 1 | +package com.genersoft.iot.vmp.utils.redis; | |
| 2 | + | |
| 3 | +import java.util.ArrayList; | |
| 4 | +import java.util.List; | |
| 5 | +import java.util.Map; | |
| 6 | +import java.util.Set; | |
| 7 | +import java.util.concurrent.TimeUnit; | |
| 8 | + | |
| 9 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 10 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 11 | +import org.springframework.stereotype.Component; | |
| 12 | +import org.springframework.util.CollectionUtils; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * @Description:Redis工具类 | |
| 16 | + * @author: songww | |
| 17 | + * @date: 2020年5月6日 下午8:27:29 | |
| 18 | + */ | |
| 19 | +@Component | |
| 20 | +public class RedisUtil { | |
| 21 | + | |
| 22 | + @Autowired | |
| 23 | + private RedisTemplate redisTemplate; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 指定缓存失效时间 | |
| 27 | + * @param key 键 | |
| 28 | + * @param time 时间(秒) | |
| 29 | + * @return true / false | |
| 30 | + */ | |
| 31 | + public boolean expire(String key, long time) { | |
| 32 | + try { | |
| 33 | + if (time > 0) { | |
| 34 | + redisTemplate.expire(key, time, TimeUnit.SECONDS); | |
| 35 | + } | |
| 36 | + return true; | |
| 37 | + } catch (Exception e) { | |
| 38 | + e.printStackTrace(); | |
| 39 | + return false; | |
| 40 | + } | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 根据 key 获取过期时间 | |
| 45 | + * @param key 键 | |
| 46 | + * @return | |
| 47 | + */ | |
| 48 | + public long getExpire(String key) { | |
| 49 | + return redisTemplate.getExpire(key, TimeUnit.SECONDS); | |
| 50 | + } | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * 判断 key 是否存在 | |
| 54 | + * @param key 键 | |
| 55 | + * @return true / false | |
| 56 | + */ | |
| 57 | + public boolean hasKey(String key) { | |
| 58 | + try { | |
| 59 | + return redisTemplate.hasKey(key); | |
| 60 | + } catch (Exception e) { | |
| 61 | + e.printStackTrace(); | |
| 62 | + return false; | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * 删除缓存 | |
| 68 | + * @SuppressWarnings("unchecked") 忽略类型转换警告 | |
| 69 | + * @param key 键(一个或者多个) | |
| 70 | + */ | |
| 71 | + public void del(String... key) { | |
| 72 | + if (key != null && key.length > 0) { | |
| 73 | + if (key.length == 1) { | |
| 74 | + redisTemplate.delete(key[0]); | |
| 75 | + } else { | |
| 76 | +// 传入一个 Collection<String> 集合 | |
| 77 | + redisTemplate.delete(CollectionUtils.arrayToList(key)); | |
| 78 | + } | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | +// ============================== String ============================== | |
| 83 | + | |
| 84 | + /** | |
| 85 | + * 普通缓存获取 | |
| 86 | + * @param key 键 | |
| 87 | + * @return 值 | |
| 88 | + */ | |
| 89 | + public Object get(String key) { | |
| 90 | + return key == null ? null : redisTemplate.opsForValue().get(key); | |
| 91 | + } | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * 普通缓存放入 | |
| 95 | + * @param key 键 | |
| 96 | + * @param value 值 | |
| 97 | + * @return true / false | |
| 98 | + */ | |
| 99 | + public boolean set(String key, Object value) { | |
| 100 | + try { | |
| 101 | + redisTemplate.opsForValue().set(key, value); | |
| 102 | + return true; | |
| 103 | + } catch (Exception e) { | |
| 104 | + e.printStackTrace(); | |
| 105 | + return false; | |
| 106 | + } | |
| 107 | + } | |
| 108 | + | |
| 109 | + /** | |
| 110 | + * 普通缓存放入并设置时间 | |
| 111 | + * @param key 键 | |
| 112 | + * @param value 值 | |
| 113 | + * @param time 时间(秒),如果 time < 0 则设置无限时间 | |
| 114 | + * @return true / false | |
| 115 | + */ | |
| 116 | + public boolean set(String key, Object value, long time) { | |
| 117 | + try { | |
| 118 | + if (time > 0) { | |
| 119 | + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); | |
| 120 | + } else { | |
| 121 | + set(key, value); | |
| 122 | + } | |
| 123 | + return true; | |
| 124 | + } catch (Exception e) { | |
| 125 | + e.printStackTrace(); | |
| 126 | + return false; | |
| 127 | + } | |
| 128 | + } | |
| 129 | + | |
| 130 | + /** | |
| 131 | + * 递增 | |
| 132 | + * @param key 键 | |
| 133 | + * @param delta 递增大小 | |
| 134 | + * @return | |
| 135 | + */ | |
| 136 | + public long incr(String key, long delta) { | |
| 137 | + if (delta < 0) { | |
| 138 | + throw new RuntimeException("递增因子必须大于 0"); | |
| 139 | + } | |
| 140 | + return redisTemplate.opsForValue().increment(key, delta); | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * 递减 | |
| 145 | + * @param key 键 | |
| 146 | + * @param delta 递减大小 | |
| 147 | + * @return | |
| 148 | + */ | |
| 149 | + public long decr(String key, long delta) { | |
| 150 | + if (delta < 0) { | |
| 151 | + throw new RuntimeException("递减因子必须大于 0"); | |
| 152 | + } | |
| 153 | + return redisTemplate.opsForValue().increment(key, delta); | |
| 154 | + } | |
| 155 | + | |
| 156 | +// ============================== Map ============================== | |
| 157 | + | |
| 158 | + /** | |
| 159 | + * HashGet | |
| 160 | + * @param key 键(no null) | |
| 161 | + * @param item 项(no null) | |
| 162 | + * @return 值 | |
| 163 | + */ | |
| 164 | + public Object hget(String key, String item) { | |
| 165 | + return redisTemplate.opsForHash().get(key, item); | |
| 166 | + } | |
| 167 | + | |
| 168 | + /** | |
| 169 | + * 获取 key 对应的 map | |
| 170 | + * @param key 键(no null) | |
| 171 | + * @return 对应的多个键值 | |
| 172 | + */ | |
| 173 | + public Map<Object, Object> hmget(String key) { | |
| 174 | + return redisTemplate.opsForHash().entries(key); | |
| 175 | + } | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * HashSet | |
| 179 | + * @param key 键 | |
| 180 | + * @param map 值 | |
| 181 | + * @return true / false | |
| 182 | + */ | |
| 183 | + public boolean hmset(String key, Map<Object, Object> map) { | |
| 184 | + try { | |
| 185 | + redisTemplate.opsForHash().putAll(key, map); | |
| 186 | + return true; | |
| 187 | + } catch (Exception e) { | |
| 188 | + e.printStackTrace(); | |
| 189 | + return false; | |
| 190 | + } | |
| 191 | + } | |
| 192 | + | |
| 193 | + /** | |
| 194 | + * HashSet 并设置时间 | |
| 195 | + * @param key 键 | |
| 196 | + * @param map 值 | |
| 197 | + * @param time 时间 | |
| 198 | + * @return true / false | |
| 199 | + */ | |
| 200 | + public boolean hmset(String key, Map<Object, Object> map, long time) { | |
| 201 | + try { | |
| 202 | + redisTemplate.opsForHash().putAll(key, map); | |
| 203 | + if (time > 0) { | |
| 204 | + expire(key, time); | |
| 205 | + } | |
| 206 | + return true; | |
| 207 | + } catch (Exception e) { | |
| 208 | + e.printStackTrace(); | |
| 209 | + return false; | |
| 210 | + } | |
| 211 | + } | |
| 212 | + | |
| 213 | + /** | |
| 214 | + * 向一张 Hash表 中放入数据,如不存在则创建 | |
| 215 | + * @param key 键 | |
| 216 | + * @param item 项 | |
| 217 | + * @param value 值 | |
| 218 | + * @return true / false | |
| 219 | + */ | |
| 220 | + public boolean hset(String key, String item, Object value) { | |
| 221 | + try { | |
| 222 | + redisTemplate.opsForHash().put(key, item, value); | |
| 223 | + return true; | |
| 224 | + } catch (Exception e) { | |
| 225 | + e.printStackTrace(); | |
| 226 | + return false; | |
| 227 | + } | |
| 228 | + } | |
| 229 | + | |
| 230 | + /** | |
| 231 | + * 向一张 Hash表 中放入数据,并设置时间,如不存在则创建 | |
| 232 | + * @param key 键 | |
| 233 | + * @param item 项 | |
| 234 | + * @param value 值 | |
| 235 | + * @param time 时间(如果原来的 Hash表 设置了时间,这里会覆盖) | |
| 236 | + * @return true / false | |
| 237 | + */ | |
| 238 | + public boolean hset(String key, String item, Object value, long time) { | |
| 239 | + try { | |
| 240 | + redisTemplate.opsForHash().put(key, item, value); | |
| 241 | + if (time > 0) { | |
| 242 | + expire(key, time); | |
| 243 | + } | |
| 244 | + return true; | |
| 245 | + } catch (Exception e) { | |
| 246 | + e.printStackTrace(); | |
| 247 | + return false; | |
| 248 | + } | |
| 249 | + } | |
| 250 | + | |
| 251 | + /** | |
| 252 | + * 删除 Hash表 中的值 | |
| 253 | + * @param key 键 | |
| 254 | + * @param item 项(可以多个,no null) | |
| 255 | + */ | |
| 256 | + public void hdel(String key, Object... item) { | |
| 257 | + redisTemplate.opsForHash().delete(key, item); | |
| 258 | + } | |
| 259 | + | |
| 260 | + /** | |
| 261 | + * 判断 Hash表 中是否有该键的值 | |
| 262 | + * @param key 键(no null) | |
| 263 | + * @param item 值(no null) | |
| 264 | + * @return true / false | |
| 265 | + */ | |
| 266 | + public boolean hHasKey(String key, String item) { | |
| 267 | + return redisTemplate.opsForHash().hasKey(key, item); | |
| 268 | + } | |
| 269 | + | |
| 270 | + /** | |
| 271 | + * Hash递增,如果不存在则创建一个,并把新增的值返回 | |
| 272 | + * @param key 键 | |
| 273 | + * @param item 项 | |
| 274 | + * @param by 递增大小 > 0 | |
| 275 | + * @return | |
| 276 | + */ | |
| 277 | + public Double hincr(String key, String item, Double by) { | |
| 278 | + return redisTemplate.opsForHash().increment(key, item, by); | |
| 279 | + } | |
| 280 | + | |
| 281 | + /** | |
| 282 | + * Hash递减 | |
| 283 | + * @param key 键 | |
| 284 | + * @param item 项 | |
| 285 | + * @param by 递减大小 | |
| 286 | + * @return | |
| 287 | + */ | |
| 288 | + public Double hdecr(String key, String item, Double by) { | |
| 289 | + return redisTemplate.opsForHash().increment(key, item, -by); | |
| 290 | + } | |
| 291 | + | |
| 292 | +// ============================== Set ============================== | |
| 293 | + | |
| 294 | + /** | |
| 295 | + * 根据 key 获取 set 中的所有值 | |
| 296 | + * @param key 键 | |
| 297 | + * @return 值 | |
| 298 | + */ | |
| 299 | + public Set<Object> sGet(String key) { | |
| 300 | + try { | |
| 301 | + return redisTemplate.opsForSet().members(key); | |
| 302 | + } catch (Exception e) { | |
| 303 | + e.printStackTrace(); | |
| 304 | + return null; | |
| 305 | + } | |
| 306 | + } | |
| 307 | + | |
| 308 | + /** | |
| 309 | + * 从键为 key 的 set 中,根据 value 查询是否存在 | |
| 310 | + * @param key 键 | |
| 311 | + * @param value 值 | |
| 312 | + * @return true / false | |
| 313 | + */ | |
| 314 | + public boolean sHasKey(String key, Object value) { | |
| 315 | + try { | |
| 316 | + return redisTemplate.opsForSet().isMember(key, value); | |
| 317 | + } catch (Exception e) { | |
| 318 | + e.printStackTrace(); | |
| 319 | + return false; | |
| 320 | + } | |
| 321 | + } | |
| 322 | + | |
| 323 | + /** | |
| 324 | + * 将数据放入 set缓存 | |
| 325 | + * @param key 键值 | |
| 326 | + * @param values 值(可以多个) | |
| 327 | + * @return 成功个数 | |
| 328 | + */ | |
| 329 | + public long sSet(String key, Object... values) { | |
| 330 | + try { | |
| 331 | + return redisTemplate.opsForSet().add(key, values); | |
| 332 | + } catch (Exception e) { | |
| 333 | + e.printStackTrace(); | |
| 334 | + return 0; | |
| 335 | + } | |
| 336 | + } | |
| 337 | + | |
| 338 | + /** | |
| 339 | + * 将数据放入 set缓存,并设置时间 | |
| 340 | + * @param key 键 | |
| 341 | + * @param time 时间 | |
| 342 | + * @param values 值(可以多个) | |
| 343 | + * @return 成功放入个数 | |
| 344 | + */ | |
| 345 | + public long sSet(String key, long time, Object... values) { | |
| 346 | + try { | |
| 347 | + long count = redisTemplate.opsForSet().add(key, values); | |
| 348 | + if (time > 0) { | |
| 349 | + expire(key, time); | |
| 350 | + } | |
| 351 | + return count; | |
| 352 | + } catch (Exception e) { | |
| 353 | + e.printStackTrace(); | |
| 354 | + return 0; | |
| 355 | + } | |
| 356 | + } | |
| 357 | + | |
| 358 | + /** | |
| 359 | + * 获取 set缓存的长度 | |
| 360 | + * @param key 键 | |
| 361 | + * @return 长度 | |
| 362 | + */ | |
| 363 | + public long sGetSetSize(String key) { | |
| 364 | + try { | |
| 365 | + return redisTemplate.opsForSet().size(key); | |
| 366 | + } catch (Exception e) { | |
| 367 | + e.printStackTrace(); | |
| 368 | + return 0; | |
| 369 | + } | |
| 370 | + } | |
| 371 | + | |
| 372 | + /** | |
| 373 | + * 移除 set缓存中,值为 value 的 | |
| 374 | + * @param key 键 | |
| 375 | + * @param values 值 | |
| 376 | + * @return 成功移除个数 | |
| 377 | + */ | |
| 378 | + public long setRemove(String key, Object... values) { | |
| 379 | + try { | |
| 380 | + return redisTemplate.opsForSet().remove(key, values); | |
| 381 | + } catch (Exception e) { | |
| 382 | + e.printStackTrace(); | |
| 383 | + return 0; | |
| 384 | + } | |
| 385 | + } | |
| 386 | + | |
| 387 | +// ============================== List ============================== | |
| 388 | + | |
| 389 | + /** | |
| 390 | + * 获取 list缓存的内容 | |
| 391 | + * @param key 键 | |
| 392 | + * @param start 开始 | |
| 393 | + * @param end 结束(0 到 -1 代表所有值) | |
| 394 | + * @return | |
| 395 | + */ | |
| 396 | + public List<Object> lGet(String key, long start, long end) { | |
| 397 | + try { | |
| 398 | + return redisTemplate.opsForList().range(key, start, end); | |
| 399 | + } catch (Exception e) { | |
| 400 | + e.printStackTrace(); | |
| 401 | + return null; | |
| 402 | + } | |
| 403 | + } | |
| 404 | + | |
| 405 | + /** | |
| 406 | + * 获取 list缓存的长度 | |
| 407 | + * @param key 键 | |
| 408 | + * @return 长度 | |
| 409 | + */ | |
| 410 | + public long lGetListSize(String key) { | |
| 411 | + try { | |
| 412 | + return redisTemplate.opsForList().size(key); | |
| 413 | + } catch (Exception e) { | |
| 414 | + e.printStackTrace(); | |
| 415 | + return 0; | |
| 416 | + } | |
| 417 | + } | |
| 418 | + | |
| 419 | + /** | |
| 420 | + * 根据索引 index 获取键为 key 的 list 中的元素 | |
| 421 | + * @param key 键 | |
| 422 | + * @param index 索引 | |
| 423 | + * 当 index >= 0 时 {0:表头, 1:第二个元素} | |
| 424 | + * 当 index < 0 时 {-1:表尾, -2:倒数第二个元素} | |
| 425 | + * @return 值 | |
| 426 | + */ | |
| 427 | + public Object lGetIndex(String key, long index) { | |
| 428 | + try { | |
| 429 | + return redisTemplate.opsForList().index(key, index); | |
| 430 | + } catch (Exception e) { | |
| 431 | + e.printStackTrace(); | |
| 432 | + return null; | |
| 433 | + } | |
| 434 | + } | |
| 435 | + | |
| 436 | + /** | |
| 437 | + * 将值 value 插入键为 key 的 list 中,如果 list 不存在则创建空 list | |
| 438 | + * @param key 键 | |
| 439 | + * @param value 值 | |
| 440 | + * @return true / false | |
| 441 | + */ | |
| 442 | + public boolean lSet(String key, Object value) { | |
| 443 | + try { | |
| 444 | + redisTemplate.opsForList().rightPush(key, value); | |
| 445 | + return true; | |
| 446 | + } catch (Exception e) { | |
| 447 | + e.printStackTrace(); | |
| 448 | + return false; | |
| 449 | + } | |
| 450 | + } | |
| 451 | + | |
| 452 | + /** | |
| 453 | + * 将值 value 插入键为 key 的 list 中,并设置时间 | |
| 454 | + * @param key 键 | |
| 455 | + * @param value 值 | |
| 456 | + * @param time 时间 | |
| 457 | + * @return true / false | |
| 458 | + */ | |
| 459 | + public boolean lSet(String key, Object value, long time) { | |
| 460 | + try { | |
| 461 | + redisTemplate.opsForList().rightPush(key, value); | |
| 462 | + if (time > 0) { | |
| 463 | + expire(key, time); | |
| 464 | + } | |
| 465 | + return true; | |
| 466 | + } catch (Exception e) { | |
| 467 | + e.printStackTrace(); | |
| 468 | + return false; | |
| 469 | + } | |
| 470 | + } | |
| 471 | + | |
| 472 | + /** | |
| 473 | + * 将 values 插入键为 key 的 list 中 | |
| 474 | + * @param key 键 | |
| 475 | + * @param values 值 | |
| 476 | + * @return true / false | |
| 477 | + */ | |
| 478 | + public boolean lSetList(String key, List<Object> values) { | |
| 479 | + try { | |
| 480 | + redisTemplate.opsForList().rightPushAll(key, values); | |
| 481 | + return true; | |
| 482 | + } catch (Exception e) { | |
| 483 | + e.printStackTrace(); | |
| 484 | + return false; | |
| 485 | + } | |
| 486 | + } | |
| 487 | + | |
| 488 | + /** | |
| 489 | + * 将 values 插入键为 key 的 list 中,并设置时间 | |
| 490 | + * @param key 键 | |
| 491 | + * @param values 值 | |
| 492 | + * @param time 时间 | |
| 493 | + * @return true / false | |
| 494 | + */ | |
| 495 | + public boolean lSetList(String key, List<Object> values, long time) { | |
| 496 | + try { | |
| 497 | + redisTemplate.opsForList().rightPushAll(key, values); | |
| 498 | + if (time > 0) { | |
| 499 | + expire(key, time); | |
| 500 | + } | |
| 501 | + return true; | |
| 502 | + } catch (Exception e) { | |
| 503 | + e.printStackTrace(); | |
| 504 | + return false; | |
| 505 | + } | |
| 506 | + } | |
| 507 | + | |
| 508 | + /** | |
| 509 | + * 根据索引 index 修改键为 key 的值 | |
| 510 | + * @param key 键 | |
| 511 | + * @param index 索引 | |
| 512 | + * @param value 值 | |
| 513 | + * @return true / false | |
| 514 | + */ | |
| 515 | + public boolean lUpdateIndex(String key, long index, Object value) { | |
| 516 | + try { | |
| 517 | + redisTemplate.opsForList().set(key, index, value); | |
| 518 | + return true; | |
| 519 | + } catch (Exception e) { | |
| 520 | + e.printStackTrace(); | |
| 521 | + return false; | |
| 522 | + } | |
| 523 | + } | |
| 524 | + | |
| 525 | + /** | |
| 526 | + * 在键为 key 的 list 中删除值为 value 的元素 | |
| 527 | + * @param key 键 | |
| 528 | + * @param count 如果 count == 0 则删除 list 中所有值为 value 的元素 | |
| 529 | + * 如果 count > 0 则删除 list 中最左边那个值为 value 的元素 | |
| 530 | + * 如果 count < 0 则删除 list 中最右边那个值为 value 的元素 | |
| 531 | + * @param value | |
| 532 | + * @return | |
| 533 | + */ | |
| 534 | + public long lRemove(String key, long count, Object value) { | |
| 535 | + try { | |
| 536 | + return redisTemplate.opsForList().remove(key, count, value); | |
| 537 | + } catch (Exception e) { | |
| 538 | + e.printStackTrace(); | |
| 539 | + return 0; | |
| 540 | + } | |
| 541 | + } | |
| 542 | + | |
| 543 | + /** | |
| 544 | + * 模糊查询 | |
| 545 | + * @param key 键 | |
| 546 | + * @return true / false | |
| 547 | + */ | |
| 548 | + public List<Object> keys(String key) { | |
| 549 | + try { | |
| 550 | + Set<String> set = redisTemplate.keys(key); | |
| 551 | + return new ArrayList<>(set); | |
| 552 | + } catch (Exception e) { | |
| 553 | + e.printStackTrace(); | |
| 554 | + return null; | |
| 555 | + } | |
| 556 | + } | |
| 557 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java | |
| 1 | +package com.genersoft.iot.vmp.vmanager.device; | |
| 2 | + | |
| 3 | +import java.util.ArrayList; | |
| 4 | +import java.util.List; | |
| 5 | + | |
| 6 | +import org.slf4j.Logger; | |
| 7 | +import org.slf4j.LoggerFactory; | |
| 8 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 9 | +import org.springframework.http.HttpStatus; | |
| 10 | +import org.springframework.http.ResponseEntity; | |
| 11 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 12 | +import org.springframework.web.bind.annotation.PathVariable; | |
| 13 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 14 | +import org.springframework.web.bind.annotation.RestController; | |
| 15 | + | |
| 16 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 17 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 18 | + | |
| 19 | +@RestController | |
| 20 | +@RequestMapping("/api") | |
| 21 | +public class DeviceController { | |
| 22 | + | |
| 23 | + private final static Logger logger = LoggerFactory.getLogger(DeviceController.class); | |
| 24 | + | |
| 25 | + @Autowired | |
| 26 | + private IVideoManagerStorager storager; | |
| 27 | + | |
| 28 | + @GetMapping("/devices/{deviceId}") | |
| 29 | + public ResponseEntity<List<Device>> devices(@PathVariable String deviceId){ | |
| 30 | + | |
| 31 | + if (logger.isDebugEnabled()) { | |
| 32 | + logger.debug("查询视频设备API调用,deviceId:" + deviceId); | |
| 33 | + } | |
| 34 | + | |
| 35 | + List<Device> deviceList = new ArrayList<>(); | |
| 36 | + deviceList.add(storager.queryVideoDevice(deviceId)); | |
| 37 | + return new ResponseEntity<>(deviceList,HttpStatus.OK); | |
| 38 | + } | |
| 39 | + | |
| 40 | + @GetMapping("/devices") | |
| 41 | + public ResponseEntity<List<Device>> devices(){ | |
| 42 | + | |
| 43 | + if (logger.isDebugEnabled()) { | |
| 44 | + logger.debug("查询所有视频设备API调用"); | |
| 45 | + } | |
| 46 | + | |
| 47 | + List<Device> deviceList = storager.queryVideoDeviceList(null); | |
| 48 | + return new ResponseEntity<>(deviceList,HttpStatus.OK); | |
| 49 | + } | |
| 50 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java | |
| 1 | +package com.genersoft.iot.vmp.vmanager.play; | |
| 2 | + | |
| 3 | +import org.slf4j.Logger; | |
| 4 | +import org.slf4j.LoggerFactory; | |
| 5 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 6 | +import org.springframework.http.HttpStatus; | |
| 7 | +import org.springframework.http.ResponseEntity; | |
| 8 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 9 | +import org.springframework.web.bind.annotation.PathVariable; | |
| 10 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 11 | +import org.springframework.web.bind.annotation.RestController; | |
| 12 | + | |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 14 | + | |
| 15 | +@RestController | |
| 16 | +@RequestMapping("/api") | |
| 17 | +public class PlayController { | |
| 18 | + | |
| 19 | + private final static Logger logger = LoggerFactory.getLogger(PlayController.class); | |
| 20 | + | |
| 21 | + @Autowired | |
| 22 | + private SIPCommander cmder; | |
| 23 | + | |
| 24 | + @GetMapping("/play/{deviceId}_{channelId}") | |
| 25 | + public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){ | |
| 26 | + | |
| 27 | + String ssrc = cmder.playStreamCmd(deviceId, channelId); | |
| 28 | + | |
| 29 | + if (logger.isDebugEnabled()) { | |
| 30 | + logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId)); | |
| 31 | + logger.debug("设备预览 API调用,ssrc:"+ssrc+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(ssrc))); | |
| 32 | + } | |
| 33 | + | |
| 34 | + if(ssrc!=null) { | |
| 35 | + return new ResponseEntity<String>(ssrc,HttpStatus.OK); | |
| 36 | + } else { | |
| 37 | + logger.warn("设备预览API调用失败!"); | |
| 38 | + return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); | |
| 39 | + } | |
| 40 | + } | |
| 41 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
0 → 100644
| 1 | +++ a/src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java | |
| 1 | +package com.genersoft.iot.vmp.vmanager.ptz; | |
| 2 | + | |
| 3 | +import org.slf4j.Logger; | |
| 4 | +import org.slf4j.LoggerFactory; | |
| 5 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 6 | +import org.springframework.http.HttpStatus; | |
| 7 | +import org.springframework.http.ResponseEntity; | |
| 8 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 9 | +import org.springframework.web.bind.annotation.PathVariable; | |
| 10 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 11 | +import org.springframework.web.bind.annotation.RestController; | |
| 12 | + | |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | |
| 14 | + | |
| 15 | +@RestController | |
| 16 | +@RequestMapping("/api") | |
| 17 | +public class PtzController { | |
| 18 | + | |
| 19 | + private final static Logger logger = LoggerFactory.getLogger(PtzController.class); | |
| 20 | + | |
| 21 | + @Autowired | |
| 22 | + private SIPCommander cmder; | |
| 23 | + | |
| 24 | + /*** | |
| 25 | + * http://localhost:8080/api/ptz/34020000001320000002_34020000001320000008?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=0 | |
| 26 | + * @param deviceId | |
| 27 | + * @param channelId | |
| 28 | + * @param leftRight | |
| 29 | + * @param upDown | |
| 30 | + * @param inOut | |
| 31 | + * @param moveSpeed | |
| 32 | + * @param zoomSpeed | |
| 33 | + * @return | |
| 34 | + */ | |
| 35 | + @GetMapping("/ptz/{deviceId}_{channelId}") | |
| 36 | + public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed){ | |
| 37 | + | |
| 38 | + if (logger.isDebugEnabled()) { | |
| 39 | + logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,leftRight:%d ,upDown:%d ,inOut:%d ,moveSpeed:%d ,zoomSpeed:%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed)); | |
| 40 | + } | |
| 41 | + | |
| 42 | + cmder.ptzCmd(deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed); | |
| 43 | + return new ResponseEntity<String>("success",HttpStatus.OK); | |
| 44 | + } | |
| 45 | +} | ... | ... |
src/main/resources/application.yml
0 → 100644
| 1 | +++ a/src/main/resources/application.yml | |
| 1 | +spring: | |
| 2 | + application: | |
| 3 | + name: wvp | |
| 4 | + # 数据存储方式,支持redis、jdbc | |
| 5 | + database: redis | |
| 6 | + redis: | |
| 7 | + # Redis服务器IP | |
| 8 | + host: 127.0.0.1 | |
| 9 | + #端口号 | |
| 10 | + port: 6379 | |
| 11 | + datebase: 0 | |
| 12 | + #访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 | |
| 13 | + password: | |
| 14 | + #超时时间 | |
| 15 | + timeout: 10000 | |
| 16 | + datasource: | |
| 17 | + name: wcp | |
| 18 | + url: jdbc:mysql://127.0.0.1:3306/wcp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true | |
| 19 | + username: root | |
| 20 | + password: 123456 | |
| 21 | + type: com.alibaba.druid.pool.DruidDataSource | |
| 22 | + driver-class-name: com.mysql.jdbc.Driver | |
| 23 | +server: | |
| 24 | + port: 8080 | |
| 25 | +sip: | |
| 26 | + # 本地服务地址 | |
| 27 | + ip: 192.168.0.3 | |
| 28 | + server_id: 34020000002000000001 | |
| 29 | + port: 5060 | |
| 30 | + domain: 34020000 | |
| 31 | + # 暂时使用统一密码,后续改为一机一密 | |
| 32 | + password: admin | |
| 33 | +media: | |
| 34 | + # ZLMediaServer IP | |
| 35 | + ip: 192.168.0.4 | |
| 36 | + port: 10000 | |
| 0 | 37 | \ No newline at end of file | ... | ... |