Merge remote-tracking branch 'origin/wvp-28181-2.0' into wvp-28181-2.0
This commit is contained in:
commit
0765874086
10
.github/ISSUE_TEMPLATE/-------.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/-------.md
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
name: "[ 新功能 ]"
|
||||||
|
about: 新功能
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
29
.github/ISSUE_TEMPLATE/--bug---.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/--bug---.md
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: "[ BUG ] "
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**描述错误**
|
||||||
|
描述下您遇到的问题
|
||||||
|
|
||||||
|
**如何复现**
|
||||||
|
有明确复现步骤的问题会很容易被解决
|
||||||
|
|
||||||
|
**预期行为**
|
||||||
|
清晰简洁的描述您期望发生的事情
|
||||||
|
|
||||||
|
**截图**
|
||||||
|
|
||||||
|
|
||||||
|
**环境信息:**
|
||||||
|
- 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/
|
||||||
|
- 2. 部署环境 windows / ubuntu/ centos ...
|
||||||
|
- 3. 端口开放情况
|
||||||
|
- 4. 是否是公网部署
|
||||||
|
- 5. 是否使用https
|
||||||
|
- 6. 方便的话提供下使用的设备品牌或平台
|
||||||
|
- 7. 你做过哪些尝试
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "be.teletask.onvif-java"]
|
[submodule "be.teletask.onvif-java"]
|
||||||
path = be.teletask.onvif-java
|
path = be.teletask.onvif-java
|
||||||
url = https://gitee.com/18010473990/be.teletask.onvif-java.git
|
url = https://gitee.com/pan648540858/be.teletask.onvif-java.git
|
||||||
|
20
README.md
20
README.md
@ -1,4 +1,4 @@
|
|||||||
![logo](https://gitee.com/18010473990/wvp-GB28181/raw/wvp-28181-2.0/web_src/static/logo.png)
|
![logo](https://gitee.com/pan648540858/wvp-GB28181-pro/raw/wvp-28181-2.0/web_src/static/logo.png)
|
||||||
# 开箱即用的的28181协议视频平台
|
# 开箱即用的的28181协议视频平台
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit)
|
[![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit)
|
||||||
@ -13,13 +13,7 @@ WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网
|
|||||||
流媒体服务基于ZLMediaKit-https://github.com/xiongziliang/ZLMediaKit
|
流媒体服务基于ZLMediaKit-https://github.com/xiongziliang/ZLMediaKit
|
||||||
|
|
||||||
前端页面基于MediaServerUI进行修改.
|
前端页面基于MediaServerUI进行修改.
|
||||||
# 快速体验
|
|
||||||
```shell
|
|
||||||
docker pull 648540858/wvp_pro
|
|
||||||
|
|
||||||
docker run --env WVP_IP="你的IP" -it -p 18080:18080 -p 30000-30500:30000-30500/udp -p 30000-30500:30000-30500/tcp -p 80:80 -p 5060:5060 -p 5060:5060/udp 648540858/wvp_pro
|
|
||||||
```
|
|
||||||
docker使用详情查看:[https://hub.docker.com/r/648540858/wvp_pro](https://hub.docker.com/r/648540858/wvp_pro)
|
|
||||||
# 应用场景:
|
# 应用场景:
|
||||||
支持浏览器无插件播放摄像头视频。
|
支持浏览器无插件播放摄像头视频。
|
||||||
支持摄像机、平台、NVR等设备接入。
|
支持摄像机、平台、NVR等设备接入。
|
||||||
@ -34,7 +28,7 @@ docker使用详情查看:[https://hub.docker.com/r/648540858/wvp_pro](https://
|
|||||||
[https://github.com/648540858/wvp-GB28181-pro/wiki](https://github.com/648540858/wvp-GB28181-pro/wiki)
|
[https://github.com/648540858/wvp-GB28181-pro/wiki](https://github.com/648540858/wvp-GB28181-pro/wiki)
|
||||||
|
|
||||||
# gitee同步仓库
|
# gitee同步仓库
|
||||||
https://gitee.com/18010473990/wvp-GB28181.git
|
https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||||
|
|
||||||
# 截图
|
# 截图
|
||||||
![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_1.png)
|
![build_1.png](https://github.com/648540858/wiki/blob/master/images/Screenshot_1.png)
|
||||||
@ -106,20 +100,28 @@ https://gitee.com/18010473990/wvp-GB28181.git
|
|||||||
- [ ] 添加ONVIF探测局域网内的设备
|
- [ ] 添加ONVIF探测局域网内的设备
|
||||||
- [X] 添加RTMP视频
|
- [X] 添加RTMP视频
|
||||||
- [X] 云端录像(需要部署单独服务配合使用)
|
- [X] 云端录像(需要部署单独服务配合使用)
|
||||||
|
- [X] 多流媒体节点,自动选择负载最低的节点使用。
|
||||||
- [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。
|
- [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。
|
||||||
- [ ] 添加系统配置
|
- [ ] 添加系统配置
|
||||||
- [ ] 添加用户管理
|
- [ ] 添加用户管理
|
||||||
- [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
|
- [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
|
||||||
|
|
||||||
|
# docker快速体验
|
||||||
|
```shell
|
||||||
|
docker pull 648540858/wvp_pro
|
||||||
|
|
||||||
|
docker run --env WVP_IP="你的IP" -it -p 18080:18080 -p 30000-30500:30000-30500/udp -p 30000-30500:30000-30500/tcp -p 80:80 -p 5060:5060 -p 5060:5060/udp 648540858/wvp_pro
|
||||||
|
```
|
||||||
|
docker使用详情查看:[https://hub.docker.com/r/648540858/wvp_pro](https://hub.docker.com/r/648540858/wvp_pro)
|
||||||
|
|
||||||
# gitee同步仓库
|
# gitee同步仓库
|
||||||
https://gitee.com/18010473990/wvp-GB28181.git
|
https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||||
|
|
||||||
# 使用帮助
|
# 使用帮助
|
||||||
QQ群: 901799015, 690854210(ZLM大群)
|
QQ群: 901799015, 690854210(ZLM大群)
|
||||||
QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助,欢迎star和提交pr。
|
QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助,欢迎star和提交pr。
|
||||||
|
|
||||||
|
|
||||||
# 致谢
|
# 致谢
|
||||||
感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架
|
感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架
|
||||||
|
|
||||||
|
Binary file not shown.
11
pom.xml
11
pom.xml
@ -212,17 +212,6 @@
|
|||||||
<!-- <version>1.0.8</version>-->
|
<!-- <version>1.0.8</version>-->
|
||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- onvif协议栈 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>be.teletask</groupId>
|
|
||||||
<artifactId>onvif-java</artifactId>
|
|
||||||
<version>1.0.2</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/libs/onvif-java-1.0.2.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
@ -23,6 +23,7 @@ create table device
|
|||||||
updateTime varchar(50) not null,
|
updateTime varchar(50) not null,
|
||||||
port int not null,
|
port int not null,
|
||||||
expires int not null,
|
expires int not null,
|
||||||
|
subscribeCycleForCatalog int not null,
|
||||||
hostAddress varchar(50) not null,
|
hostAddress varchar(50) not null,
|
||||||
charset varchar(50) not null
|
charset varchar(50) not null
|
||||||
);
|
);
|
||||||
@ -207,6 +208,7 @@ create table stream_proxy
|
|||||||
enable_hls bit null,
|
enable_hls bit null,
|
||||||
enable_mp4 bit null,
|
enable_mp4 bit null,
|
||||||
enable bit not null,
|
enable bit not null,
|
||||||
|
enable_remove_none_reader bit not null,
|
||||||
createTime varchar(50) not null,
|
createTime varchar(50) not null,
|
||||||
primary key (app, stream)
|
primary key (app, stream)
|
||||||
);
|
);
|
||||||
|
@ -6,6 +6,7 @@ import org.springframework.boot.SpringApplication;
|
|||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import springfox.documentation.oas.annotations.EnableOpenApi;
|
import springfox.documentation.oas.annotations.EnableOpenApi;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public class StreamInfo {
|
|||||||
private String rtsps;
|
private String rtsps;
|
||||||
private String rtc;
|
private String rtc;
|
||||||
private String mediaServerId;
|
private String mediaServerId;
|
||||||
private JSONArray tracks;
|
private Object tracks;
|
||||||
|
|
||||||
public static class TransactionInfo{
|
public static class TransactionInfo{
|
||||||
public String callId;
|
public String callId;
|
||||||
@ -105,11 +105,11 @@ public class StreamInfo {
|
|||||||
this.rtsp = rtsp;
|
this.rtsp = rtsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONArray getTracks() {
|
public Object getTracks() {
|
||||||
return tracks;
|
return tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTracks(JSONArray tracks) {
|
public void setTracks(Object tracks) {
|
||||||
this.tracks = tracks;
|
this.tracks = tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
package com.genersoft.iot.vmp.common;
|
package com.genersoft.iot.vmp.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 定义常量
|
* @description: 定义常量
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年5月30日 下午3:04:04
|
* @date: 2019年5月30日 下午3:04:04
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class VideoManagerConstants {
|
public class VideoManagerConstants {
|
||||||
|
|
||||||
public static final String WVP_SERVER_PREFIX = "VMP_wvp_server";
|
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
|
||||||
|
|
||||||
|
public static final String WVP_SERVER_STREAM_PUSH_PREFIX = "VMP_SIGNALLING_STREAM_PUSH_";
|
||||||
|
|
||||||
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
|
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
|
||||||
|
|
||||||
@ -25,6 +27,7 @@ public class VideoManagerConstants {
|
|||||||
public static final String PLAYER_PREFIX = "VMP_PLAYER_";
|
public static final String PLAYER_PREFIX = "VMP_PLAYER_";
|
||||||
|
|
||||||
public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
|
public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
|
||||||
|
public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
|
||||||
|
|
||||||
public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_PLATFORM_KEEPLIVE_";
|
public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_PLATFORM_KEEPLIVE_";
|
||||||
|
|
||||||
@ -51,4 +54,7 @@ public class VideoManagerConstants {
|
|||||||
public static final String MEDIA_SSRC_USED_PREFIX = "VMP_media_used_ssrc_";
|
public static final String MEDIA_SSRC_USED_PREFIX = "VMP_media_used_ssrc_";
|
||||||
|
|
||||||
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_media_transaction_";
|
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_media_transaction_";
|
||||||
|
|
||||||
|
//************************** redis 消息*********************************
|
||||||
|
public static final String WVP_MSG_STREAM_PUSH_CHANGE_PREFIX = "WVP_MSG_STREAM_PUSH_CHANGE";
|
||||||
}
|
}
|
||||||
|
43
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
Normal file
43
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||||
|
import org.springframework.scheduling.support.CronTrigger;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态定时任务
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DynamicTask {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||||
|
|
||||||
|
private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
|
||||||
|
return new ThreadPoolTaskScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String startCron(String key, Runnable task, int cycleForCatalog) {
|
||||||
|
stopCron(key);
|
||||||
|
// scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
|
||||||
|
ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, cycleForCatalog * 1000L);
|
||||||
|
futureMap.put(key, future);
|
||||||
|
return "startCron";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopCron(String key) {
|
||||||
|
if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
|
||||||
|
futureMap.get(key).cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -163,9 +163,9 @@ public class ProxyServletConfig {
|
|||||||
* 异常处理
|
* 异常处理
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){
|
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResponse, Exception e){
|
||||||
try {
|
try {
|
||||||
super.handleRequestException(proxyRequest, proxyResonse, e);
|
super.handleRequestException(proxyRequest, proxyResponse, e);
|
||||||
} catch (ServletException servletException) {
|
} catch (ServletException servletException) {
|
||||||
logger.error("录像服务 代理失败: ", e);
|
logger.error("录像服务 代理失败: ", e);
|
||||||
} catch (IOException ioException) {
|
} catch (IOException ioException) {
|
||||||
|
@ -16,7 +16,7 @@ import redis.clients.jedis.JedisPool;
|
|||||||
import redis.clients.jedis.JedisPoolConfig;
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
* @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年5月30日 上午10:58:25
|
* @date: 2019年5月30日 上午10:58:25
|
||||||
*
|
*
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ -27,7 +25,7 @@ public class SipConfig {
|
|||||||
|
|
||||||
Integer ptzSpeed = 50;
|
Integer ptzSpeed = 50;
|
||||||
|
|
||||||
Integer keepaliveTimeOut = 180;
|
Integer keepaliveTimeOut = 255;
|
||||||
|
|
||||||
Integer registerTimeInterval = 60;
|
Integer registerTimeInterval = 60;
|
||||||
|
|
||||||
|
@ -32,5 +32,7 @@ public class SipDeviceRunner implements CommandLineRunner {
|
|||||||
for (String deviceId : onlineForAll) {
|
for (String deviceId : onlineForAll) {
|
||||||
storager.online(deviceId);
|
storager.online(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAsync(proxyTargetClass = true)
|
||||||
|
public class ThreadPoolTaskConfig {
|
||||||
|
|
||||||
|
public static final int cpuNum = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
|
||||||
|
* 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
|
||||||
|
* 当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心线程数(默认线程数)
|
||||||
|
*/
|
||||||
|
private static final int corePoolSize = cpuNum;
|
||||||
|
/**
|
||||||
|
* 最大线程数
|
||||||
|
*/
|
||||||
|
private static final int maxPoolSize = cpuNum*2;
|
||||||
|
/**
|
||||||
|
* 允许线程空闲时间(单位:默认为秒)
|
||||||
|
*/
|
||||||
|
private static final int keepAliveTime = 30;
|
||||||
|
/**
|
||||||
|
* 缓冲队列大小
|
||||||
|
*/
|
||||||
|
private static final int queueCapacity = 500;
|
||||||
|
/**
|
||||||
|
* 线程池名前缀
|
||||||
|
*/
|
||||||
|
private static final String threadNamePrefix = "wvp-sip-handle-";
|
||||||
|
|
||||||
|
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
|
||||||
|
public ThreadPoolTaskExecutor taskExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setCorePoolSize(corePoolSize);
|
||||||
|
executor.setMaxPoolSize(maxPoolSize);
|
||||||
|
executor.setQueueCapacity(queueCapacity);
|
||||||
|
executor.setKeepAliveSeconds(keepAliveTime);
|
||||||
|
executor.setThreadNamePrefix(threadNamePrefix);
|
||||||
|
|
||||||
|
// 线程池对拒绝任务的处理策略
|
||||||
|
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
// 初始化
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,8 @@ public class UserSetup {
|
|||||||
|
|
||||||
private Boolean logInDatebase = Boolean.TRUE;
|
private Boolean logInDatebase = Boolean.TRUE;
|
||||||
|
|
||||||
|
private String serverId = "000000";
|
||||||
|
|
||||||
private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
|
private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
|
||||||
|
|
||||||
public Boolean getSavePositionHistory() {
|
public Boolean getSavePositionHistory() {
|
||||||
@ -104,4 +106,12 @@ public class UserSetup {
|
|||||||
public void setLogInDatebase(Boolean logInDatebase) {
|
public void setLogInDatebase(Boolean logInDatebase) {
|
||||||
this.logInDatebase = logInDatebase;
|
this.logInDatebase = logInDatebase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerId(String serverId) {
|
||||||
|
this.serverId = serverId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: 获取数据库配置
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月6日 下午2:46:00
|
|
||||||
*/
|
|
||||||
@Configuration("vmConfig")
|
|
||||||
public class VManagerConfig {
|
|
||||||
|
|
||||||
@Value("${spring.application.database:redis}")
|
|
||||||
private String database;
|
|
||||||
|
|
||||||
|
|
||||||
public String getDatabase() {
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDatabase(String database) {
|
|
||||||
this.database = database;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,10 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -12,13 +15,22 @@ public class WVPTimerTask {
|
|||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MediaConfig mediaConfig;
|
private UserSetup userSetup;
|
||||||
|
|
||||||
@Scheduled(cron="0/2 * * * * ? ") //每3秒执行一次
|
@Value("${server.port}")
|
||||||
|
private int serverPort;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 2 * 1000) //每3秒执行一次
|
||||||
public void execute(){
|
public void execute(){
|
||||||
// redisCatchStorage.updateWVPInfo();
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("ip", sipConfig.getIp());
|
||||||
|
jsonObject.put("port", serverPort);
|
||||||
|
redisCatchStorage.updateWVPInfo(userSetup.getServerId(), jsonObject, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public class LoginFailureHandler implements AuthenticationFailureHandler {
|
|||||||
|
|
||||||
} else if (e instanceof BadCredentialsException) {
|
} else if (e instanceof BadCredentialsException) {
|
||||||
// 密码错误
|
// 密码错误
|
||||||
logger.info("[登录失败] - 用户[{}]密码错误", username);
|
logger.info("[登录失败] - 用户[{}]密码/SIP服务器ID 错误", username);
|
||||||
|
|
||||||
} else if (e instanceof CredentialsExpiredException) {
|
} else if (e instanceof CredentialsExpiredException) {
|
||||||
// 密码过期
|
// 密码过期
|
||||||
|
@ -1,18 +1,11 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181;
|
package com.genersoft.iot.vmp.gb28181;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.TooManyListenersException;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.header.CallIdHeader;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import gov.nist.javax.sip.SipProviderImpl;
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -20,14 +13,15 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import javax.sip.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
|
import java.util.Properties;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
import java.util.TooManyListenersException;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class SipLayer implements SipListener {
|
public class SipLayer{
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
|
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
|
||||||
|
|
||||||
@ -35,33 +29,14 @@ public class SipLayer implements SipListener {
|
|||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPProcessorFactory processorFactory;
|
private ISIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SipSubscribe sipSubscribe;
|
|
||||||
|
|
||||||
private SipStackImpl sipStack;
|
private SipStackImpl sipStack;
|
||||||
|
|
||||||
private SipFactory sipFactory;
|
private SipFactory sipFactory;
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息处理器线程池
|
|
||||||
*/
|
|
||||||
private ThreadPoolExecutor processThreadPool;
|
|
||||||
|
|
||||||
@Bean("initSipServer")
|
|
||||||
private ThreadPoolExecutor initSipServer() {
|
|
||||||
|
|
||||||
int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
|
|
||||||
LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
|
|
||||||
processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
|
|
||||||
0L,TimeUnit.MILLISECONDS,processQueue,
|
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy());
|
|
||||||
return processThreadPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean("sipFactory")
|
@Bean("sipFactory")
|
||||||
@DependsOn("initSipServer")
|
|
||||||
private SipFactory createSipFactory() {
|
private SipFactory createSipFactory() {
|
||||||
sipFactory = SipFactory.getInstance();
|
sipFactory = SipFactory.getInstance();
|
||||||
sipFactory.setPathName("gov.nist");
|
sipFactory.setPathName("gov.nist");
|
||||||
@ -69,7 +44,7 @@ public class SipLayer implements SipListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean("sipStack")
|
@Bean("sipStack")
|
||||||
@DependsOn({"initSipServer", "sipFactory"})
|
@DependsOn({"sipFactory"})
|
||||||
private SipStack createSipStack() throws PeerUnavailableException {
|
private SipStack createSipStack() throws PeerUnavailableException {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
|
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
|
||||||
@ -87,7 +62,7 @@ public class SipLayer implements SipListener {
|
|||||||
return sipStack;
|
return sipStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean("tcpSipProvider")
|
@Bean(name = "tcpSipProvider")
|
||||||
@DependsOn("sipStack")
|
@DependsOn("sipStack")
|
||||||
private SipProviderImpl startTcpListener() {
|
private SipProviderImpl startTcpListener() {
|
||||||
ListeningPoint tcpListeningPoint = null;
|
ListeningPoint tcpListeningPoint = null;
|
||||||
@ -95,7 +70,7 @@ public class SipLayer implements SipListener {
|
|||||||
try {
|
try {
|
||||||
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "TCP");
|
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "TCP");
|
||||||
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||||
tcpSipProvider.addSipListener(this);
|
tcpSipProvider.addSipListener(sipProcessorObserver);
|
||||||
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}");
|
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}");
|
||||||
} catch (TransportNotSupportedException e) {
|
} catch (TransportNotSupportedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -110,7 +85,7 @@ public class SipLayer implements SipListener {
|
|||||||
return tcpSipProvider;
|
return tcpSipProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean("udpSipProvider")
|
@Bean(name = "udpSipProvider")
|
||||||
@DependsOn("sipStack")
|
@DependsOn("sipStack")
|
||||||
private SipProviderImpl startUdpListener() {
|
private SipProviderImpl startUdpListener() {
|
||||||
ListeningPoint udpListeningPoint = null;
|
ListeningPoint udpListeningPoint = null;
|
||||||
@ -118,8 +93,7 @@ public class SipLayer implements SipListener {
|
|||||||
try {
|
try {
|
||||||
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
|
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
|
||||||
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||||
udpSipProvider.addSipListener(this);
|
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||||
// udpSipProvider.setAutomaticDialogSupportEnabled(false);
|
|
||||||
} catch (TransportNotSupportedException e) {
|
} catch (TransportNotSupportedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InvalidArgumentException e) {
|
} catch (InvalidArgumentException e) {
|
||||||
@ -134,123 +108,4 @@ public class SipLayer implements SipListener {
|
|||||||
return udpSipProvider;
|
return udpSipProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a
|
|
||||||
* new request arrives.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processRequest(RequestEvent evt) {
|
|
||||||
logger.debug(evt.getRequest().toString());
|
|
||||||
// 由于jainsip是单线程程序,为提高性能并发处理
|
|
||||||
processThreadPool.execute(() -> {
|
|
||||||
if (processorFactory != null) {
|
|
||||||
processorFactory.createRequestProcessor(evt).process();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processResponse(ResponseEvent evt) {
|
|
||||||
Response response = evt.getResponse();
|
|
||||||
logger.debug(evt.getResponse().toString());
|
|
||||||
int status = response.getStatusCode();
|
|
||||||
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
|
||||||
ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
|
||||||
try {
|
|
||||||
processor.process(evt, this, sipConfig);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
|
||||||
if (callIdHeader != null) {
|
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
|
|
||||||
if (subscribe != null) {
|
|
||||||
subscribe.response(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((status >= 100) && (status < 200)) {
|
|
||||||
// 增加其它无需回复的响应,如101、180等
|
|
||||||
} else {
|
|
||||||
logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
|
|
||||||
if (evt.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
|
||||||
if (callIdHeader != null) {
|
|
||||||
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
|
||||||
if (subscribe != null) {
|
|
||||||
subscribe.response(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processTimeout
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param timeoutEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processTimeout(TimeoutEvent timeoutEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processIOException
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param exceptionEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processIOException(IOExceptionEvent exceptionEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processTransactionTerminated
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param transactionTerminatedEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Title: processDialogTerminated
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Description:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param dialogTerminatedEvent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:注册逻辑处理,当设备注册后触发逻辑。
|
* @description:注册逻辑处理,当设备注册后触发逻辑。
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午9:41:46
|
* @date: 2020年5月8日 下午9:41:46
|
||||||
*/
|
*/
|
||||||
|
@ -109,6 +109,11 @@ public class Device {
|
|||||||
*/
|
*/
|
||||||
private String charset ;
|
private String charset ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目录订阅周期,0为不订阅
|
||||||
|
*/
|
||||||
|
private int subscribeCycleForCatalog ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getDeviceId() {
|
public String getDeviceId() {
|
||||||
@ -270,4 +275,12 @@ public class Device {
|
|||||||
public void setCharset(String charset) {
|
public void setCharset(String charset) {
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSubscribeCycleForCatalog() {
|
||||||
|
return subscribeCycleForCatalog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscribeCycleForCatalog(int subscribeCycleForCatalog) {
|
||||||
|
this.subscribeCycleForCatalog = subscribeCycleForCatalog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 移动位置bean
|
* @description: 移动位置bean
|
||||||
* @author: lawrencehj
|
* @author: lawrencehj
|
||||||
* @date: 2021年1月23日
|
* @date: 2021年1月23日
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@ package com.genersoft.iot.vmp.gb28181.bean;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备录像信息bean
|
* @description:设备录像信息bean
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午2:05:56
|
* @date: 2020年5月8日 下午2:05:56
|
||||||
*/
|
*/
|
||||||
@ -14,6 +14,10 @@ public class RecordInfo {
|
|||||||
|
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
|
|
||||||
|
private String channelId;
|
||||||
|
|
||||||
|
private String sn;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private int sumNum;
|
private int sumNum;
|
||||||
@ -52,4 +56,19 @@ public class RecordInfo {
|
|||||||
this.recordList = recordList;
|
this.recordList = recordList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getChannelId() {
|
||||||
|
return channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChannelId(String channelId) {
|
||||||
|
this.channelId = channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSn() {
|
||||||
|
return sn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSn(String sn) {
|
||||||
|
this.sn = sn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备录像bean
|
* @description:设备录像bean
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午2:06:54
|
* @date: 2020年5月8日 下午2:06:54
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备离在线状态检测器,用于检测设备状态
|
* @description:设备离在线状态检测器,用于检测设备状态
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月13日 下午2:40:29
|
* @date: 2020年5月13日 下午2:40:29
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
|
import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Event事件通知推送器,支持推送在线事件、离线事件
|
* @description:Event事件通知推送器,支持推送在线事件、离线事件
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:30:50
|
* @date: 2020年5月6日 上午11:30:50
|
||||||
*/
|
*/
|
||||||
|
@ -1,38 +1,127 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.event;
|
package com.genersoft.iot.vmp.gb28181.event;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
import javax.sip.*;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class SipSubscribe {
|
public class SipSubscribe {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class);
|
||||||
|
|
||||||
private Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>();
|
private Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
|
private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private Map<String, Date> timeSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
|
||||||
|
// @Scheduled(fixedRate= 100 * 60 * 60 )
|
||||||
|
@Scheduled(cron="0 0 * * * ?") //每小时执行一次, 每个整点
|
||||||
|
public void execute(){
|
||||||
|
logger.info("[定时任务] 清理过期的订阅信息");
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(new Date());
|
||||||
|
calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) - 1);
|
||||||
|
for (String key : timeSubscribes.keySet()) {
|
||||||
|
if (timeSubscribes.get(key).before(calendar.getTime())){
|
||||||
|
logger.info("[定时任务] 清理过期的订阅信息: {}", key);
|
||||||
|
errorSubscribes.remove(key);
|
||||||
|
okSubscribes.remove(key);
|
||||||
|
timeSubscribes.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface Event {
|
public interface Event {
|
||||||
void response(ResponseEvent event);
|
void response(EventResult eventResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EventResult<EventObject>{
|
||||||
|
public int statusCode;
|
||||||
|
public String type;
|
||||||
|
public String msg;
|
||||||
|
public String callId;
|
||||||
|
public Dialog dialog;
|
||||||
|
public EventObject event;
|
||||||
|
|
||||||
|
public EventResult() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventResult(EventObject event) {
|
||||||
|
this.event = event;
|
||||||
|
if (event instanceof ResponseEvent) {
|
||||||
|
ResponseEvent responseEvent = (ResponseEvent)event;
|
||||||
|
Response response = responseEvent.getResponse();
|
||||||
|
this.dialog = responseEvent.getDialog();
|
||||||
|
this.type = "response";
|
||||||
|
if (response != null) {
|
||||||
|
this.msg = response.getReasonPhrase();
|
||||||
|
this.statusCode = response.getStatusCode();
|
||||||
|
}
|
||||||
|
this.callId = ((CallIdHeader)response.getHeader(CallIdHeader.NAME)).getCallId();
|
||||||
|
|
||||||
|
}else if (event instanceof TimeoutEvent) {
|
||||||
|
TimeoutEvent timeoutEvent = (TimeoutEvent)event;
|
||||||
|
this.type = "timeout";
|
||||||
|
this.msg = "消息超时未回复";
|
||||||
|
this.statusCode = -1024;
|
||||||
|
this.callId = timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId();
|
||||||
|
this.dialog = timeoutEvent.getClientTransaction().getDialog();
|
||||||
|
}else if (event instanceof TransactionTerminatedEvent) {
|
||||||
|
TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event;
|
||||||
|
this.type = "transactionTerminated";
|
||||||
|
this.msg = "事务已结束";
|
||||||
|
this.statusCode = -1024;
|
||||||
|
this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId();
|
||||||
|
this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog();
|
||||||
|
}else if (event instanceof DialogTerminatedEvent) {
|
||||||
|
DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event;
|
||||||
|
this.type = "dialogTerminated";
|
||||||
|
this.msg = "会话已结束";
|
||||||
|
this.statusCode = -1024;
|
||||||
|
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
|
||||||
|
this.dialog = dialogTerminatedEvent.getDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addErrorSubscribe(String key, SipSubscribe.Event event) {
|
public void addErrorSubscribe(String key, SipSubscribe.Event event) {
|
||||||
errorSubscribes.put(key, event);
|
errorSubscribes.put(key, event);
|
||||||
|
timeSubscribes.put(key, new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOkSubscribe(String key, SipSubscribe.Event event) {
|
public void addOkSubscribe(String key, SipSubscribe.Event event) {
|
||||||
okSubscribes.put(key, event);
|
okSubscribes.put(key, event);
|
||||||
|
timeSubscribes.put(key, new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SipSubscribe.Event getErrorSubscribe(String key) {
|
public SipSubscribe.Event getErrorSubscribe(String key) {
|
||||||
return errorSubscribes.get(key);
|
return errorSubscribes.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeErrorSubscribe(String key) {
|
||||||
|
errorSubscribes.remove(key);
|
||||||
|
timeSubscribes.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
public SipSubscribe.Event getOkSubscribe(String key) {
|
public SipSubscribe.Event getOkSubscribe(String key) {
|
||||||
return okSubscribes.get(key);
|
return okSubscribes.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeOkSubscribe(String key) {
|
||||||
|
okSubscribes.remove(key);
|
||||||
|
timeSubscribes.remove(key);
|
||||||
|
}
|
||||||
public int getErrorSubscribesSize(){
|
public int getErrorSubscribesSize(){
|
||||||
return errorSubscribes.size();
|
return errorSubscribes.size();
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
* @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:35:46
|
* @date: 2020年5月6日 上午11:35:46
|
||||||
*/
|
*/
|
||||||
@ -39,10 +39,6 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa
|
|||||||
// 获取失效的key
|
// 获取失效的key
|
||||||
String expiredKey = message.toString();
|
String expiredKey = message.toString();
|
||||||
logger.debug(expiredKey);
|
logger.debug(expiredKey);
|
||||||
if(!expiredKey.startsWith(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX)){
|
|
||||||
logger.debug("收到redis过期监听,但开头不是"+VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX+",忽略");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线
|
// 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线
|
||||||
if (expiredKey.startsWith(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX)) {
|
if (expiredKey.startsWith(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX)) {
|
||||||
String platformGBId = expiredKey.substring(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX.length(),expiredKey.length());
|
String platformGBId = expiredKey.substring(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX.length(),expiredKey.length());
|
||||||
|
@ -12,7 +12,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
* @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:35:46
|
* @date: 2020年5月6日 上午11:35:46
|
||||||
*/
|
*/
|
||||||
|
@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.gb28181.event.offline;
|
|||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 离线事件类
|
* @description: 离线事件类
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:33:13
|
* @date: 2020年5月6日 上午11:33:13
|
||||||
*/
|
*/
|
||||||
|
@ -11,8 +11,8 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源:
|
* @description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源:
|
||||||
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
|
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor}
|
||||||
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}
|
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午1:51:23
|
* @date: 2020年5月6日 下午1:51:23
|
||||||
@ -54,5 +54,8 @@ public class OfflineEventListener implements ApplicationListener<OfflineEvent> {
|
|||||||
|
|
||||||
// 处理离线监听
|
// 处理离线监听
|
||||||
storager.outline(event.getDeviceId());
|
storager.outline(event.getDeviceId());
|
||||||
|
|
||||||
|
// TODO 离线取消订阅
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 在线事件类
|
* @description: 在线事件类
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午11:32:56
|
* @date: 2020年5月6日 上午11:32:56
|
||||||
*/
|
*/
|
||||||
|
@ -13,12 +13,11 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源:
|
* @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源:
|
||||||
* 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
|
* 1、设备主动注销,发送注销指令
|
||||||
* 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor}
|
* 2、设备未知原因离线,心跳超时
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 下午1:51:23
|
* @date: 2020年5月6日 下午1:51:23
|
||||||
*/
|
*/
|
||||||
@ -74,5 +73,8 @@ public class OnlineEventListener implements ApplicationListener<OnlineEvent> {
|
|||||||
device.setOnline(1);
|
device.setOnline(1);
|
||||||
// 处理上线监听
|
// 处理上线监听
|
||||||
storager.updateDevice(device);
|
storager.updateDevice(device);
|
||||||
|
|
||||||
|
// TODO 上线添加订阅
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import javax.sip.ResponseEvent;
|
|||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 平台心跳超时事件
|
* @description: 平台心跳超时事件
|
||||||
* @author: panll
|
* @author: panll
|
||||||
* @date: 2020年11月5日 10:00
|
* @date: 2020年11月5日 10:00
|
||||||
*/
|
*/
|
||||||
@ -66,6 +66,7 @@ public class PlatformKeepaliveExpireEventLister implements ApplicationListener<P
|
|||||||
storager.updateParentPlatformStatus(event.getPlatformGbID(), false);
|
storager.updateParentPlatformStatus(event.getPlatformGbID(), false);
|
||||||
publisher.platformNotRegisterEventPublish(event.getPlatformGbID());
|
publisher.platformNotRegisterEventPublish(event.getPlatformGbID());
|
||||||
parentPlatformCatch.setKeepAliveReply(0);
|
parentPlatformCatch.setKeepAliveReply(0);
|
||||||
|
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
||||||
}else {
|
}else {
|
||||||
// 再次发送心跳
|
// 再次发送心跳
|
||||||
String callId = sipCommanderForPlatform.keepalive(parentPlatform);
|
String callId = sipCommanderForPlatform.keepalive(parentPlatform);
|
||||||
@ -75,8 +76,8 @@ public class PlatformKeepaliveExpireEventLister implements ApplicationListener<P
|
|||||||
redisCatchStorage.updatePlatformKeepalive(parentPlatform);
|
redisCatchStorage.updatePlatformKeepalive(parentPlatform);
|
||||||
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
||||||
|
|
||||||
sipSubscribe.addOkSubscribe(callId, (ResponseEvent responseEvent) ->{
|
sipSubscribe.addOkSubscribe(callId, (SipSubscribe.EventResult eventResult) ->{
|
||||||
if (responseEvent.getResponse().getStatusCode() == Response.OK) {
|
if (eventResult.statusCode == Response.OK) {
|
||||||
// 收到心跳响应信息,
|
// 收到心跳响应信息,
|
||||||
parentPlatformCatch.setKeepAliveReply(0);
|
parentPlatformCatch.setKeepAliveReply(0);
|
||||||
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
||||||
|
@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 平台未注册事件,来源有二:
|
* @description: 平台未注册事件,来源有二:
|
||||||
* 1、平台新添加
|
* 1、平台新添加
|
||||||
* 2、平台心跳超时
|
* 2、平台心跳超时
|
||||||
* @author: panll
|
* @author: panll
|
||||||
@ -100,6 +100,6 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
|
|||||||
logger.info("再次向平台注册,平台国标ID:" + event.getPlatformGbID());
|
logger.info("再次向平台注册,平台国标ID:" + event.getPlatformGbID());
|
||||||
sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
|
sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
|
||||||
}
|
}
|
||||||
}, config.getRegisterTimeInterval(), config.getRegisterTimeInterval());//十五秒后再次发起注册
|
}, config.getRegisterTimeInterval()* 1000, config.getRegisterTimeInterval()* 1000);//十五秒后再次发起注册
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
* @description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月13日 下午4:03:02
|
* @date: 2020年5月13日 下午4:03:02
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit;
|
||||||
|
|
||||||
|
import javax.sip.SipListener;
|
||||||
|
|
||||||
|
public interface ISIPProcessorObserver extends SipListener {
|
||||||
|
}
|
@ -1,243 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit;
|
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
import javax.sip.SipProvider;
|
|
||||||
import javax.sip.header.CSeqHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
|
||||||
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.AckRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.ByeResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.CancelResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.InviteResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcessor;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: SIP信令处理分配
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:24:37
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class SIPProcessorFactory {
|
|
||||||
|
|
||||||
// private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SipConfig sipConfig;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RegisterLogicHandler handler;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EventPublisher publisher;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SIPCommander cmder;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SIPCommanderFroPlatform cmderFroPlatform;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IDeviceAlarmService deviceAlarmService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisUtil redis;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeferredResultHolder deferredResultHolder;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceOffLineDetector offLineDetector;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private InviteResponseProcessor inviteResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ByeResponseProcessor byeResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CancelResponseProcessor cancelResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@Lazy
|
|
||||||
private RegisterResponseProcessor registerResponseProcessor;
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private OtherResponseProcessor otherResponseProcessor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IPlayService playService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IMediaServerService mediaServerService;
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
|
||||||
private SipProvider tcpSipProvider;
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
|
||||||
private SipProvider udpSipProvider;
|
|
||||||
|
|
||||||
public ISIPRequestProcessor createRequestProcessor(RequestEvent evt) {
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
String method = request.getMethod();
|
|
||||||
// logger.info("接收到消息:"+request.getMethod());
|
|
||||||
// sipSubscribe.getSubscribe(evt.getServerTransaction().getBranchId()).response(evt);
|
|
||||||
if (Request.INVITE.equals(method)) {
|
|
||||||
InviteRequestProcessor processor = new InviteRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
|
|
||||||
processor.setCmder(cmder);
|
|
||||||
processor.setCmderFroPlatform(cmderFroPlatform);
|
|
||||||
processor.setPlayService(playService);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
|
||||||
processor.setMediaServerService(mediaServerService);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.REGISTER.equals(method)) {
|
|
||||||
RegisterRequestProcessor processor = new RegisterRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setHandler(handler);
|
|
||||||
processor.setPublisher(publisher);
|
|
||||||
processor.setSipConfig(sipConfig);
|
|
||||||
processor.setVideoManagerStorager(storager);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.SUBSCRIBE.equals(method)) {
|
|
||||||
SubscribeRequestProcessor processor = new SubscribeRequestProcessor();
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.ACK.equals(method)) {
|
|
||||||
AckRequestProcessor processor = new AckRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
|
||||||
processor.setMediaServerService(mediaServerService);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.BYE.equals(method)) {
|
|
||||||
ByeRequestProcessor processor = new ByeRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
|
||||||
processor.setSIPCommander(cmder);
|
|
||||||
processor.setMediaServerService(mediaServerService);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.CANCEL.equals(method)) {
|
|
||||||
CancelRequestProcessor processor = new CancelRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.MESSAGE.equals(method)) {
|
|
||||||
MessageRequestProcessor processor = new MessageRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setPublisher(publisher);
|
|
||||||
processor.setRedis(redis);
|
|
||||||
processor.setDeferredResultHolder(deferredResultHolder);
|
|
||||||
processor.setOffLineDetector(offLineDetector);
|
|
||||||
processor.setCmder(cmder);
|
|
||||||
processor.setCmderFroPlatform(cmderFroPlatform);
|
|
||||||
processor.setDeviceAlarmService(deviceAlarmService);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
return processor;
|
|
||||||
} else if (Request.NOTIFY.equalsIgnoreCase(method)) {
|
|
||||||
NotifyRequestProcessor processor = new NotifyRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
|
||||||
processor.setPublisher(publisher);
|
|
||||||
processor.setRedis(redis);
|
|
||||||
processor.setDeferredResultHolder(deferredResultHolder);
|
|
||||||
processor.setOffLineDetector(offLineDetector);
|
|
||||||
processor.setCmder(cmder);
|
|
||||||
processor.setStorager(storager);
|
|
||||||
processor.setRedisCatchStorage(redisCatchStorage);
|
|
||||||
return processor;
|
|
||||||
} else {
|
|
||||||
OtherRequestProcessor processor = new OtherRequestProcessor();
|
|
||||||
processor.setRequestEvent(evt);
|
|
||||||
return processor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) {
|
|
||||||
|
|
||||||
Response response = evt.getResponse();
|
|
||||||
CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
|
||||||
String method = cseqHeader.getMethod();
|
|
||||||
if(Request.INVITE.equals(method)){
|
|
||||||
return inviteResponseProcessor;
|
|
||||||
} else if (Request.BYE.equals(method)) {
|
|
||||||
return byeResponseProcessor;
|
|
||||||
} else if (Request.CANCEL.equals(method)) {
|
|
||||||
return cancelResponseProcessor;
|
|
||||||
}else if (Request.REGISTER.equals(method)) {
|
|
||||||
return registerResponseProcessor;
|
|
||||||
} else {
|
|
||||||
return otherResponseProcessor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SipProvider getTcpSipProvider() {
|
|
||||||
if (tcpSipProvider == null) {
|
|
||||||
tcpSipProvider = (SipProvider) SpringBeanFactory.getBean("tcpSipProvider");
|
|
||||||
}
|
|
||||||
return tcpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SipProvider getUdpSipProvider() {
|
|
||||||
if (udpSipProvider == null) {
|
|
||||||
udpSipProvider = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
|
|
||||||
}
|
|
||||||
return udpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,162 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.header.CSeqHeader;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: SIP信令处理类观察者
|
||||||
|
* @author: panlinlin
|
||||||
|
* @date: 2021年11月5日 下午15:32
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SIPProcessorObserver implements ISIPProcessorObserver {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class);
|
||||||
|
|
||||||
|
private static Map<String, ISIPRequestProcessor> requestProcessorMap = new ConcurrentHashMap<>();
|
||||||
|
private static Map<String, ISIPResponseProcessor> responseProcessorMap = new ConcurrentHashMap<>();
|
||||||
|
private static ITimeoutProcessor timeoutProcessor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
|
// @Autowired
|
||||||
|
// @Qualifier(value = "taskExecutor")
|
||||||
|
// private ThreadPoolTaskExecutor poolTaskExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 request订阅
|
||||||
|
* @param method 方法名
|
||||||
|
* @param processor 处理程序
|
||||||
|
*/
|
||||||
|
public void addRequestProcessor(String method, ISIPRequestProcessor processor) {
|
||||||
|
requestProcessorMap.put(method, processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 response订阅
|
||||||
|
* @param method 方法名
|
||||||
|
* @param processor 处理程序
|
||||||
|
*/
|
||||||
|
public void addResponseProcessor(String method, ISIPResponseProcessor processor) {
|
||||||
|
responseProcessorMap.put(method, processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 超时事件订阅
|
||||||
|
* @param processor 处理程序
|
||||||
|
*/
|
||||||
|
public void addTimeoutProcessor(ITimeoutProcessor processor) {
|
||||||
|
this.timeoutProcessor = processor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分发RequestEvent事件
|
||||||
|
* @param requestEvent RequestEvent事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Async
|
||||||
|
public void processRequest(RequestEvent requestEvent) {
|
||||||
|
String method = requestEvent.getRequest().getMethod();
|
||||||
|
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
|
||||||
|
if (sipRequestProcessor == null) {
|
||||||
|
logger.warn("不支持方法{}的request", method);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
requestProcessorMap.get(method).process(requestEvent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分发ResponseEvent事件
|
||||||
|
* @param responseEvent responseEvent事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Async
|
||||||
|
public void processResponse(ResponseEvent responseEvent) {
|
||||||
|
logger.debug(responseEvent.getResponse().toString());
|
||||||
|
Response response = responseEvent.getResponse();
|
||||||
|
logger.debug(responseEvent.getResponse().toString());
|
||||||
|
int status = response.getStatusCode();
|
||||||
|
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
||||||
|
// ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
||||||
|
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
|
||||||
|
String method = cseqHeader.getMethod();
|
||||||
|
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method);
|
||||||
|
if (sipRequestProcessor != null) {
|
||||||
|
sipRequestProcessor.process(responseEvent);
|
||||||
|
}
|
||||||
|
if (responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
||||||
|
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
|
||||||
|
if (callIdHeader != null) {
|
||||||
|
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
|
||||||
|
if (subscribe != null) {
|
||||||
|
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
|
||||||
|
subscribe.response(eventResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((status >= 100) && (status < 200)) {
|
||||||
|
// 增加其它无需回复的响应,如101、180等
|
||||||
|
} else {
|
||||||
|
logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
|
||||||
|
if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
|
||||||
|
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
|
||||||
|
if (callIdHeader != null) {
|
||||||
|
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
||||||
|
if (subscribe != null) {
|
||||||
|
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
|
||||||
|
subscribe.response(eventResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (responseEvent.getDialog() != null) {
|
||||||
|
responseEvent.getDialog().delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向超时订阅发送消息
|
||||||
|
* @param timeoutEvent timeoutEvent事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void processTimeout(TimeoutEvent timeoutEvent) {
|
||||||
|
if(timeoutProcessor != null) {
|
||||||
|
timeoutProcessor.process(timeoutEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processIOException(IOExceptionEvent exceptionEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
|
||||||
|
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.RecordInfoResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor;
|
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class CheckForAllRecordsThread extends Thread {
|
public class CheckForAllRecordsThread extends Thread {
|
||||||
|
|
||||||
@ -54,13 +53,11 @@ public class CheckForAllRecordsThread extends Thread {
|
|||||||
// 自然顺序排序, 元素进行升序排列
|
// 自然顺序排序, 元素进行升序排列
|
||||||
this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
|
this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
String deviceId = recordInfo.getDeviceId();
|
msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn());
|
||||||
msg.setDeviceId(deviceId);
|
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
|
|
||||||
msg.setData(recordInfo);
|
msg.setData(recordInfo);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
logger.info("处理完成,返回结果");
|
logger.info("处理完成,返回结果");
|
||||||
MessageRequestProcessor.threadNameList.remove(cacheKey);
|
RecordInfoResponseMessageHandler.threadNameList.remove(cacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRedis(RedisUtil redis) {
|
public void setRedis(RedisUtil redis) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -9,7 +11,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 异步请求处理
|
* @description: 异步请求处理
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午7:59:05
|
* @date: 2020年5月8日 下午7:59:05
|
||||||
*/
|
*/
|
||||||
@ -31,12 +33,14 @@ public class DeferredResultHolder {
|
|||||||
|
|
||||||
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
|
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
|
||||||
|
|
||||||
public static final String CALLBACK_CMD_PlAY = "CALLBACK_PLAY";
|
public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
|
||||||
|
|
||||||
|
public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAY";
|
||||||
|
|
||||||
|
public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
|
||||||
|
|
||||||
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
|
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
|
||||||
|
|
||||||
public static final String CALLBACK_ONVIF = "CALLBACK_ONVIF";
|
|
||||||
|
|
||||||
public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
|
public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
|
||||||
|
|
||||||
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
|
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
|
||||||
@ -45,21 +49,72 @@ public class DeferredResultHolder {
|
|||||||
|
|
||||||
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
|
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
|
||||||
|
|
||||||
private Map<String, DeferredResult> map = new ConcurrentHashMap<String, DeferredResult>();
|
private Map<String, Map<String, DeferredResult>> map = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public void put(String key, DeferredResult result) {
|
|
||||||
map.put(key, result);
|
public void put(String key, String id, DeferredResult result) {
|
||||||
|
Map<String, DeferredResult> deferredResultMap = map.get(key);
|
||||||
|
if (deferredResultMap == null) {
|
||||||
|
deferredResultMap = new ConcurrentHashMap<>();
|
||||||
|
map.put(key, deferredResultMap);
|
||||||
|
}
|
||||||
|
deferredResultMap.put(id, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeferredResult get(String key) {
|
public DeferredResult get(String key, String id) {
|
||||||
return map.get(key);
|
Map<String, DeferredResult> deferredResultMap = map.get(key);
|
||||||
|
if (deferredResultMap == null) return null;
|
||||||
|
return deferredResultMap.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean exist(String key, String id){
|
||||||
|
if (key == null) return false;
|
||||||
|
Map<String, DeferredResult> deferredResultMap = map.get(key);
|
||||||
|
if (id == null) {
|
||||||
|
return deferredResultMap != null;
|
||||||
|
}else {
|
||||||
|
return deferredResultMap != null && deferredResultMap.get(id) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放单个请求
|
||||||
|
* @param msg
|
||||||
|
*/
|
||||||
public void invokeResult(RequestMessage msg) {
|
public void invokeResult(RequestMessage msg) {
|
||||||
DeferredResult result = map.get(msg.getId());
|
Map<String, DeferredResult> deferredResultMap = map.get(msg.getKey());
|
||||||
|
if (deferredResultMap == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DeferredResult result = deferredResultMap.get(msg.getId());
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
|
result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
|
||||||
|
deferredResultMap.remove(msg.getId());
|
||||||
|
if (deferredResultMap.size() == 0) {
|
||||||
|
map.remove(msg.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放所有的请求
|
||||||
|
* @param msg
|
||||||
|
*/
|
||||||
|
public void invokeAllResult(RequestMessage msg) {
|
||||||
|
Map<String, DeferredResult> deferredResultMap = map.get(msg.getKey());
|
||||||
|
if (deferredResultMap == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<String> ids = deferredResultMap.keySet();
|
||||||
|
for (String id : ids) {
|
||||||
|
DeferredResult result = deferredResultMap.get(id);
|
||||||
|
if (result == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.setResult(ResponseEntity.ok().body(msg.getData()));
|
||||||
|
}
|
||||||
|
map.remove(msg.getKey());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 请求信息定义
|
* @description: 请求信息定义
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月8日 下午1:09:18
|
* @date: 2020年5月8日 下午1:09:18
|
||||||
*/
|
*/
|
||||||
@ -9,9 +9,7 @@ public class RequestMessage {
|
|||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private String deviceId;
|
private String key;
|
||||||
|
|
||||||
private String type;
|
|
||||||
|
|
||||||
private Object data;
|
private Object data;
|
||||||
|
|
||||||
@ -23,22 +21,12 @@ public class RequestMessage {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDeviceId() {
|
public void setKey(String key) {
|
||||||
return deviceId;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeviceId(String deviceId) {
|
public String getKey() {
|
||||||
this.deviceId = deviceId;
|
return key;
|
||||||
this.id = type + deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
this.id = type + deviceId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getData() {
|
public Object getData() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
@ -7,7 +8,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
|||||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午9:16:34
|
* @date: 2020年5月3日 下午9:16:34
|
||||||
*/
|
*/
|
||||||
@ -121,6 +122,26 @@ public interface ISIPCommander {
|
|||||||
void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
|
void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
|
||||||
void streamByeCmd(String deviceId, String channelId);
|
void streamByeCmd(String deviceId, String channelId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放暂停
|
||||||
|
*/
|
||||||
|
void playPauseCmd(Device device, StreamInfo streamInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放恢复
|
||||||
|
*/
|
||||||
|
void playResumeCmd(Device device, StreamInfo streamInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放拖动播放
|
||||||
|
*/
|
||||||
|
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放倍速播放
|
||||||
|
*/
|
||||||
|
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 语音广播
|
* 语音广播
|
||||||
*
|
*
|
||||||
@ -235,8 +256,9 @@ public interface ISIPCommander {
|
|||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
|
* @param sn
|
||||||
*/
|
*/
|
||||||
boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime);
|
boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询报警信息
|
* 查询报警信息
|
||||||
@ -299,4 +321,11 @@ public interface ISIPCommander {
|
|||||||
* @return true = 命令发送成功
|
* @return true = 命令发送成功
|
||||||
*/
|
*/
|
||||||
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅、取消订阅目录信息
|
||||||
|
* @param device 视频设备
|
||||||
|
* @return true = 命令发送成功
|
||||||
|
*/
|
||||||
|
boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 平台命令request创造器 TODO 冗余代码太多待优化
|
* @description: 平台命令request创造器 TODO 冗余代码太多待优化
|
||||||
* @author: panll
|
* @author: panll
|
||||||
* @date: 2020年5月6日 上午9:29:02
|
* @date: 2020年5月6日 上午9:29:02
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.sip.Dialog;
|
||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
import javax.sip.PeerUnavailableException;
|
import javax.sip.PeerUnavailableException;
|
||||||
import javax.sip.SipFactory;
|
import javax.sip.SipFactory;
|
||||||
@ -11,6 +12,9 @@ import javax.sip.address.SipURI;
|
|||||||
import javax.sip.header.*;
|
import javax.sip.header.*;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.session.InfoCseqCache;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -18,7 +22,7 @@ import com.genersoft.iot.vmp.conf.SipConfig;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:摄像头命令request创造器 TODO 冗余代码太多待优化
|
* @description:摄像头命令request创造器 TODO 冗余代码太多待优化
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月6日 上午9:29:02
|
* @date: 2020年5月6日 上午9:29:02
|
||||||
*/
|
*/
|
||||||
@ -31,6 +35,9 @@ public class SIPRequestHeaderProvider {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SipFactory sipFactory;
|
private SipFactory sipFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VideoStreamSessionManager streamSession;
|
||||||
|
|
||||||
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
// sipuri
|
// sipuri
|
||||||
@ -99,13 +106,13 @@ public class SIPRequestHeaderProvider {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
//请求行
|
//请求行
|
||||||
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||||
// via
|
// via
|
||||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag);
|
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||||
viaHeader.setRPort();
|
viaHeader.setRPort();
|
||||||
viaHeaders.add(viaHeader);
|
viaHeaders.add(viaHeader);
|
||||||
//from
|
//from
|
||||||
@ -113,7 +120,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
||||||
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||||
//to
|
//to
|
||||||
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,sipConfig.getDomain());
|
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId, sipConfig.getDomain());
|
||||||
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
|
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null);
|
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null);
|
||||||
|
|
||||||
@ -127,6 +134,9 @@ public class SIPRequestHeaderProvider {
|
|||||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
|
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
|
||||||
// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||||
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||||
|
// Subject
|
||||||
|
SubjectHeader subjectHeader = sipFactory.createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
|
||||||
|
request.addHeader(subjectHeader);
|
||||||
|
|
||||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
@ -207,4 +217,50 @@ public class SIPRequestHeaderProvider {
|
|||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Request createInfoRequest(Device device, StreamInfo streamInfo, String content)
|
||||||
|
throws PeerUnavailableException, ParseException, InvalidArgumentException {
|
||||||
|
Request request = null;
|
||||||
|
Dialog dialog = streamSession.getDialog(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||||
|
|
||||||
|
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
|
||||||
|
device.getHostAddress());
|
||||||
|
// via
|
||||||
|
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
|
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(),
|
||||||
|
device.getTransport(), null);
|
||||||
|
viaHeader.setRPort();
|
||||||
|
viaHeaders.add(viaHeader);
|
||||||
|
// from
|
||||||
|
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),
|
||||||
|
sipConfig.getDomain());
|
||||||
|
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
||||||
|
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, dialog.getLocalTag());
|
||||||
|
// to
|
||||||
|
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(streamInfo.getChannelId(),
|
||||||
|
sipConfig.getDomain());
|
||||||
|
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
|
||||||
|
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, dialog.getRemoteTag());
|
||||||
|
|
||||||
|
// callid
|
||||||
|
CallIdHeader callIdHeader = dialog.getCallId();
|
||||||
|
|
||||||
|
// Forwards
|
||||||
|
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
|
||||||
|
|
||||||
|
// ceq
|
||||||
|
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory()
|
||||||
|
.createCSeqHeader(InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()), Request.INFO);
|
||||||
|
|
||||||
|
request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,
|
||||||
|
fromHeader, toHeader, viaHeaders, maxForwards);
|
||||||
|
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
|
||||||
|
.createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort()));
|
||||||
|
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||||
|
|
||||||
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application",
|
||||||
|
"MANSRTSP");
|
||||||
|
request.setContent(content, contentTypeHeader);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.CallIdHeader;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||||
import com.genersoft.iot.vmp.media.zlm.*;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.session.InfoCseqCache;
|
||||||
import gov.nist.javax.sip.SipProviderImpl;
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
import gov.nist.javax.sip.message.SIPRequest;
|
||||||
@ -29,20 +28,20 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
import javax.sip.header.ViaHeader;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午9:22:48
|
* @date: 2020年5月3日 下午9:22:48
|
||||||
*/
|
*/
|
||||||
@ -55,12 +54,10 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Lazy
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="tcpSipProvider")
|
@Qualifier(value="tcpSipProvider")
|
||||||
private SipProviderImpl tcpSipProvider;
|
private SipProviderImpl tcpSipProvider;
|
||||||
|
|
||||||
@Lazy
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="udpSipProvider")
|
@Qualifier(value="udpSipProvider")
|
||||||
private SipProviderImpl udpSipProvider;
|
private SipProviderImpl udpSipProvider;
|
||||||
@ -89,11 +86,6 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
private SIPDialog dialog;
|
|
||||||
|
|
||||||
public SipConfig getSipConfig() {
|
|
||||||
return sipConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
||||||
@ -361,7 +353,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
//
|
//
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
content.append("o="+ sipConfig.getId()+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
||||||
content.append("s=Play\r\n");
|
content.append("s=Play\r\n");
|
||||||
content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
||||||
content.append("t=0 0\r\n");
|
content.append("t=0 0\r\n");
|
||||||
@ -427,8 +419,8 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
|
mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
|
||||||
errorEvent.response(e);
|
errorEvent.response(e);
|
||||||
}), e ->{
|
}), e ->{
|
||||||
streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(),e.getClientTransaction());
|
streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
|
||||||
streamSession.put(device.getDeviceId(), channelId , e.getDialog());
|
streamSession.put(device.getDeviceId(), channelId , e.dialog);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -468,7 +460,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+sipConfig.getId()+" 0 0 IN IP4 "+sipConfig.getIp()+"\r\n");
|
content.append("o="+sipConfig.getId()+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
|
||||||
content.append("s=Playback\r\n");
|
content.append("s=Playback\r\n");
|
||||||
content.append("u="+channelId+":0\r\n");
|
content.append("u="+channelId+":0\r\n");
|
||||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||||
@ -532,12 +524,12 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
||||||
: udpSipProvider.getNewCallId();
|
: udpSipProvider.getNewCallId();
|
||||||
|
|
||||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
|
||||||
|
|
||||||
transmitRequest(device, request, errorEvent, okEvent -> {
|
transmitRequest(device, request, errorEvent, okEvent -> {
|
||||||
Dialog dialog = okEvent.getClientTransaction().getDialog();
|
ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
|
||||||
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), okEvent.getClientTransaction());
|
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), responseEvent.getClientTransaction());
|
||||||
streamSession.put(device.getDeviceId(), channelId, dialog);
|
streamSession.put(device.getDeviceId(), channelId, okEvent.dialog);
|
||||||
});
|
});
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -575,7 +567,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+sipConfig.getId()+" 0 0 IN IP4 "+sipConfig.getIp()+"\r\n");
|
content.append("o="+sipConfig.getId()+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
|
||||||
content.append("s=Download\r\n");
|
content.append("s=Download\r\n");
|
||||||
content.append("u="+channelId+":0\r\n");
|
content.append("u="+channelId+":0\r\n");
|
||||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||||
@ -640,7 +632,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
||||||
: udpSipProvider.getNewCallId();
|
: udpSipProvider.getNewCallId();
|
||||||
|
|
||||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
|
||||||
|
|
||||||
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
||||||
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
|
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
|
||||||
@ -667,6 +659,10 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
||||||
if (transaction == null) {
|
if (transaction == null) {
|
||||||
logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
||||||
|
SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
|
||||||
|
if (okEvent != null) {
|
||||||
|
okEvent.response(eventResult);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
|
SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
|
||||||
@ -1200,14 +1196,15 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime) {
|
public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent) {
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
StringBuffer recordInfoXml = new StringBuffer(200);
|
StringBuffer recordInfoXml = new StringBuffer(200);
|
||||||
recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||||
recordInfoXml.append("<Query>\r\n");
|
recordInfoXml.append("<Query>\r\n");
|
||||||
recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
|
recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
|
||||||
recordInfoXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
|
||||||
recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||||
recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
|
recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
|
||||||
recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
|
recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
|
||||||
@ -1224,7 +1221,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
|
Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
|
||||||
"z9hG4bK-ViaRecordInfo-" + tm, "fromRec" + tm, null, callIdHeader);
|
"z9hG4bK-ViaRecordInfo-" + tm, "fromRec" + tm, null, callIdHeader);
|
||||||
|
|
||||||
transmitRequest(device, request);
|
transmitRequest(device, request, errorEvent);
|
||||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
@ -1486,6 +1483,33 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
|
||||||
|
try {
|
||||||
|
StringBuffer cmdXml = new StringBuffer(200);
|
||||||
|
cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
|
||||||
|
cmdXml.append("<Query>\r\n");
|
||||||
|
cmdXml.append("<CmdType>Catalog</CmdType>\r\n");
|
||||||
|
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||||
|
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||||
|
cmdXml.append("</Query>\r\n");
|
||||||
|
|
||||||
|
String tm = Long.toString(System.currentTimeMillis());
|
||||||
|
|
||||||
|
CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
|
||||||
|
: udpSipProvider.getNewCallId();
|
||||||
|
|
||||||
|
Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" , callIdHeader);
|
||||||
|
transmitRequest(device, request, errorEvent, okEvent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
||||||
return transmitRequest(device, request, null, null);
|
return transmitRequest(device, request, null, null);
|
||||||
@ -1506,14 +1530,127 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
|
CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
|
||||||
// 添加错误订阅
|
// 添加错误订阅
|
||||||
if (errorEvent != null) {
|
if (errorEvent != null) {
|
||||||
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), errorEvent);
|
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
|
||||||
|
errorEvent.response(eventResult);
|
||||||
|
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
// 添加订阅
|
// 添加订阅
|
||||||
if (okEvent != null) {
|
if (okEvent != null) {
|
||||||
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);
|
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult ->{
|
||||||
|
okEvent.response(eventResult);
|
||||||
|
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clientTransaction.sendRequest();
|
clientTransaction.sendRequest();
|
||||||
return clientTransaction;
|
return clientTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放暂停
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void playPauseCmd(Device device, StreamInfo streamInfo) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
StringBuffer content = new StringBuffer(200);
|
||||||
|
content.append("PAUSE RTSP/1.0\r\n");
|
||||||
|
content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
|
||||||
|
content.append("PauseTime: now\r\n");
|
||||||
|
Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
|
||||||
|
logger.info(request.toString());
|
||||||
|
ClientTransaction clientTransaction = null;
|
||||||
|
if ("TCP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = tcpSipProvider.getNewClientTransaction(request);
|
||||||
|
} else if ("UDP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = udpSipProvider.getNewClientTransaction(request);
|
||||||
|
}
|
||||||
|
if (clientTransaction != null) {
|
||||||
|
clientTransaction.sendRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放恢复
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void playResumeCmd(Device device, StreamInfo streamInfo) {
|
||||||
|
try {
|
||||||
|
StringBuffer content = new StringBuffer(200);
|
||||||
|
content.append("PLAY RTSP/1.0\r\n");
|
||||||
|
content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
|
||||||
|
content.append("Range: npt=now-\r\n");
|
||||||
|
Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
|
||||||
|
logger.info(request.toString());
|
||||||
|
ClientTransaction clientTransaction = null;
|
||||||
|
if ("TCP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = tcpSipProvider.getNewClientTransaction(request);
|
||||||
|
} else if ("UDP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = udpSipProvider.getNewClientTransaction(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientTransaction.sendRequest();
|
||||||
|
|
||||||
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放拖动播放
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) {
|
||||||
|
try {
|
||||||
|
StringBuffer content = new StringBuffer(200);
|
||||||
|
content.append("PLAY RTSP/1.0\r\n");
|
||||||
|
content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
|
||||||
|
content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
|
||||||
|
|
||||||
|
Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
|
||||||
|
logger.info(request.toString());
|
||||||
|
ClientTransaction clientTransaction = null;
|
||||||
|
if ("TCP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = tcpSipProvider.getNewClientTransaction(request);
|
||||||
|
} else if ("UDP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = udpSipProvider.getNewClientTransaction(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientTransaction.sendRequest();
|
||||||
|
|
||||||
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回放倍速播放
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) {
|
||||||
|
try {
|
||||||
|
StringBuffer content = new StringBuffer(200);
|
||||||
|
content.append("PLAY RTSP/1.0\r\n");
|
||||||
|
content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
|
||||||
|
content.append("Scale: " + String.format("%.1f",speed) + "\r\n");
|
||||||
|
Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
|
||||||
|
logger.info(request.toString());
|
||||||
|
ClientTransaction clientTransaction = null;
|
||||||
|
if ("TCP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = tcpSipProvider.getNewClientTransaction(request);
|
||||||
|
} else if ("UDP".equals(device.getTransport())) {
|
||||||
|
clientTransaction = udpSipProvider.getNewClientTransaction(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientTransaction.sendRequest();
|
||||||
|
|
||||||
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
|||||||
if (event != null) {
|
if (event != null) {
|
||||||
logger.info("向上级平台 [ {} ] 注册发上错误: {} ",
|
logger.info("向上级平台 [ {} ] 注册发上错误: {} ",
|
||||||
parentPlatform.getServerGBId(),
|
parentPlatform.getServerGBId(),
|
||||||
event.getResponse().getReasonPhrase());
|
event.msg);
|
||||||
}
|
}
|
||||||
if (errorEvent != null ) {
|
if (errorEvent != null ) {
|
||||||
errorEvent.response(event);
|
errorEvent.response(event);
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 对SIP事件进行处理,包括request, response, timeout, ioException, transactionTerminated,dialogTerminated
|
||||||
|
* @author: panlinlin
|
||||||
|
* @date: 2021年11月5日 15:47
|
||||||
|
*/
|
||||||
|
public interface ISIPRequestProcessor {
|
||||||
|
|
||||||
|
void process(RequestEvent event);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request;
|
||||||
|
|
||||||
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:处理接收IPCamera发来的SIP协议请求消息
|
||||||
|
* @author: songww
|
||||||
|
* @date: 2020年5月3日 下午4:42:22
|
||||||
|
*/
|
||||||
|
public abstract class SIPRequestProcessorAbstract {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(value="tcpSipProvider")
|
||||||
|
private SipProviderImpl tcpSipProvider;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(value="udpSipProvider")
|
||||||
|
private SipProviderImpl udpSipProvider;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,179 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request;
|
||||||
|
|
||||||
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
|
import gov.nist.javax.sip.message.SIPRequest;
|
||||||
|
import gov.nist.javax.sip.stack.SIPServerTransaction;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.dom4j.io.SAXReader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.address.Address;
|
||||||
|
import javax.sip.address.AddressFactory;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.ContentTypeHeader;
|
||||||
|
import javax.sip.header.HeaderFactory;
|
||||||
|
import javax.sip.header.ViaHeader;
|
||||||
|
import javax.sip.message.MessageFactory;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:处理接收IPCamera发来的SIP协议请求消息
|
||||||
|
* @author: songww
|
||||||
|
* @date: 2020年5月3日 下午4:42:22
|
||||||
|
*/
|
||||||
|
public abstract class SIPRequestProcessorParent {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(SIPRequestProcessorParent.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(value="tcpSipProvider")
|
||||||
|
private SipProviderImpl tcpSipProvider;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier(value="udpSipProvider")
|
||||||
|
private SipProviderImpl udpSipProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 RequestEvent 获取 ServerTransaction
|
||||||
|
* @param evt
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ServerTransaction getServerTransaction(RequestEvent evt) {
|
||||||
|
Request request = evt.getRequest();
|
||||||
|
ServerTransaction serverTransaction = evt.getServerTransaction();
|
||||||
|
// 判断TCP还是UDP
|
||||||
|
boolean isTcp = false;
|
||||||
|
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||||
|
String transport = reqViaHeader.getTransport();
|
||||||
|
if (transport.equals("TCP")) {
|
||||||
|
isTcp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverTransaction == null) {
|
||||||
|
try {
|
||||||
|
if (isTcp) {
|
||||||
|
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
|
||||||
|
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
||||||
|
if (serverTransaction == null) {
|
||||||
|
serverTransaction = tcpSipProvider.getNewServerTransaction(request);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
|
||||||
|
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
||||||
|
if (serverTransaction == null) {
|
||||||
|
serverTransaction = udpSipProvider.getNewServerTransaction(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (TransactionAlreadyExistsException e) {
|
||||||
|
logger.error(e.getMessage());
|
||||||
|
} catch (TransactionUnavailableException e) {
|
||||||
|
logger.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return serverTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressFactory getAddressFactory() {
|
||||||
|
try {
|
||||||
|
return SipFactory.getInstance().createAddressFactory();
|
||||||
|
} catch (PeerUnavailableException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeaderFactory getHeaderFactory() {
|
||||||
|
try {
|
||||||
|
return SipFactory.getInstance().createHeaderFactory();
|
||||||
|
} catch (PeerUnavailableException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageFactory getMessageFactory() {
|
||||||
|
try {
|
||||||
|
return SipFactory.getInstance().createMessageFactory();
|
||||||
|
} catch (PeerUnavailableException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 回复状态码
|
||||||
|
* 100 trying
|
||||||
|
* 200 OK
|
||||||
|
* 400
|
||||||
|
* 404
|
||||||
|
* @param evt
|
||||||
|
* @throws SipException
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException {
|
||||||
|
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
|
||||||
|
ServerTransaction serverTransaction = getServerTransaction(evt);
|
||||||
|
serverTransaction.sendResponse(response);
|
||||||
|
if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) {
|
||||||
|
|
||||||
|
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
|
||||||
|
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
|
||||||
|
response.setReasonPhrase(msg);
|
||||||
|
ServerTransaction serverTransaction = getServerTransaction(evt);
|
||||||
|
serverTransaction.sendResponse(response);
|
||||||
|
if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) {
|
||||||
|
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回复带sdp的200
|
||||||
|
* @param evt
|
||||||
|
* @param sdp
|
||||||
|
* @throws SipException
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
public void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
|
||||||
|
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
||||||
|
SipFactory sipFactory = SipFactory.getInstance();
|
||||||
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||||
|
response.setContent(sdp, contentTypeHeader);
|
||||||
|
|
||||||
|
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
|
||||||
|
|
||||||
|
Address concatAddress = sipFactory.createAddressFactory().createAddress(
|
||||||
|
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
|
||||||
|
));
|
||||||
|
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||||
|
getServerTransaction(evt).sendResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element getRootElement(RequestEvent evt) throws DocumentException {
|
||||||
|
return getRootElement(evt, "gb2312");
|
||||||
|
}
|
||||||
|
public Element getRootElement(RequestEvent evt, String charset) throws DocumentException {
|
||||||
|
if (charset == null) charset = "gb2312";
|
||||||
|
Request request = evt.getRequest();
|
||||||
|
SAXReader reader = new SAXReader();
|
||||||
|
reader.setEncoding(charset);
|
||||||
|
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
||||||
|
return xml.getRootElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,39 +1,58 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.HeaderAddress;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.Dialog;
|
||||||
|
import javax.sip.DialogState;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.header.HeaderAddress;
|
||||||
|
import javax.sip.header.ToHeader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:ACK请求处理器
|
* SIP命令类型: ACK请求
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:31:45
|
|
||||||
*/
|
*/
|
||||||
public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
@Component
|
||||||
|
public class AckRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class);
|
private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class);
|
||||||
|
private String method = "ACK";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 ACK请求
|
* 处理 ACK请求
|
||||||
*
|
*
|
||||||
@ -41,11 +60,9 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt) {
|
public void process(RequestEvent evt) {
|
||||||
//Request request = evt.getRequest();
|
|
||||||
Dialog dialog = evt.getDialog();
|
Dialog dialog = evt.getDialog();
|
||||||
if (dialog == null) return;
|
if (dialog == null) return;
|
||||||
//DialogState state = dialog.getState();
|
if (dialog.getState()== DialogState.CONFIRMED) {
|
||||||
if (/*request.getMecodewwthod().equals(Request.INVITE) &&*/ dialog.getState()== DialogState.CONFIRMED) {
|
|
||||||
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
||||||
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
||||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId);
|
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId);
|
||||||
@ -102,41 +119,5 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try {
|
|
||||||
// Request ackRequest = null;
|
|
||||||
// CSeq csReq = (CSeq) request.getHeader(CSeq.NAME);
|
|
||||||
// ackRequest = dialog.createAck(csReq.getSeqNumber());
|
|
||||||
// dialog.sendAck(ackRequest);
|
|
||||||
// logger.info("send ack to callee:" + ackRequest.toString());
|
|
||||||
// } catch (SipException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// } catch (InvalidArgumentException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
|
||||||
return zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
|
||||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMediaServerService getMediaServerService() {
|
|
||||||
return mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
|
||||||
this.mediaServerService = mediaServerService;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,17 +1,12 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.HeaderAddress;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
@ -19,30 +14,53 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.header.HeaderAddress;
|
||||||
|
import javax.sip.header.ToHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: BYE请求处理器
|
* SIP命令类型: BYE请求
|
||||||
* @author: lawrencehj
|
|
||||||
* @date: 2021年3月9日
|
|
||||||
*/
|
*/
|
||||||
public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
@Component
|
||||||
|
public class ByeRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(ByeRequestProcessor.class);
|
private final Logger logger = LoggerFactory.getLogger(ByeRequestProcessor.class);
|
||||||
|
private final String method = "BYE";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private ISIPCommander cmder;
|
private ISIPCommander cmder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理BYE请求
|
* 处理BYE请求
|
||||||
* @param evt
|
* @param evt
|
||||||
@ -50,7 +68,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt) {
|
public void process(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
Dialog dialog = evt.getDialog();
|
Dialog dialog = evt.getDialog();
|
||||||
if (dialog == null) return;
|
if (dialog == null) return;
|
||||||
if (dialog.getState().equals(DialogState.TERMINATED)) {
|
if (dialog.getState().equals(DialogState.TERMINATED)) {
|
||||||
@ -93,58 +111,4 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复200 OK
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
|
||||||
return zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
|
||||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISIPCommander getSIPCommander() {
|
|
||||||
return cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSIPCommander(ISIPCommander cmder) {
|
|
||||||
this.cmder = cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMediaServerService getMediaServerService() {
|
|
||||||
return mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
|
||||||
this.mediaServerService = mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IVideoManagerStorager getStorager() {
|
|
||||||
return storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SIP命令类型: CANCEL请求
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CancelRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
|
private String method = "CANCEL";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理CANCEL请求
|
||||||
|
*
|
||||||
|
* @param evt 事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void process(RequestEvent evt) {
|
||||||
|
// TODO 优先级99 Cancel Request消息实现,此消息一般为级联消息,上级给下级发送请求取消指令
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,62 +1,77 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import javax.sdp.*;
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.Address;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.*;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
import com.genersoft.iot.vmp.service.IPlayService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
||||||
import com.genersoft.iot.vmp.service.IPlayService;
|
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
import gov.nist.javax.sip.address.AddressImpl;
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
import gov.nist.javax.sip.address.SipUri;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sdp.*;
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.ServerTransaction;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import javax.sip.message.Response;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:处理INVITE请求
|
* SIP命令类型: INVITE请求
|
||||||
* @author: panll
|
|
||||||
* @date: 2021年1月14日
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
@Component
|
||||||
|
public class InviteRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
private final static Logger logger = LoggerFactory.getLogger(InviteRequestProcessor.class);
|
||||||
|
|
||||||
|
private String method = "INVITE";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private SIPCommanderFroPlatform cmderFroPlatform;
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private SIPCommander cmder;
|
private SIPCommander cmder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IPlayService playService;
|
private IPlayService playService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IMediaServerService mediaServerService;
|
||||||
|
|
||||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
@Autowired
|
||||||
return zlmrtpServerFactory;
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
}
|
|
||||||
|
|
||||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
@Override
|
||||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +119,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
String mediaServerId = gbStream.getMediaServerId();
|
String mediaServerId = gbStream.getMediaServerId();
|
||||||
mediaServerItem = mediaServerService.getOne(mediaServerId);
|
mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||||
if (mediaServerItem == null) {
|
if (mediaServerItem == null) {
|
||||||
logger.info("[ app={}, stream={} ]zlm找不到,返回410",gbStream.getApp(), gbStream.getStream());
|
logger.info("[ app={}, stream={} ]找不到zlm {},返回410",gbStream.getApp(), gbStream.getStream(), mediaServerId);
|
||||||
responseAck(evt, Response.GONE, "media server not found");
|
responseAck(evt, Response.GONE, "media server not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -123,12 +138,21 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// 解析sdp消息, 使用jainsip 自带的sdp解析方式
|
// 解析sdp消息, 使用jainsip 自带的sdp解析方式
|
||||||
String contentString = new String(request.getRawContent());
|
String contentString = new String(request.getRawContent());
|
||||||
|
|
||||||
// jainSip不支持y=字段, 移除移除以解析。
|
// jainSip不支持y=字段, 移除以解析。
|
||||||
int ssrcIndex = contentString.indexOf("y=");
|
int ssrcIndex = contentString.indexOf("y=");
|
||||||
|
// 检查是否有y字段
|
||||||
|
String ssrcDefault = "0000000000";
|
||||||
|
String ssrc;
|
||||||
|
SessionDescription sdp;
|
||||||
|
if (ssrcIndex >= 0) {
|
||||||
//ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
|
//ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
|
||||||
String ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
|
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
|
||||||
String substring = contentString.substring(0, contentString.indexOf("y="));
|
String substring = contentString.substring(0, contentString.indexOf("y="));
|
||||||
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
|
sdp = SdpFactory.getInstance().createSessionDescription(substring);
|
||||||
|
}else {
|
||||||
|
ssrc = ssrcDefault;
|
||||||
|
sdp = SdpFactory.getInstance().createSessionDescription(contentString);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取支持的格式
|
// 获取支持的格式
|
||||||
Vector mediaDescriptions = sdp.getMediaDescriptions(true);
|
Vector mediaDescriptions = sdp.getMediaDescriptions(true);
|
||||||
@ -212,7 +236,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
|
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
||||||
content.append("s=Play\r\n");
|
content.append("s=Play\r\n");
|
||||||
content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
||||||
content.append("t=0 0\r\n");
|
content.append("t=0 0\r\n");
|
||||||
@ -235,7 +259,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// 未知错误。直接转发设备点播的错误
|
// 未知错误。直接转发设备点播的错误
|
||||||
Response response = null;
|
Response response = null;
|
||||||
try {
|
try {
|
||||||
response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest());
|
response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
ServerTransaction serverTransaction = getServerTransaction(evt);
|
||||||
serverTransaction.sendResponse(response);
|
serverTransaction.sendResponse(response);
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
||||||
@ -269,7 +293,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// TODO 添加对tcp的支持
|
// TODO 添加对tcp的支持
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||||
content.append("s=Play\r\n");
|
content.append("s=Play\r\n");
|
||||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||||
content.append("t=0 0\r\n");
|
content.append("t=0 0\r\n");
|
||||||
@ -368,111 +392,4 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复状态码
|
|
||||||
* 100 trying
|
|
||||||
* 200 OK
|
|
||||||
* 400
|
|
||||||
* 404
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (statusCode >= 200) {
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
|
|
||||||
response.setReasonPhrase(msg);
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (statusCode >= 200) {
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回复带sdp的200
|
|
||||||
* @param evt
|
|
||||||
* @param sdp
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
SipFactory sipFactory = SipFactory.getInstance();
|
|
||||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
|
||||||
response.setContent(sdp, contentTypeHeader);
|
|
||||||
|
|
||||||
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
|
|
||||||
|
|
||||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(
|
|
||||||
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
|
|
||||||
));
|
|
||||||
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
|
||||||
getServerTransaction(evt).sendResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SIPCommanderFroPlatform getCmderFroPlatform() {
|
|
||||||
return cmderFroPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) {
|
|
||||||
this.cmderFroPlatform = cmderFroPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IVideoManagerStorager getStorager() {
|
|
||||||
return storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SIPCommander getCmder() {
|
|
||||||
return cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmder(SIPCommander cmder) {
|
|
||||||
this.cmder = cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPlayService getPlayService() {
|
|
||||||
return playService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlayService(IPlayService playService) {
|
|
||||||
this.playService = playService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMediaServerService getMediaServerService() {
|
|
||||||
return mediaServerService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
|
||||||
this.mediaServerService = mediaServerService;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,92 +1,71 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.Address;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.Header;
|
|
||||||
import javax.sip.header.HeaderAddress;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.VManageBootstrap;
|
import com.genersoft.iot.vmp.VManageBootstrap;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.utils.GpsUtil;
|
import com.genersoft.iot.vmp.utils.GpsUtil;
|
||||||
import com.genersoft.iot.vmp.utils.SipUtils;
|
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
||||||
|
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
import gov.nist.javax.sip.address.SipUri;
|
||||||
|
|
||||||
import org.dom4j.Document;
|
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
import org.dom4j.io.SAXReader;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.*;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.header.HeaderAddress;
|
||||||
|
import javax.sip.header.ToHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:MESSAGE请求处理器
|
* @description: MESSAGE请求分发处理器,
|
||||||
* @author: swwheihei
|
* @author: panlinlin
|
||||||
* @date: 2020年5月3日 下午5:32:41
|
* @date: 2021年11月8日 10:28
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings(value={"unchecked", "rawtypes"})
|
@SuppressWarnings(value={"unchecked", "rawtypes"})
|
||||||
public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
@Component
|
||||||
|
public class MessageRequestProcessor1 extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
public static volatile List<String> threadNameList = new ArrayList();
|
public static volatile List<String> threadNameList = new ArrayList();
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor1.class);
|
||||||
|
private static Map<String, ISIPRequestProcessor> messageHandlerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
|
||||||
|
|
||||||
private SIPCommander cmder;
|
|
||||||
|
|
||||||
private SIPCommanderFroPlatform cmderFroPlatform;
|
|
||||||
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
private EventPublisher publisher;
|
|
||||||
|
|
||||||
private RedisUtil redis;
|
|
||||||
|
|
||||||
private DeferredResultHolder deferredResultHolder;
|
|
||||||
|
|
||||||
private DeviceOffLineDetector offLineDetector;
|
|
||||||
|
|
||||||
private IDeviceAlarmService deviceAlarmService;
|
|
||||||
|
|
||||||
private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
|
private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
|
||||||
|
|
||||||
private static final String MESSAGE_KEEP_ALIVE = "Keepalive";
|
private static final String MESSAGE_KEEP_ALIVE = "Keepalive";
|
||||||
private static final String MESSAGE_CONFIG_DOWNLOAD = "ConfigDownload";
|
private static final String MESSAGE_CONFIG_DOWNLOAD = "ConfigDownload";
|
||||||
private static final String MESSAGE_CATALOG = "Catalog";
|
private static final String MESSAGE_CATALOG = "Catalog";
|
||||||
@ -99,8 +78,50 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl";
|
private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl";
|
||||||
private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig";
|
private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig";
|
||||||
private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
|
private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
|
||||||
// private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";
|
|
||||||
private static final String MESSAGE_PRESET_QUERY = "PresetQuery";
|
private static final String MESSAGE_PRESET_QUERY = "PresetQuery";
|
||||||
|
private String method = "MESSAGE1111";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetup userSetup;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommander cmder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtil redis;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeviceAlarmService deviceAlarmService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理MESSAGE请求
|
* 处理MESSAGE请求
|
||||||
@ -112,7 +133,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String cmd = XmlUtil.getText(rootElement, "CmdType");
|
String cmd = getText(rootElement, "CmdType");
|
||||||
|
|
||||||
if (MESSAGE_KEEP_ALIVE.equals(cmd)) {
|
if (MESSAGE_KEEP_ALIVE.equals(cmd)) {
|
||||||
logger.debug("接收到KeepAlive消息");
|
logger.debug("接收到KeepAlive消息");
|
||||||
@ -155,7 +176,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
processMessageBroadcast(evt);
|
processMessageBroadcast(evt);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("接收到消息:" + cmd);
|
logger.debug("接收到消息:" + cmd);
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
}
|
}
|
||||||
} catch (DocumentException | SipException |InvalidArgumentException | ParseException e) {
|
} catch (DocumentException | SipException |InvalidArgumentException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -173,32 +194,32 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
logger.warn("处理MobilePosition移动位置消息时未找到设备信息");
|
logger.warn("处理MobilePosition移动位置消息时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Element rootElement = getRootElement(evt, device.getCharset());
|
Element rootElement = getRootElement(evt, device.getCharset());
|
||||||
|
|
||||||
MobilePosition mobilePosition = new MobilePosition();
|
MobilePosition mobilePosition = new MobilePosition();
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
|
||||||
if (!StringUtils.isEmpty(device.getName())) {
|
if (!StringUtils.isEmpty(device.getName())) {
|
||||||
mobilePosition.setDeviceName(device.getName());
|
mobilePosition.setDeviceName(device.getName());
|
||||||
}
|
}
|
||||||
mobilePosition.setDeviceId(deviceId);
|
mobilePosition.setDeviceId(deviceId);
|
||||||
mobilePosition.setChannelId(XmlUtil.getText(rootElement, "DeviceID"));
|
mobilePosition.setChannelId(getText(rootElement, "DeviceID"));
|
||||||
mobilePosition.setTime(XmlUtil.getText(rootElement, "Time"));
|
mobilePosition.setTime(getText(rootElement, "Time"));
|
||||||
mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
|
||||||
mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
|
if (NumericUtil.isDouble(getText(rootElement, "Speed"))) {
|
||||||
mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed")));
|
mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed")));
|
||||||
} else {
|
} else {
|
||||||
mobilePosition.setSpeed(0.0);
|
mobilePosition.setSpeed(0.0);
|
||||||
}
|
}
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) {
|
if (NumericUtil.isDouble(getText(rootElement, "Direction"))) {
|
||||||
mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction")));
|
mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction")));
|
||||||
} else {
|
} else {
|
||||||
mobilePosition.setDirection(0.0);
|
mobilePosition.setDirection(0.0);
|
||||||
}
|
}
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) {
|
if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) {
|
||||||
mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude")));
|
mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude")));
|
||||||
} else {
|
} else {
|
||||||
mobilePosition.setAltitude(0.0);
|
mobilePosition.setAltitude(0.0);
|
||||||
}
|
}
|
||||||
@ -214,7 +235,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
}
|
}
|
||||||
storager.insertMobilePosition(mobilePosition);
|
storager.insertMobilePosition(mobilePosition);
|
||||||
//回复 200 OK
|
//回复 200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -227,21 +248,27 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageDeviceStatus(RequestEvent evt) {
|
private void processMessageDeviceStatus(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceStatus设备状态Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String name = rootElement.getName();
|
String name = rootElement.getName();
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
String deviceId = deviceIdElement.getText();
|
String channelId = deviceIdElement.getText();
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
|
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
|
||||||
logger.info("接收到DeviceStatus查询消息");
|
logger.info("接收到DeviceStatus查询消息");
|
||||||
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
|
String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
|
||||||
if (platformId == null) {
|
if (platformId == null) {
|
||||||
response404Ack(evt);
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
String sn = rootElement.element("SN").getText();
|
String sn = rootElement.element("SN").getText();
|
||||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
|
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
|
||||||
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
|
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
|
||||||
@ -251,17 +278,16 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// 检查设备是否存在, 不存在则不回复
|
// 检查设备是否存在, 不存在则不回复
|
||||||
if (storager.exists(deviceId)) {
|
if (storager.exists(deviceId)) {
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
XmlUtil.node2Json(rootElement, json);
|
XmlUtil.node2Json(rootElement, json);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId + channelId);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
|
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
@ -282,11 +308,18 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageDeviceControl(RequestEvent evt) {
|
private void processMessageDeviceControl(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceControl设备状态Message未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
//String result = XmlUtil.getText(rootElement, "Result");
|
//String result = getText(rootElement, "Result");
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (rootElement.getName().equals("Response")) {//} !StringUtils.isEmpty(result)) {
|
if (rootElement.getName().equals("Response")) {//} !StringUtils.isEmpty(result)) {
|
||||||
// 此处是对本平台发出DeviceControl指令的应答
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
@ -295,16 +328,16 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL);
|
msg.setKey(key);
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
} else {
|
} else {
|
||||||
// 此处是上级发出的DeviceControl指令
|
// 此处是上级发出的DeviceControl指令
|
||||||
String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
||||||
String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
||||||
// 远程启动功能
|
// 远程启动功能
|
||||||
if (!StringUtils.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) {
|
if (!StringUtils.isEmpty(getText(rootElement, "TeleBoot"))) {
|
||||||
if (deviceId.equals(targetGBId)) {
|
if (deviceId.equals(targetGBId)) {
|
||||||
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
|
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
|
||||||
logger.info("执行远程启动本平台命令");
|
logger.info("执行远程启动本平台命令");
|
||||||
@ -342,10 +375,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 云台/前端控制命令
|
// 云台/前端控制命令
|
||||||
if (!StringUtils.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
|
if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
|
||||||
String cmdString = XmlUtil.getText(rootElement,"PTZCmd");
|
String cmdString = getText(rootElement,"PTZCmd");
|
||||||
Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
|
Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
|
||||||
cmder.fronEndCmd(device, deviceId, cmdString);
|
cmder.fronEndCmd(deviceForPlatform, deviceId, cmdString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||||
@ -360,10 +393,18 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageDeviceConfig(RequestEvent evt) {
|
private void processMessageDeviceConfig(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceConfig设备状态Message消息时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (rootElement.getName().equals("Response")) {
|
if (rootElement.getName().equals("Response")) {
|
||||||
// 此处是对本平台发出DeviceControl指令的应答
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
@ -371,11 +412,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG);
|
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
} else {
|
} else {
|
||||||
// 此处是上级发出的DeviceConfig指令
|
// 此处是上级发出的DeviceConfig指令
|
||||||
}
|
}
|
||||||
@ -391,10 +432,19 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageConfigDownload(RequestEvent evt) {
|
private void processMessageConfigDownload(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理ConfigDownload设备状态Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + deviceId + channelId;
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (rootElement.getName().equals("Response")) {
|
if (rootElement.getName().equals("Response")) {
|
||||||
// 此处是对本平台发出DeviceControl指令的应答
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
@ -403,10 +453,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD);
|
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
} else {
|
} else {
|
||||||
// 此处是上级发出的DeviceConfig指令
|
// 此处是上级发出的DeviceConfig指令
|
||||||
}
|
}
|
||||||
@ -422,10 +471,19 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessagePresetQuery(RequestEvent evt) {
|
private void processMessagePresetQuery(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理PresetQuery预置位列表Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId + channelId;
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (rootElement.getName().equals("Response")) {// !StringUtils.isEmpty(result)) {
|
if (rootElement.getName().equals("Response")) {// !StringUtils.isEmpty(result)) {
|
||||||
// 此处是对本平台发出DeviceControl指令的应答
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
@ -434,10 +492,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY);
|
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
} else {
|
} else {
|
||||||
// 此处是上级发出的DeviceControl指令
|
// 此处是上级发出的DeviceControl指令
|
||||||
}
|
}
|
||||||
@ -453,51 +510,55 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageDeviceInfo(RequestEvent evt) {
|
private void processMessageDeviceInfo(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(deviceId);
|
||||||
|
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String requestName = rootElement.getName();
|
String requestName = rootElement.getName();
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
String deviceId = deviceIdElement.getTextTrim();
|
String channelId = deviceIdElement.getTextTrim();
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + deviceId + channelId;
|
||||||
if (device != null ) {
|
if (device != null ) {
|
||||||
rootElement = getRootElement(evt, device.getCharset());
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
}
|
}
|
||||||
if (requestName.equals("Query")) {
|
if (requestName.equals("Query")) {
|
||||||
logger.info("接收到DeviceInfo查询消息");
|
logger.info("接收到DeviceInfo查询消息");
|
||||||
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser();
|
if (parentPlatform == null) {
|
||||||
if (platformId == null) {
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
response404Ack(evt);
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
String sn = rootElement.element("SN").getText();
|
String sn = rootElement.element("SN").getText();
|
||||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
|
|
||||||
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
|
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug("接收到DeviceInfo应答消息");
|
logger.debug("接收到DeviceInfo应答消息");
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
device.setName(XmlUtil.getText(rootElement, "DeviceName"));
|
device.setName(getText(rootElement, "DeviceName"));
|
||||||
|
|
||||||
device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
|
device.setManufacturer(getText(rootElement, "Manufacturer"));
|
||||||
device.setModel(XmlUtil.getText(rootElement, "Model"));
|
device.setModel(getText(rootElement, "Model"));
|
||||||
device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
|
device.setFirmware(getText(rootElement, "Firmware"));
|
||||||
if (StringUtils.isEmpty(device.getStreamMode())) {
|
if (StringUtils.isEmpty(device.getStreamMode())) {
|
||||||
device.setStreamMode("UDP");
|
device.setStreamMode("UDP");
|
||||||
}
|
}
|
||||||
storager.updateDevice(device);
|
storager.updateDevice(device);
|
||||||
|
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO);
|
|
||||||
msg.setData(device);
|
msg.setData(device);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
}
|
}
|
||||||
@ -514,26 +575,28 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageCatalogList(RequestEvent evt) {
|
private void processMessageCatalogList(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(deviceId);
|
||||||
|
|
||||||
|
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String name = rootElement.getName();
|
String name = rootElement.getName();
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
String deviceId = deviceIdElement.getText();
|
String channelId = deviceIdElement.getText();
|
||||||
Element deviceListElement = rootElement.element("DeviceList");
|
Element deviceListElement = rootElement.element("DeviceList");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
|
||||||
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
|
||||||
SipUri uri = (SipUri) address.getURI();
|
|
||||||
String platformId = uri.getUser();
|
|
||||||
// if (deviceListElement == null) { // 存在DeviceList则为响应 catalog, 不存在DeviceList则为查询请求
|
|
||||||
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
|
if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
|
||||||
// TODO 后续将代码拆分
|
// TODO 后续将代码拆分
|
||||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
|
|
||||||
if (parentPlatform == null) {
|
if (parentPlatform == null) {
|
||||||
response404Ack(evt);
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
|
|
||||||
Element snElement = rootElement.element("SN");
|
Element snElement = rootElement.element("SN");
|
||||||
String sn = snElement.getText();
|
String sn = snElement.getText();
|
||||||
@ -562,7 +625,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
deviceChannel.setStatus(gbStream.isStatus()?1:0);
|
deviceChannel.setStatus(gbStream.isStatus()?1:0);
|
||||||
// deviceChannel.setParentId(parentPlatform.getDeviceGBId());
|
// deviceChannel.setParentId(parentPlatform.getDeviceGBId());
|
||||||
deviceChannel.setRegisterWay(1);
|
deviceChannel.setRegisterWay(1);
|
||||||
deviceChannel.setCivilCode(cmder.getSipConfig().getDomain());
|
deviceChannel.setCivilCode(config.getDomain());
|
||||||
deviceChannel.setModel("live");
|
deviceChannel.setModel("live");
|
||||||
deviceChannel.setOwner("wvp-pro");
|
deviceChannel.setOwner("wvp-pro");
|
||||||
// deviceChannel.setAddress("test");
|
// deviceChannel.setAddress("test");
|
||||||
@ -581,8 +644,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
|
logger.warn("收到catalog设备目录列表请求时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deviceListElement = getRootElement(evt, device.getCharset()).element("DeviceList");
|
deviceListElement = getRootElement(evt, device.getCharset()).element("DeviceList");
|
||||||
@ -612,74 +676,73 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
deviceChannel.setStatus(0);
|
deviceChannel.setStatus(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
|
deviceChannel.setManufacture(getText(itemDevice, "Manufacturer"));
|
||||||
deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
|
deviceChannel.setModel(getText(itemDevice, "Model"));
|
||||||
deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
|
deviceChannel.setOwner(getText(itemDevice, "Owner"));
|
||||||
deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
|
deviceChannel.setCivilCode(getText(itemDevice, "CivilCode"));
|
||||||
deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
|
deviceChannel.setBlock(getText(itemDevice, "Block"));
|
||||||
deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
|
deviceChannel.setAddress(getText(itemDevice, "Address"));
|
||||||
if (XmlUtil.getText(itemDevice, "Parental") == null || XmlUtil.getText(itemDevice, "Parental") == "") {
|
if (getText(itemDevice, "Parental") == null || getText(itemDevice, "Parental") == "") {
|
||||||
deviceChannel.setParental(0);
|
deviceChannel.setParental(0);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
|
deviceChannel.setParental(Integer.parseInt(getText(itemDevice, "Parental")));
|
||||||
}
|
}
|
||||||
deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
|
deviceChannel.setParentId(getText(itemDevice, "ParentID"));
|
||||||
if (XmlUtil.getText(itemDevice, "SafetyWay") == null || XmlUtil.getText(itemDevice, "SafetyWay") == "") {
|
if (getText(itemDevice, "SafetyWay") == null || getText(itemDevice, "SafetyWay") == "") {
|
||||||
deviceChannel.setSafetyWay(0);
|
deviceChannel.setSafetyWay(0);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
|
deviceChannel.setSafetyWay(Integer.parseInt(getText(itemDevice, "SafetyWay")));
|
||||||
}
|
}
|
||||||
if (XmlUtil.getText(itemDevice, "RegisterWay") == null || XmlUtil.getText(itemDevice, "RegisterWay") == "") {
|
if (getText(itemDevice, "RegisterWay") == null || getText(itemDevice, "RegisterWay") == "") {
|
||||||
deviceChannel.setRegisterWay(1);
|
deviceChannel.setRegisterWay(1);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
|
deviceChannel.setRegisterWay(Integer.parseInt(getText(itemDevice, "RegisterWay")));
|
||||||
}
|
}
|
||||||
deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
|
deviceChannel.setCertNum(getText(itemDevice, "CertNum"));
|
||||||
if (XmlUtil.getText(itemDevice, "Certifiable") == null || XmlUtil.getText(itemDevice, "Certifiable") == "") {
|
if (getText(itemDevice, "Certifiable") == null || getText(itemDevice, "Certifiable") == "") {
|
||||||
deviceChannel.setCertifiable(0);
|
deviceChannel.setCertifiable(0);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
|
deviceChannel.setCertifiable(Integer.parseInt(getText(itemDevice, "Certifiable")));
|
||||||
}
|
}
|
||||||
if (XmlUtil.getText(itemDevice, "ErrCode") == null || XmlUtil.getText(itemDevice, "ErrCode") == "") {
|
if (getText(itemDevice, "ErrCode") == null || getText(itemDevice, "ErrCode") == "") {
|
||||||
deviceChannel.setErrCode(0);
|
deviceChannel.setErrCode(0);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
|
deviceChannel.setErrCode(Integer.parseInt(getText(itemDevice, "ErrCode")));
|
||||||
}
|
}
|
||||||
deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
|
deviceChannel.setEndTime(getText(itemDevice, "EndTime"));
|
||||||
deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
|
deviceChannel.setSecrecy(getText(itemDevice, "Secrecy"));
|
||||||
deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
|
deviceChannel.setIpAddress(getText(itemDevice, "IPAddress"));
|
||||||
if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") {
|
if (getText(itemDevice, "Port") == null || getText(itemDevice, "Port") == "") {
|
||||||
deviceChannel.setPort(0);
|
deviceChannel.setPort(0);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
|
deviceChannel.setPort(Integer.parseInt(getText(itemDevice, "Port")));
|
||||||
}
|
}
|
||||||
deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
|
deviceChannel.setPassword(getText(itemDevice, "Password"));
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {
|
if (NumericUtil.isDouble(getText(itemDevice, "Longitude"))) {
|
||||||
deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
|
deviceChannel.setLongitude(Double.parseDouble(getText(itemDevice, "Longitude")));
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setLongitude(0.00);
|
deviceChannel.setLongitude(0.00);
|
||||||
}
|
}
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
|
if (NumericUtil.isDouble(getText(itemDevice, "Latitude"))) {
|
||||||
deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
|
deviceChannel.setLatitude(Double.parseDouble(getText(itemDevice, "Latitude")));
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setLatitude(0.00);
|
deviceChannel.setLatitude(0.00);
|
||||||
}
|
}
|
||||||
if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") {
|
if (getText(itemDevice, "PTZType") == null || getText(itemDevice, "PTZType") == "") {
|
||||||
deviceChannel.setPTZType(0);
|
deviceChannel.setPTZType(0);
|
||||||
} else {
|
} else {
|
||||||
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
|
deviceChannel.setPTZType(Integer.parseInt(getText(itemDevice, "PTZType")));
|
||||||
}
|
}
|
||||||
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
||||||
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
|
|
||||||
msg.setData(device);
|
msg.setData(device);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
}
|
}
|
||||||
@ -701,13 +764,15 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
logger.warn("处理alarm设备报警信息未找到设备信息");
|
logger.warn("处理alarm设备报警信息未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Element rootElement = getRootElement(evt, device.getCharset());
|
Element rootElement = getRootElement(evt, device.getCharset());
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
String channelId = deviceIdElement.getText().toString();
|
String channelId = deviceIdElement.getText().toString();
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId + channelId;
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
|
|
||||||
if (device.getCharset() != null) {
|
if (device.getCharset() != null) {
|
||||||
rootElement = getRootElement(evt, device.getCharset());
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
@ -717,21 +782,21 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
DeviceAlarm deviceAlarm = new DeviceAlarm();
|
DeviceAlarm deviceAlarm = new DeviceAlarm();
|
||||||
deviceAlarm.setDeviceId(deviceId);
|
deviceAlarm.setDeviceId(deviceId);
|
||||||
deviceAlarm.setChannelId(channelId);
|
deviceAlarm.setChannelId(channelId);
|
||||||
deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
|
deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority"));
|
||||||
deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
|
deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod"));
|
||||||
deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime"));
|
deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime"));
|
||||||
if (XmlUtil.getText(rootElement, "AlarmDescription") == null) {
|
if (getText(rootElement, "AlarmDescription") == null) {
|
||||||
deviceAlarm.setAlarmDescription("");
|
deviceAlarm.setAlarmDescription("");
|
||||||
} else {
|
} else {
|
||||||
deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription"));
|
deviceAlarm.setAlarmDescription(getText(rootElement, "AlarmDescription"));
|
||||||
}
|
}
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) {
|
if (NumericUtil.isDouble(getText(rootElement, "Longitude"))) {
|
||||||
deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
|
deviceAlarm.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
|
||||||
} else {
|
} else {
|
||||||
deviceAlarm.setLongitude(0.00);
|
deviceAlarm.setLongitude(0.00);
|
||||||
}
|
}
|
||||||
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) {
|
if (NumericUtil.isDouble(getText(rootElement, "Latitude"))) {
|
||||||
deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
|
deviceAlarm.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
|
||||||
} else {
|
} else {
|
||||||
deviceAlarm.setLatitude(0.00);
|
deviceAlarm.setLatitude(0.00);
|
||||||
}
|
}
|
||||||
@ -756,7 +821,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
storager.insertMobilePosition(mobilePosition);
|
storager.insertMobilePosition(mobilePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("存储报警信息、报警分类");
|
logger.debug("存储报警信息、报警分类");
|
||||||
// 存储报警信息、报警分类
|
// 存储报警信息、报警分类
|
||||||
deviceAlarmService.add(deviceAlarm);
|
deviceAlarmService.add(deviceAlarm);
|
||||||
|
|
||||||
@ -770,10 +835,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_ALARM);
|
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
}
|
}
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -787,14 +851,18 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageKeepAlive(RequestEvent evt) {
|
private void processMessageKeepAlive(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
Element rootElement = getRootElement(evt);
|
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
|
||||||
|
Element rootElement = getRootElement(evt);
|
||||||
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
|
|
||||||
// 检查设备是否存在并在线, 不在线则设置为在线
|
// 检查设备是否存在并在线, 不在线则设置为在线
|
||||||
if (device != null ) {
|
if (device != null ) {
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||||
}else{
|
}else{
|
||||||
logger.warn("收到[ "+deviceId+" ]心跳信息, 但是设备不存在, 回复404");
|
logger.warn("收到[ "+deviceId+" ]心跳信息, 但是设备不存在, 回复404");
|
||||||
@ -831,33 +899,42 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageRecordInfo(RequestEvent evt) {
|
private void processMessageRecordInfo(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
String uuid = UUID.randomUUID().toString().replace("-", "");
|
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||||
RecordInfo recordInfo = new RecordInfo();
|
RecordInfo recordInfo = new RecordInfo();
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
String sn = getText(rootElement, "SN");
|
||||||
String deviceId = deviceIdElement.getText().toString();
|
String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
|
||||||
if (device != null ) {
|
if (device != null ) {
|
||||||
rootElement = getRootElement(evt, device.getCharset());
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
}
|
}
|
||||||
recordInfo.setDeviceId(deviceId);
|
recordInfo.setDeviceId(deviceId);
|
||||||
recordInfo.setName(XmlUtil.getText(rootElement, "Name"));
|
recordInfo.setSn(sn);
|
||||||
if (XmlUtil.getText(rootElement, "SumNum")== null || XmlUtil.getText(rootElement, "SumNum") =="") {
|
recordInfo.setName(getText(rootElement, "Name"));
|
||||||
|
if (getText(rootElement, "SumNum")== null || getText(rootElement, "SumNum") =="") {
|
||||||
recordInfo.setSumNum(0);
|
recordInfo.setSumNum(0);
|
||||||
} else {
|
} else {
|
||||||
recordInfo.setSumNum(Integer.parseInt(XmlUtil.getText(rootElement, "SumNum")));
|
recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum")));
|
||||||
}
|
}
|
||||||
String sn = XmlUtil.getText(rootElement, "SN");
|
|
||||||
Element recordListElement = rootElement.element("RecordList");
|
Element recordListElement = rootElement.element("RecordList");
|
||||||
if (recordListElement == null || recordInfo.getSumNum() == 0) {
|
if (recordListElement == null || recordInfo.getSumNum() == 0) {
|
||||||
logger.info("无录像数据");
|
logger.info("无录像数据");
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
|
|
||||||
msg.setData(recordInfo);
|
msg.setData(recordInfo);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
} else {
|
} else {
|
||||||
Iterator<Element> recordListIterator = recordListElement.elementIterator();
|
Iterator<Element> recordListIterator = recordListElement.elementIterator();
|
||||||
List<RecordItem> recordList = new ArrayList<RecordItem>();
|
List<RecordItem> recordList = new ArrayList<RecordItem>();
|
||||||
@ -873,18 +950,18 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
record = new RecordItem();
|
record = new RecordItem();
|
||||||
record.setDeviceId(XmlUtil.getText(itemRecord, "DeviceID"));
|
record.setDeviceId(getText(itemRecord, "DeviceID"));
|
||||||
record.setName(XmlUtil.getText(itemRecord, "Name"));
|
record.setName(getText(itemRecord, "Name"));
|
||||||
record.setFilePath(XmlUtil.getText(itemRecord, "FilePath"));
|
record.setFilePath(getText(itemRecord, "FilePath"));
|
||||||
record.setAddress(XmlUtil.getText(itemRecord, "Address"));
|
record.setAddress(getText(itemRecord, "Address"));
|
||||||
record.setStartTime(
|
record.setStartTime(
|
||||||
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord, "StartTime")));
|
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "StartTime")));
|
||||||
record.setEndTime(
|
record.setEndTime(
|
||||||
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord, "EndTime")));
|
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "EndTime")));
|
||||||
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
|
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
|
||||||
: Integer.parseInt(XmlUtil.getText(itemRecord, "Secrecy")));
|
: Integer.parseInt(getText(itemRecord, "Secrecy")));
|
||||||
record.setType(XmlUtil.getText(itemRecord, "Type"));
|
record.setType(getText(itemRecord, "Type"));
|
||||||
record.setRecorderId(XmlUtil.getText(itemRecord, "RecorderID"));
|
record.setRecorderId(getText(itemRecord, "RecorderID"));
|
||||||
recordList.add(record);
|
recordList.add(record);
|
||||||
}
|
}
|
||||||
recordInfo.setRecordList(recordList);
|
recordInfo.setRecordList(recordList);
|
||||||
@ -956,11 +1033,21 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageMediaStatus(RequestEvent evt){
|
private void processMessageMediaStatus(RequestEvent evt){
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
String NotifyType =XmlUtil.getText(rootElement, "NotifyType");
|
String NotifyType =getText(rootElement, "NotifyType");
|
||||||
if (NotifyType.equals("121")){
|
if (NotifyType.equals("121")){
|
||||||
logger.info("媒体播放完毕,通知关流");
|
logger.info("媒体播放完毕,通知关流");
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, "*");
|
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, "*");
|
||||||
@ -981,10 +1068,21 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processMessageBroadcast(RequestEvent evt) {
|
private void processMessageBroadcast(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
|
||||||
|
responseAck(evt, Response.NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId + channelId;
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (rootElement.getName().equals("Response")) {
|
if (rootElement.getName().equals("Response")) {
|
||||||
// 此处是对本平台发出Broadcast指令的应答
|
// 此处是对本平台发出Broadcast指令的应答
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
@ -993,10 +1091,9 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
logger.debug(json.toJSONString());
|
logger.debug(json.toJSONString());
|
||||||
}
|
}
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setDeviceId(deviceId);
|
msg.setKey(key);
|
||||||
msg.setType(DeferredResultHolder.CALLBACK_CMD_BROADCAST);
|
|
||||||
msg.setData(json);
|
msg.setData(json);
|
||||||
deferredResultHolder.invokeResult(msg);
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
} else {
|
} else {
|
||||||
// 此处是上级发出的Broadcast指令
|
// 此处是上级发出的Broadcast指令
|
||||||
}
|
}
|
||||||
@ -1004,97 +1101,4 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复200 OK
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) {
|
|
||||||
serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复404
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) {
|
|
||||||
serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element getRootElement(RequestEvent evt) throws DocumentException {
|
|
||||||
|
|
||||||
return getRootElement(evt, "gb2312");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element getRootElement(RequestEvent evt, String charset) throws DocumentException {
|
|
||||||
if (charset == null) {
|
|
||||||
charset = "gb2312";
|
|
||||||
}
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
SAXReader reader = new SAXReader();
|
|
||||||
reader.setEncoding(charset);
|
|
||||||
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
|
||||||
return xml.getRootElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmder(SIPCommander cmder) {
|
|
||||||
this.cmder = cmder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPublisher(EventPublisher publisher) {
|
|
||||||
this.publisher = publisher;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedis(RedisUtil redis) {
|
|
||||||
this.redis = redis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) {
|
|
||||||
this.deferredResultHolder = deferredResultHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffLineDetector(DeviceOffLineDetector offLineDetector) {
|
|
||||||
this.offLineDetector = offLineDetector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRedisCatchStorage getRedisCatchStorage() {
|
|
||||||
return redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
|
||||||
this.redisCatchStorage = redisCatchStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SIPCommanderFroPlatform getCmderFroPlatform() {
|
|
||||||
return cmderFroPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmderFroPlatform(SIPCommanderFroPlatform cmderFroPlatform) {
|
|
||||||
this.cmderFroPlatform = cmderFroPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceAlarmService(IDeviceAlarmService deviceAlarmService) {
|
|
||||||
this.deviceAlarmService = deviceAlarmService;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,67 +1,76 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.utils.GpsUtil;
|
import com.genersoft.iot.vmp.utils.GpsUtil;
|
||||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
|
||||||
import org.dom4j.Document;
|
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
import org.dom4j.io.SAXReader;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: Notify请求处理器
|
* SIP命令类型: NOTIFY请求
|
||||||
* @author: lawrencehj
|
|
||||||
* @date: 2021年1月27日
|
|
||||||
*/
|
*/
|
||||||
|
@Component
|
||||||
|
public class NotifyRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private UserSetup userSetup = (UserSetup) SpringBeanFactory.getBean("userSetup");
|
private final static Logger logger = LoggerFactory.getLogger(NotifyRequestProcessor.class);
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
@Autowired
|
||||||
|
private UserSetup userSetup;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private EventPublisher publisher;
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private DeviceOffLineDetector offLineDetector;
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
private static final String NOTIFY_CATALOG = "Catalog";
|
private static final String NOTIFY_CATALOG = "Catalog";
|
||||||
private static final String NOTIFY_ALARM = "Alarm";
|
private static final String NOTIFY_ALARM = "Alarm";
|
||||||
private static final String NOTIFY_MOBILE_POSITION = "MobilePosition";
|
private static final String NOTIFY_MOBILE_POSITION = "MobilePosition";
|
||||||
|
private String method = "NOTIFY";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt) {
|
public void process(RequestEvent evt) {
|
||||||
@ -80,7 +89,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
processNotifyMobilePosition(evt);
|
processNotifyMobilePosition(evt);
|
||||||
} else {
|
} else {
|
||||||
logger.info("接收到消息:" + cmd);
|
logger.info("接收到消息:" + cmd);
|
||||||
response200Ok(evt);
|
responseAck(evt, Response.OK);
|
||||||
}
|
}
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -135,7 +144,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
storager.clearMobilePositionsByDeviceId(deviceId);
|
storager.clearMobilePositionsByDeviceId(deviceId);
|
||||||
}
|
}
|
||||||
storager.insertMobilePosition(mobilePosition);
|
storager.insertMobilePosition(mobilePosition);
|
||||||
response200Ok(evt);
|
responseAck(evt, Response.OK);
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -199,7 +208,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// TODO: 需要实现存储报警信息、报警分类
|
// TODO: 需要实现存储报警信息、报警分类
|
||||||
|
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
response200Ok(evt);
|
responseAck(evt, Response.OK);
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
publisher.deviceAlarmEventPublish(deviceAlarm);
|
publisher.deviceAlarmEventPublish(deviceAlarm);
|
||||||
}
|
}
|
||||||
@ -215,10 +224,14 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
*/
|
*/
|
||||||
private void processNotifyCatalogList(RequestEvent evt) {
|
private void processNotifyCatalogList(RequestEvent evt) {
|
||||||
try {
|
try {
|
||||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
|
||||||
|
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
Element deviceIdElement = rootElement.element("DeviceID");
|
|
||||||
String deviceId = deviceIdElement.getText();
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (device != null ) {
|
if (device != null ) {
|
||||||
rootElement = getRootElement(evt, device.getCharset());
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
}
|
}
|
||||||
@ -228,9 +241,7 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
}
|
}
|
||||||
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
||||||
if (deviceListIterator != null) {
|
if (deviceListIterator != null) {
|
||||||
if (device == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 遍历DeviceList
|
// 遍历DeviceList
|
||||||
while (deviceListIterator.hasNext()) {
|
while (deviceListIterator.hasNext()) {
|
||||||
Element itemDevice = deviceListIterator.next();
|
Element itemDevice = deviceListIterator.next();
|
||||||
@ -238,14 +249,78 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
if (channelDeviceElement == null) {
|
if (channelDeviceElement == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String channelDeviceId = channelDeviceElement.getTextTrim();
|
Element eventElement = itemDevice.element("Event");
|
||||||
|
DeviceChannel channel = channelContentHander(itemDevice);
|
||||||
|
switch (eventElement.getText().toUpperCase()) {
|
||||||
|
case "ON" : // 上线
|
||||||
|
logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId());
|
||||||
|
storager.deviceChannelOnline(deviceId, channel.getChannelId());
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
case "OFF" : // 离线
|
||||||
|
logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId());
|
||||||
|
storager.deviceChannelOffline(deviceId, channel.getChannelId());
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
case "VLOST" : // 视频丢失
|
||||||
|
logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId());
|
||||||
|
storager.deviceChannelOffline(deviceId, channel.getChannelId());
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
case "DEFECT" : // 故障
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
case "ADD" : // 增加
|
||||||
|
logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId());
|
||||||
|
storager.updateChannel(deviceId, channel);
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
case "DEL" : // 删除
|
||||||
|
logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId());
|
||||||
|
storager.delChannel(deviceId, channel.getChannelId());
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
case "UPDATE" : // 更新
|
||||||
|
logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId());
|
||||||
|
storager.updateChannel(deviceId, channel);
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
responseAck(evt, Response.BAD_REQUEST, "event not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestMessage msg = new RequestMessage();
|
||||||
|
// msg.setDeviceId(deviceId);
|
||||||
|
// msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
|
||||||
|
// msg.setData(device);
|
||||||
|
// deferredResultHolder.invokeResult(msg);
|
||||||
|
|
||||||
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceChannel channelContentHander(Element itemDevice){
|
||||||
Element channdelNameElement = itemDevice.element("Name");
|
Element channdelNameElement = itemDevice.element("Name");
|
||||||
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
|
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
|
||||||
Element statusElement = itemDevice.element("Status");
|
Element statusElement = itemDevice.element("Status");
|
||||||
String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
|
String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
|
||||||
DeviceChannel deviceChannel = new DeviceChannel();
|
DeviceChannel deviceChannel = new DeviceChannel();
|
||||||
deviceChannel.setName(channelName);
|
deviceChannel.setName(channelName);
|
||||||
deviceChannel.setChannelId(channelDeviceId);
|
Element channdelIdElement = itemDevice.element("DeviceID");
|
||||||
|
String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : "";
|
||||||
|
deviceChannel.setChannelId(channelId);
|
||||||
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
|
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
|
||||||
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
|
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
|
||||||
deviceChannel.setStatus(1);
|
deviceChannel.setStatus(1);
|
||||||
@ -318,50 +393,10 @@ public class NotifyRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
|
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
|
||||||
}
|
}
|
||||||
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
||||||
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
return deviceChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestMessage msg = new RequestMessage();
|
|
||||||
// msg.setDeviceId(deviceId);
|
|
||||||
// msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
|
|
||||||
// msg.setData(device);
|
|
||||||
// deferredResultHolder.invokeResult(msg);
|
|
||||||
// 回复200 OK
|
|
||||||
response200Ok(evt);
|
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
|
||||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 回复200 OK
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @throws SipException
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
* @throws ParseException
|
|
||||||
*/
|
|
||||||
private void response200Ok(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
|
||||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
|
||||||
serverTransaction.sendResponse(response);
|
|
||||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
|
|
||||||
}
|
|
||||||
private Element getRootElement(RequestEvent evt) throws DocumentException {
|
|
||||||
return getRootElement(evt, "gb2312");
|
|
||||||
}
|
|
||||||
private Element getRootElement(RequestEvent evt, String charset) throws DocumentException {
|
|
||||||
if (charset == null) charset = "gb2312";
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
SAXReader reader = new SAXReader();
|
|
||||||
reader.setEncoding(charset);
|
|
||||||
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
|
||||||
return xml.getRootElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmder(SIPCommander cmder) {
|
public void setCmder(SIPCommander cmder) {
|
||||||
}
|
}
|
@ -1,59 +1,71 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.header.AuthorizationHeader;
|
|
||||||
import javax.sip.header.ContactHeader;
|
|
||||||
import javax.sip.header.ExpiresHeader;
|
|
||||||
import javax.sip.header.FromHeader;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
|
|
||||||
import gov.nist.javax.sip.RequestEventExt;
|
|
||||||
import gov.nist.javax.sip.header.SIPDateHeader;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
|
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
|
||||||
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
|
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import gov.nist.javax.sip.RequestEventExt;
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
import gov.nist.javax.sip.address.AddressImpl;
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
import gov.nist.javax.sip.address.SipUri;
|
||||||
import gov.nist.javax.sip.header.Expires;
|
import gov.nist.javax.sip.header.Expires;
|
||||||
|
import gov.nist.javax.sip.header.SIPDateHeader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.ServerTransaction;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.*;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:收到注册请求 处理
|
* SIP命令类型: REGISTER请求
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:47:25
|
|
||||||
*/
|
*/
|
||||||
public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
|
@Component
|
||||||
|
public class RegisterRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
|
private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
|
||||||
|
|
||||||
|
public String method = "REGISTER";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private RegisterLogicHandler handler;
|
private RegisterLogicHandler handler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
private EventPublisher publisher;
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收到注册请求 处理
|
* 收到注册请求 处理
|
||||||
* @param evt
|
* @param evt
|
||||||
@ -96,7 +108,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// 注册失败
|
// 注册失败
|
||||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||||
response.setReasonPhrase("wrong password");
|
response.setReasonPhrase("wrong password");
|
||||||
logger.info("[{}] 密码错误 回复403", requestAddress);
|
logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress);
|
||||||
}else {
|
}else {
|
||||||
// 携带授权头并且密码正确
|
// 携带授权头并且密码正确
|
||||||
response = getMessageFactory().createResponse(Response.OK, request);
|
response = getMessageFactory().createResponse(Response.OK, request);
|
||||||
@ -182,20 +194,4 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSipConfig(SipConfig sipConfig) {
|
|
||||||
this.sipConfig = sipConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHandler(RegisterLogicHandler handler) {
|
|
||||||
this.handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVideoManagerStorager(IVideoManagerStorager storager) {
|
|
||||||
this.storager = storager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPublisher(EventPublisher publisher) {
|
|
||||||
this.publisher = publisher;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,13 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
import javax.sip.RequestEvent;
|
import javax.sip.RequestEvent;
|
||||||
@ -9,19 +16,25 @@ import javax.sip.SipException;
|
|||||||
import javax.sip.header.ExpiresHeader;
|
import javax.sip.header.ExpiresHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:SUBSCRIBE请求处理器
|
* SIP命令类型: SUBSCRIBE请求
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:31:20
|
|
||||||
*/
|
*/
|
||||||
public class SubscribeRequestProcessor extends SIPRequestAbstractProcessor {
|
@Component
|
||||||
|
public class SubscribeRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(SubscribeRequestProcessor.class);
|
private Logger logger = LoggerFactory.getLogger(SubscribeRequestProcessor.class);
|
||||||
|
private String method = "SUBSCRIBE";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理SUBSCRIBE请求
|
* 处理SUBSCRIBE请求
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
public interface IMessageHandler {
|
||||||
|
/**
|
||||||
|
* 处理来自设备的信息
|
||||||
|
* @param evt
|
||||||
|
* @param device
|
||||||
|
*/
|
||||||
|
void handForDevice(RequestEvent evt, Device device, Element element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理来自平台的信息
|
||||||
|
* @param evt
|
||||||
|
* @param parentPlatform
|
||||||
|
*/
|
||||||
|
void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element);
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent implements IMessageHandler{
|
||||||
|
|
||||||
|
public Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public void addHandler(String cmdType, IMessageHandler messageHandler) {
|
||||||
|
messageHandlerMap.put(cmdType, messageHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
String cmd = getText(element, "CmdType");
|
||||||
|
IMessageHandler messageHandler = messageHandlerMap.get(cmd);
|
||||||
|
if (messageHandler != null) {
|
||||||
|
messageHandler.handForDevice(evt, device, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
String cmd = getText(element, "CmdType");
|
||||||
|
IMessageHandler messageHandler = messageHandlerMap.get(cmd);
|
||||||
|
if (messageHandler != null) {
|
||||||
|
messageHandler.handForPlatform(evt, parentPlatform, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MessageRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
|
||||||
|
|
||||||
|
private final String method = "MESSAGE";
|
||||||
|
|
||||||
|
private static Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHandler(String name, IMessageHandler handler) {
|
||||||
|
messageHandlerMap.put(name, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(RequestEvent evt) {
|
||||||
|
logger.debug("接收到消息:" + evt.getRequest());
|
||||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||||
|
// 查询设备是否存在
|
||||||
|
Device device = storage.queryVideoDevice(deviceId);
|
||||||
|
// 查询上级平台是否存在
|
||||||
|
ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
|
||||||
|
try {
|
||||||
|
if (device == null && parentPlatform == null) {
|
||||||
|
// 不存在则回复404
|
||||||
|
responseAck(evt, Response.NOT_FOUND, "device id not found");
|
||||||
|
}else {
|
||||||
|
Element rootElement = getRootElement(evt);
|
||||||
|
String name = rootElement.getName();
|
||||||
|
IMessageHandler messageHandler = messageHandlerMap.get(name);
|
||||||
|
if (messageHandler != null) {
|
||||||
|
if (device != null) {
|
||||||
|
messageHandler.handForDevice(evt, device, rootElement);
|
||||||
|
}else { // 由于上面已经判断都为null则直接返回,所以这里device和parentPlatform必有一个不为null
|
||||||
|
messageHandler.handForPlatform(evt, parentPlatform, rootElement);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
// 不支持的message
|
||||||
|
// 不存在则回复415
|
||||||
|
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SipException e) {
|
||||||
|
logger.warn("SIP 回复错误", e);
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
logger.warn("参数无效", e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
logger.warn("SIP回复时解析异常", e);
|
||||||
|
} catch (DocumentException e) {
|
||||||
|
logger.warn("解析XML消息内容异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令类型: 控制命令
|
||||||
|
* 命令类型: 设备控制: 远程启动, 录像控制(TODO), 报警布防/撤防命令(TODO), 报警复位命令(TODO),
|
||||||
|
* 强制关键帧命令(TODO), 拉框放大/缩小控制命令(TODO), 看守位控制(TODO), 报警复位(TODO)
|
||||||
|
* 命令类型: 设备配置: SVAC编码配置(TODO), 音频参数(TODO), SVAC解码配置(TODO)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ControlMessageHandler extends MessageHandlerAbstract implements InitializingBean {
|
||||||
|
|
||||||
|
private final String messageType = "Control";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageRequestProcessor messageRequestProcessor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
messageRequestProcessor.addHandler(messageType, this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.VManageBootstrap;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.ControlMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
||||||
|
import gov.nist.javax.sip.SipStackImpl;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.ListeningPoint;
|
||||||
|
import javax.sip.ObjectInUseException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipProvider;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.HeaderAddress;
|
||||||
|
import javax.sip.header.ToHeader;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceControlQueryMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceControl";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ControlMessageHandler controlMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommander cmder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
controlMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
// 此处是上级发出的DeviceControl指令
|
||||||
|
String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
||||||
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
|
// 远程启动功能
|
||||||
|
if (!StringUtils.isEmpty(getText(rootElement, "TeleBoot"))) {
|
||||||
|
if (parentPlatform.getServerGBId().equals(targetGBId)) {
|
||||||
|
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
|
||||||
|
logger.info("执行远程启动本平台命令");
|
||||||
|
cmderFroPlatform.unregister(parentPlatform, null, null);
|
||||||
|
|
||||||
|
Thread restartThread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(3000);
|
||||||
|
SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
|
||||||
|
SipStackImpl stack = (SipStackImpl)up.getSipStack();
|
||||||
|
stack.stop();
|
||||||
|
Iterator listener = stack.getListeningPoints();
|
||||||
|
while (listener.hasNext()) {
|
||||||
|
stack.deleteListeningPoint((ListeningPoint) listener.next());
|
||||||
|
}
|
||||||
|
Iterator providers = stack.getSipProviders();
|
||||||
|
while (providers.hasNext()) {
|
||||||
|
stack.deleteSipProvider((SipProvider) providers.next());
|
||||||
|
}
|
||||||
|
VManageBootstrap.restart();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
} catch (ObjectInUseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
restartThread.setDaemon(false);
|
||||||
|
restartThread.start();
|
||||||
|
} else {
|
||||||
|
// 远程启动指定设备
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 云台/前端控制命令
|
||||||
|
if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) {
|
||||||
|
String cmdString = getText(rootElement,"PTZCmd");
|
||||||
|
Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
|
||||||
|
cmder.fronEndCmd(deviceForPlatform, channelId, cmdString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令类型: 通知命令
|
||||||
|
* 命令类型: 状态信息(心跳)报送, 报警通知, 媒体通知, 移动设备位置数据,语音广播通知(TODO), 设备预置位(TODO)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class NotifyMessageHandler extends MessageHandlerAbstract implements InitializingBean {
|
||||||
|
|
||||||
|
private final String messageType = "Notify";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageRequestProcessor messageRequestProcessor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
messageRequestProcessor.addHandler(messageType, this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.utils.GpsUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class);
|
||||||
|
private final String cmdType = "Alarm";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyMessageHandler notifyMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetup userSetup;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeviceAlarmService deviceAlarmService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
notifyMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
|
String channelId = deviceIdElement.getText().toString();
|
||||||
|
DeviceAlarm deviceAlarm = new DeviceAlarm();
|
||||||
|
deviceAlarm.setDeviceId(device.getDeviceId());
|
||||||
|
deviceAlarm.setChannelId(channelId);
|
||||||
|
deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority"));
|
||||||
|
deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod"));
|
||||||
|
deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime"));
|
||||||
|
if (getText(rootElement, "AlarmDescription") == null) {
|
||||||
|
deviceAlarm.setAlarmDescription("");
|
||||||
|
} else {
|
||||||
|
deviceAlarm.setAlarmDescription(getText(rootElement, "AlarmDescription"));
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Longitude"))) {
|
||||||
|
deviceAlarm.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
|
||||||
|
} else {
|
||||||
|
deviceAlarm.setLongitude(0.00);
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Latitude"))) {
|
||||||
|
deviceAlarm.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
|
||||||
|
} else {
|
||||||
|
deviceAlarm.setLatitude(0.00);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
|
||||||
|
if ( deviceAlarm.getAlarmMethod().equals("4")) {
|
||||||
|
MobilePosition mobilePosition = new MobilePosition();
|
||||||
|
mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
|
||||||
|
mobilePosition.setTime(deviceAlarm.getAlarmTime());
|
||||||
|
mobilePosition.setLongitude(deviceAlarm.getLongitude());
|
||||||
|
mobilePosition.setLatitude(deviceAlarm.getLatitude());
|
||||||
|
mobilePosition.setReportSource("GPS Alarm");
|
||||||
|
BaiduPoint bp = new BaiduPoint();
|
||||||
|
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
|
||||||
|
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
|
||||||
|
mobilePosition.setGeodeticSystem("BD-09");
|
||||||
|
mobilePosition.setCnLng(bp.getBdLng());
|
||||||
|
mobilePosition.setCnLat(bp.getBdLat());
|
||||||
|
if (!userSetup.getSavePositionHistory()) {
|
||||||
|
storager.clearMobilePositionsByDeviceId(device.getDeviceId());
|
||||||
|
}
|
||||||
|
storager.insertMobilePosition(mobilePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("存储报警信息、报警分类");
|
||||||
|
// 存储报警信息、报警分类
|
||||||
|
deviceAlarmService.add(deviceAlarm);
|
||||||
|
|
||||||
|
if (offLineDetector.isOnline(device.getDeviceId())) {
|
||||||
|
publisher.deviceAlarmEventPublish(deviceAlarm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(CatalogNotifyMessageHandler.class);
|
||||||
|
private final String cmdType = "Catalog";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyMessageHandler notifyMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
notifyMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId();
|
||||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
|
try {
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
Element snElement = rootElement.element("SN");
|
||||||
|
String sn = snElement.getText();
|
||||||
|
// 准备回复通道信息
|
||||||
|
List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
|
||||||
|
// 查询关联的直播通道
|
||||||
|
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
|
||||||
|
int size = channelReduces.size() + gbStreams.size();
|
||||||
|
// 回复级联的通道
|
||||||
|
if (channelReduces.size() > 0) {
|
||||||
|
for (ChannelReduce channelReduce : channelReduces) {
|
||||||
|
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
|
||||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 回复直播的通道
|
||||||
|
if (gbStreams.size() > 0) {
|
||||||
|
for (GbStream gbStream : gbStreams) {
|
||||||
|
DeviceChannel deviceChannel = new DeviceChannel();
|
||||||
|
deviceChannel.setChannelId(gbStream.getGbId());
|
||||||
|
deviceChannel.setName(gbStream.getName());
|
||||||
|
deviceChannel.setLongitude(gbStream.getLongitude());
|
||||||
|
deviceChannel.setLatitude(gbStream.getLatitude());
|
||||||
|
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
|
||||||
|
deviceChannel.setManufacture("wvp-pro");
|
||||||
|
deviceChannel.setStatus(gbStream.isStatus()?1:0);
|
||||||
|
// deviceChannel.setParentId(parentPlatform.getDeviceGBId());
|
||||||
|
deviceChannel.setRegisterWay(1);
|
||||||
|
deviceChannel.setCivilCode(config.getDomain());
|
||||||
|
deviceChannel.setModel("live");
|
||||||
|
deviceChannel.setOwner("wvp-pro");
|
||||||
|
deviceChannel.setParental(0);
|
||||||
|
deviceChannel.setSecrecy("0");
|
||||||
|
deviceChannel.setSecrecy("0");
|
||||||
|
|
||||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size == 0) {
|
||||||
|
// 回复无通道
|
||||||
|
cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size);
|
||||||
|
}
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
|
||||||
|
private final String cmdType = "Keepalive";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyMessageHandler notifyMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
notifyMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
// 检查设备是否存在并在线, 不在线则设置为在线
|
||||||
|
try {
|
||||||
|
if (device != null ) {
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||||
|
}
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
// 不会收到上级平台的心跳信息
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(MediaStatusNotifyMessageHandler.class);
|
||||||
|
private final String cmdType = "MediaStatus";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyMessageHandler notifyMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommander cmder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
notifyMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
|
||||||
|
// 回复200 OK
|
||||||
|
try {
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
String NotifyType =getText(rootElement, "NotifyType");
|
||||||
|
if (NotifyType.equals("121")){
|
||||||
|
logger.info("媒体播放完毕,通知关流");
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*");
|
||||||
|
if (streamInfo != null) {
|
||||||
|
redisCatchStorage.stopPlayback(streamInfo);
|
||||||
|
cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.utils.GpsUtil;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(MobilePositionNotifyMessageHandler.class);
|
||||||
|
private final String cmdType = "MobilePosition";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotifyMessageHandler notifyMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetup userSetup;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
notifyMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
|
|
||||||
|
MobilePosition mobilePosition = new MobilePosition();
|
||||||
|
if (!StringUtils.isEmpty(device.getName())) {
|
||||||
|
mobilePosition.setDeviceName(device.getName());
|
||||||
|
}
|
||||||
|
mobilePosition.setDeviceId(device.getDeviceId());
|
||||||
|
mobilePosition.setChannelId(getText(rootElement, "DeviceID"));
|
||||||
|
mobilePosition.setTime(getText(rootElement, "Time"));
|
||||||
|
mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
|
||||||
|
mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Speed"))) {
|
||||||
|
mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed")));
|
||||||
|
} else {
|
||||||
|
mobilePosition.setSpeed(0.0);
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Direction"))) {
|
||||||
|
mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction")));
|
||||||
|
} else {
|
||||||
|
mobilePosition.setDirection(0.0);
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) {
|
||||||
|
mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude")));
|
||||||
|
} else {
|
||||||
|
mobilePosition.setAltitude(0.0);
|
||||||
|
}
|
||||||
|
mobilePosition.setReportSource("Mobile Position");
|
||||||
|
BaiduPoint bp = new BaiduPoint();
|
||||||
|
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
|
||||||
|
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
|
||||||
|
mobilePosition.setGeodeticSystem("BD-09");
|
||||||
|
mobilePosition.setCnLng(bp.getBdLng());
|
||||||
|
mobilePosition.setCnLat(bp.getBdLat());
|
||||||
|
if (!userSetup.getSavePositionHistory()) {
|
||||||
|
storager.clearMobilePositionsByDeviceId(device.getDeviceId());
|
||||||
|
}
|
||||||
|
storager.insertMobilePosition(mobilePosition);
|
||||||
|
//回复 200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令类型: 查询指令
|
||||||
|
* 命令类型: 设备状态, 设备目录信息, 设备信息, 文件目录检索(TODO), 报警(TODO), 设备配置(TODO), 设备预置位(TODO), 移动设备位置数据(TODO)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class QueryMessageHandler extends MessageHandlerAbstract implements InitializingBean {
|
||||||
|
|
||||||
|
private final String messageType = "Query";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageRequestProcessor messageRequestProcessor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
messageRequestProcessor.addHandler(messageType, this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(AlarmQueryMessageHandler.class);
|
||||||
|
private final String cmdType = "Alarm";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private QueryMessageHandler queryMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
queryMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
logger.info("不支持alarm查询");
|
||||||
|
try {
|
||||||
|
responseAck(evt, Response.NOT_FOUND, "not support alarm query");
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(CatalogQueryMessageHandler.class);
|
||||||
|
private final String cmdType = "Catalog";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private QueryMessageHandler queryMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
queryMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId();
|
||||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
|
try {
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
Element snElement = rootElement.element("SN");
|
||||||
|
String sn = snElement.getText();
|
||||||
|
// 准备回复通道信息
|
||||||
|
List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
|
||||||
|
// 查询关联的直播通道
|
||||||
|
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
|
||||||
|
int size = channelReduces.size() + gbStreams.size();
|
||||||
|
// 回复级联的通道
|
||||||
|
if (channelReduces.size() > 0) {
|
||||||
|
for (ChannelReduce channelReduce : channelReduces) {
|
||||||
|
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
|
||||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 回复直播的通道
|
||||||
|
if (gbStreams.size() > 0) {
|
||||||
|
for (GbStream gbStream : gbStreams) {
|
||||||
|
DeviceChannel deviceChannel = new DeviceChannel();
|
||||||
|
deviceChannel.setChannelId(gbStream.getGbId());
|
||||||
|
deviceChannel.setName(gbStream.getName());
|
||||||
|
deviceChannel.setLongitude(gbStream.getLongitude());
|
||||||
|
deviceChannel.setLatitude(gbStream.getLatitude());
|
||||||
|
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
|
||||||
|
deviceChannel.setManufacture("wvp-pro");
|
||||||
|
deviceChannel.setStatus(gbStream.isStatus()?1:0);
|
||||||
|
// deviceChannel.setParentId(parentPlatform.getDeviceGBId());
|
||||||
|
deviceChannel.setRegisterWay(1);
|
||||||
|
deviceChannel.setCivilCode(config.getDomain());
|
||||||
|
deviceChannel.setModel("live");
|
||||||
|
deviceChannel.setOwner("wvp-pro");
|
||||||
|
deviceChannel.setParental(0);
|
||||||
|
deviceChannel.setSecrecy("0");
|
||||||
|
deviceChannel.setSecrecy("0");
|
||||||
|
|
||||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size == 0) {
|
||||||
|
// 回复无通道
|
||||||
|
cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size);
|
||||||
|
}
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceInfoQueryMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceInfo";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private QueryMessageHandler queryMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
queryMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
logger.info("接收到DeviceInfo查询消息");
|
||||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
|
try {
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
String sn = rootElement.element("SN").getText();
|
||||||
|
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.FromHeader;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceStatusQueryMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceStatus";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private QueryMessageHandler queryMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
queryMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
logger.info("接收到DeviceStatus查询消息");
|
||||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
|
||||||
|
// 回复200 OK
|
||||||
|
try {
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
String sn = rootElement.element("SN").getText();
|
||||||
|
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令类型: 请求动作的应答
|
||||||
|
* 命令类型: 设备控制, 报警通知, 设备目录信息查询, 目录信息查询, 目录收到, 设备信息查询, 设备状态信息查询 ......
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ResponseMessageHandler extends MessageHandlerAbstract implements InitializingBean {
|
||||||
|
|
||||||
|
private final String messageType = "Response";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageRequestProcessor messageRequestProcessor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
messageRequestProcessor.addHandler(messageType, this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AlarmResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(AlarmResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "Alarm";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
|
String channelId = deviceIdElement.getText().toString();
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + device.getDeviceId() + channelId;
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
XmlUtil.node2Json(rootElement, json);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(json.toJSONString());
|
||||||
|
}
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(json);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(BroadcastResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "Broadcast";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
try {
|
||||||
|
String channelId = getText(rootElement, "DeviceID");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId;
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
// 此处是对本平台发出Broadcast指令的应答
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
XmlUtil.node2Json(rootElement, json);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(json.toJSONString());
|
||||||
|
}
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(json);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (ParseException | SipException | InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,182 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "Catalog";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + device.getDeviceId();
|
||||||
|
Element rootElement = null;
|
||||||
|
try {
|
||||||
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
|
Element deviceListElement = rootElement.element("DeviceList");
|
||||||
|
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
|
||||||
|
if (deviceListIterator != null) {
|
||||||
|
|
||||||
|
// 遍历DeviceList
|
||||||
|
while (deviceListIterator.hasNext()) {
|
||||||
|
Element itemDevice = deviceListIterator.next();
|
||||||
|
Element channelDeviceElement = itemDevice.element("DeviceID");
|
||||||
|
if (channelDeviceElement == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String channelDeviceId = channelDeviceElement.getText();
|
||||||
|
Element channdelNameElement = itemDevice.element("Name");
|
||||||
|
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
|
||||||
|
Element statusElement = itemDevice.element("Status");
|
||||||
|
String status = statusElement != null ? statusElement.getText().toString() : "ON";
|
||||||
|
DeviceChannel deviceChannel = new DeviceChannel();
|
||||||
|
deviceChannel.setName(channelName);
|
||||||
|
deviceChannel.setChannelId(channelDeviceId);
|
||||||
|
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
|
||||||
|
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
|
||||||
|
deviceChannel.setStatus(1);
|
||||||
|
}
|
||||||
|
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
|
||||||
|
deviceChannel.setStatus(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceChannel.setManufacture(getText(itemDevice, "Manufacturer"));
|
||||||
|
deviceChannel.setModel(getText(itemDevice, "Model"));
|
||||||
|
deviceChannel.setOwner(getText(itemDevice, "Owner"));
|
||||||
|
deviceChannel.setCivilCode(getText(itemDevice, "CivilCode"));
|
||||||
|
deviceChannel.setBlock(getText(itemDevice, "Block"));
|
||||||
|
deviceChannel.setAddress(getText(itemDevice, "Address"));
|
||||||
|
if (getText(itemDevice, "Parental") == null || getText(itemDevice, "Parental") == "") {
|
||||||
|
deviceChannel.setParental(0);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setParental(Integer.parseInt(getText(itemDevice, "Parental")));
|
||||||
|
}
|
||||||
|
deviceChannel.setParentId(getText(itemDevice, "ParentID"));
|
||||||
|
if (getText(itemDevice, "SafetyWay") == null || getText(itemDevice, "SafetyWay") == "") {
|
||||||
|
deviceChannel.setSafetyWay(0);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setSafetyWay(Integer.parseInt(getText(itemDevice, "SafetyWay")));
|
||||||
|
}
|
||||||
|
if (getText(itemDevice, "RegisterWay") == null || getText(itemDevice, "RegisterWay") == "") {
|
||||||
|
deviceChannel.setRegisterWay(1);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setRegisterWay(Integer.parseInt(getText(itemDevice, "RegisterWay")));
|
||||||
|
}
|
||||||
|
deviceChannel.setCertNum(getText(itemDevice, "CertNum"));
|
||||||
|
if (getText(itemDevice, "Certifiable") == null || getText(itemDevice, "Certifiable") == "") {
|
||||||
|
deviceChannel.setCertifiable(0);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setCertifiable(Integer.parseInt(getText(itemDevice, "Certifiable")));
|
||||||
|
}
|
||||||
|
if (getText(itemDevice, "ErrCode") == null || getText(itemDevice, "ErrCode") == "") {
|
||||||
|
deviceChannel.setErrCode(0);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setErrCode(Integer.parseInt(getText(itemDevice, "ErrCode")));
|
||||||
|
}
|
||||||
|
deviceChannel.setEndTime(getText(itemDevice, "EndTime"));
|
||||||
|
deviceChannel.setSecrecy(getText(itemDevice, "Secrecy"));
|
||||||
|
deviceChannel.setIpAddress(getText(itemDevice, "IPAddress"));
|
||||||
|
if (getText(itemDevice, "Port") == null || getText(itemDevice, "Port") == "") {
|
||||||
|
deviceChannel.setPort(0);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setPort(Integer.parseInt(getText(itemDevice, "Port")));
|
||||||
|
}
|
||||||
|
deviceChannel.setPassword(getText(itemDevice, "Password"));
|
||||||
|
if (NumericUtil.isDouble(getText(itemDevice, "Longitude"))) {
|
||||||
|
deviceChannel.setLongitude(Double.parseDouble(getText(itemDevice, "Longitude")));
|
||||||
|
} else {
|
||||||
|
deviceChannel.setLongitude(0.00);
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(itemDevice, "Latitude"))) {
|
||||||
|
deviceChannel.setLatitude(Double.parseDouble(getText(itemDevice, "Latitude")));
|
||||||
|
} else {
|
||||||
|
deviceChannel.setLatitude(0.00);
|
||||||
|
}
|
||||||
|
if (getText(itemDevice, "PTZType") == null || getText(itemDevice, "PTZType") == "") {
|
||||||
|
deviceChannel.setPTZType(0);
|
||||||
|
} else {
|
||||||
|
deviceChannel.setPTZType(Integer.parseInt(getText(itemDevice, "PTZType")));
|
||||||
|
}
|
||||||
|
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
||||||
|
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(device);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
if (offLineDetector.isOnline(device.getDeviceId())) {
|
||||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (DocumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(ConfigDownloadResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "ConfigDownload";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
String channelId = getText(element, "DeviceID");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId;
|
||||||
|
try {
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
XmlUtil.node2Json(element, json);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(json.toJSONString());
|
||||||
|
}
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(json);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
// 不会收到上级平台的心跳信息
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceConfigResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceConfigResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceConfig";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
XmlUtil.node2Json(element, json);
|
||||||
|
String channelId = getText(element, "DeviceID");
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(json.toJSONString());
|
||||||
|
}
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + device.getDeviceId() + channelId;
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(json);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceControlResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceControlResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceControl";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
String channelId = getText(element, "DeviceID");
|
||||||
|
XmlUtil.node2Json(element, json);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(json.toJSONString());
|
||||||
|
}
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + device.getDeviceId() + channelId;
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(json);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceInfoResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceInfo";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
logger.debug("接收到DeviceInfo应答消息");
|
||||||
|
try {
|
||||||
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
|
Element deviceIdElement = rootElement.element("DeviceID");
|
||||||
|
String channelId = deviceIdElement.getTextTrim();
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + device.getDeviceId() + channelId;
|
||||||
|
device.setName(getText(rootElement, "DeviceName"));
|
||||||
|
|
||||||
|
device.setManufacturer(getText(rootElement, "Manufacturer"));
|
||||||
|
device.setModel(getText(rootElement, "Model"));
|
||||||
|
device.setFirmware(getText(rootElement, "Firmware"));
|
||||||
|
if (StringUtils.isEmpty(device.getStreamMode())) {
|
||||||
|
device.setStreamMode("UDP");
|
||||||
|
}
|
||||||
|
storager.updateDevice(device);
|
||||||
|
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(device);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
// 回复200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
if (offLineDetector.isOnline(device.getDeviceId())) {
|
||||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
|
}
|
||||||
|
} catch (DocumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(DeviceStatusResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "DeviceStatus";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventPublisher publisher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||||
|
logger.info("接收到DeviceStatus应答消息");
|
||||||
|
// 检查设备是否存在, 不存在则不回复
|
||||||
|
// 回复200 OK
|
||||||
|
try {
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Element deviceIdElement = element.element("DeviceID");
|
||||||
|
String channelId = deviceIdElement.getText();
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
XmlUtil.node2Json(element, json);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(json.toJSONString());
|
||||||
|
}
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId() + channelId);
|
||||||
|
msg.setData(json);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
|
||||||
|
if (offLineDetector.isOnline(device.getDeviceId())) {
|
||||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.utils.GpsUtil;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MobilePositionResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(MobilePositionResponseMessageHandler.class);
|
||||||
|
private final String cmdType = "MobilePosition";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetup userSetup;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
|
|
||||||
|
MobilePosition mobilePosition = new MobilePosition();
|
||||||
|
if (!StringUtils.isEmpty(device.getName())) {
|
||||||
|
mobilePosition.setDeviceName(device.getName());
|
||||||
|
}
|
||||||
|
mobilePosition.setDeviceId(device.getDeviceId());
|
||||||
|
mobilePosition.setChannelId(getText(rootElement, "DeviceID"));
|
||||||
|
mobilePosition.setTime(getText(rootElement, "Time"));
|
||||||
|
mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
|
||||||
|
mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Speed"))) {
|
||||||
|
mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed")));
|
||||||
|
} else {
|
||||||
|
mobilePosition.setSpeed(0.0);
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Direction"))) {
|
||||||
|
mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction")));
|
||||||
|
} else {
|
||||||
|
mobilePosition.setDirection(0.0);
|
||||||
|
}
|
||||||
|
if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) {
|
||||||
|
mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude")));
|
||||||
|
} else {
|
||||||
|
mobilePosition.setAltitude(0.0);
|
||||||
|
}
|
||||||
|
mobilePosition.setReportSource("Mobile Position");
|
||||||
|
BaiduPoint bp = new BaiduPoint();
|
||||||
|
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude()));
|
||||||
|
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat());
|
||||||
|
mobilePosition.setGeodeticSystem("BD-09");
|
||||||
|
mobilePosition.setCnLng(bp.getBdLng());
|
||||||
|
mobilePosition.setCnLat(bp.getBdLat());
|
||||||
|
if (!userSetup.getSavePositionHistory()) {
|
||||||
|
storager.clearMobilePositionsByDeviceId(device.getDeviceId());
|
||||||
|
}
|
||||||
|
storager.insertMobilePosition(mobilePosition);
|
||||||
|
//回复 200 OK
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.RequestEvent;
|
||||||
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(RecordInfoResponseMessageHandler.class);
|
||||||
|
public static volatile List<String> threadNameList = new ArrayList();
|
||||||
|
private final String cmdType = "RecordInfo";
|
||||||
|
private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResponseMessageHandler responseMessageHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtil redis;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeferredResultHolder deferredResultHolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
responseMessageHandler.addHandler(cmdType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||||
|
|
||||||
|
// 回复200 OK
|
||||||
|
try {
|
||||||
|
responseAck(evt, Response.OK);
|
||||||
|
|
||||||
|
rootElement = getRootElement(evt, device.getCharset());
|
||||||
|
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
RecordInfo recordInfo = new RecordInfo();
|
||||||
|
String sn = getText(rootElement, "SN");
|
||||||
|
String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + sn;
|
||||||
|
recordInfo.setDeviceId(device.getDeviceId());
|
||||||
|
recordInfo.setSn(sn);
|
||||||
|
recordInfo.setName(getText(rootElement, "Name"));
|
||||||
|
if (getText(rootElement, "SumNum") == null || getText(rootElement, "SumNum") == "") {
|
||||||
|
recordInfo.setSumNum(0);
|
||||||
|
} else {
|
||||||
|
recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum")));
|
||||||
|
}
|
||||||
|
Element recordListElement = rootElement.element("RecordList");
|
||||||
|
if (recordListElement == null || recordInfo.getSumNum() == 0) {
|
||||||
|
logger.info("无录像数据");
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setKey(key);
|
||||||
|
msg.setData(recordInfo);
|
||||||
|
deferredResultHolder.invokeAllResult(msg);
|
||||||
|
} else {
|
||||||
|
Iterator<Element> recordListIterator = recordListElement.elementIterator();
|
||||||
|
List<RecordItem> recordList = new ArrayList<RecordItem>();
|
||||||
|
if (recordListIterator != null) {
|
||||||
|
RecordItem record = new RecordItem();
|
||||||
|
logger.info("处理录像列表数据...");
|
||||||
|
// 遍历DeviceList
|
||||||
|
while (recordListIterator.hasNext()) {
|
||||||
|
Element itemRecord = recordListIterator.next();
|
||||||
|
Element recordElement = itemRecord.element("DeviceID");
|
||||||
|
if (recordElement == null) {
|
||||||
|
logger.info("记录为空,下一个...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
record = new RecordItem();
|
||||||
|
record.setDeviceId(getText(itemRecord, "DeviceID"));
|
||||||
|
record.setName(getText(itemRecord, "Name"));
|
||||||
|
record.setFilePath(getText(itemRecord, "FilePath"));
|
||||||
|
record.setAddress(getText(itemRecord, "Address"));
|
||||||
|
record.setStartTime(
|
||||||
|
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "StartTime")));
|
||||||
|
record.setEndTime(
|
||||||
|
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "EndTime")));
|
||||||
|
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
|
||||||
|
: Integer.parseInt(getText(itemRecord, "Secrecy")));
|
||||||
|
record.setType(getText(itemRecord, "Type"));
|
||||||
|
record.setRecorderId(getText(itemRecord, "RecorderID"));
|
||||||
|
recordList.add(record);
|
||||||
|
}
|
||||||
|
recordInfo.setRecordList(recordList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题
|
||||||
|
String cacheKey = CACHE_RECORDINFO_KEY + device.getDeviceId() + sn;
|
||||||
|
redis.set(cacheKey + "_" + uuid, recordList, 90);
|
||||||
|
if (!threadNameList.contains(cacheKey)) {
|
||||||
|
threadNameList.add(cacheKey);
|
||||||
|
CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo);
|
||||||
|
chk.setName(cacheKey);
|
||||||
|
chk.setDeferredResultHolder(deferredResultHolder);
|
||||||
|
chk.setRedis(redis);
|
||||||
|
chk.setLogger(logger);
|
||||||
|
chk.start();
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Start Thread " + cacheKey + ".");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Thread " + cacheKey + " already started.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (DocumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response;
|
||||||
|
|
||||||
|
import javax.sip.ResponseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:处理接收IPCamera发来的SIP协议响应消息
|
||||||
|
* @author: swwheihei
|
||||||
|
* @date: 2020年5月3日 下午4:42:22
|
||||||
|
*/
|
||||||
|
public interface ISIPResponseProcessor {
|
||||||
|
|
||||||
|
void process(ResponseEvent evt);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
public abstract class SIPResponseProcessorAbstract implements InitializingBean, ISIPResponseProcessor {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.ResponseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: BYE请求响应器
|
||||||
|
* @author: swwheihei
|
||||||
|
* @date: 2020年5月3日 下午5:32:05
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ByeResponseProcessor extends SIPResponseProcessorAbstract {
|
||||||
|
|
||||||
|
private String method = "BYE";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipLayer sipLayer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addResponseProcessor(method, this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 处理BYE响应
|
||||||
|
*
|
||||||
|
* @param evt
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void process(ResponseEvent evt) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.ResponseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: CANCEL响应处理器
|
||||||
|
* @author: panlinlin
|
||||||
|
* @date: 2021年11月5日 16:35
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CancelResponseProcessor extends SIPResponseProcessorAbstract {
|
||||||
|
|
||||||
|
private String method = "CANCEL";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipLayer sipLayer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addResponseProcessor(method, this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 处理CANCEL响应
|
||||||
|
*
|
||||||
|
* @param evt
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void process(ResponseEvent evt) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,10 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
import javax.sip.*;
|
|
||||||
import javax.sip.address.SipURI;
|
|
||||||
import javax.sip.header.CSeqHeader;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
|
||||||
import gov.nist.javax.sip.ResponseEventExt;
|
import gov.nist.javax.sip.ResponseEventExt;
|
||||||
import gov.nist.javax.sip.stack.SIPDialog;
|
import gov.nist.javax.sip.stack.SIPDialog;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -16,20 +12,42 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import javax.sip.InvalidArgumentException;
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
import javax.sip.ResponseEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.CSeqHeader;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:处理INVITE响应
|
* @description: 处理INVITE响应
|
||||||
* @author: swwheihei
|
* @author: panlinlin
|
||||||
* @date: 2020年5月3日 下午4:43:52
|
* @date: 2021年11月5日 16:40
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class InviteResponseProcessor implements ISIPResponseProcessor {
|
public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
||||||
|
private String method = "INVITE";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipLayer sipLayer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig config;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addResponseProcessor(method, this);
|
||||||
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private VideoStreamSessionManager streamSession;
|
private VideoStreamSessionManager streamSession;
|
||||||
@ -41,7 +59,7 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|||||||
* @throws ParseException
|
* @throws ParseException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException {
|
public void process(ResponseEvent evt ){
|
||||||
try {
|
try {
|
||||||
Response response = evt.getResponse();
|
Response response = evt.getResponse();
|
||||||
int statusCode = response.getStatusCode();
|
int statusCode = response.getStatusCode();
|
||||||
@ -56,7 +74,11 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|||||||
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||||
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
||||||
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
||||||
|
try {
|
||||||
requestURI.setHost(event.getRemoteIpAddress());
|
requestURI.setHost(event.getRemoteIpAddress());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
requestURI.setPort(event.getRemotePort());
|
requestURI.setPort(event.getRemotePort());
|
||||||
reqAck.setRequestURI(requestURI);
|
reqAck.setRequestURI(requestURI);
|
||||||
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
|
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
|
@ -1,11 +1,10 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -19,14 +18,15 @@ import javax.sip.header.WWWAuthenticateHeader;
|
|||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:Register响应处理器
|
* @description:Register响应处理器
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午5:32:23
|
* @date: 2020年5月3日 下午5:32:23
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class RegisterResponseProcessor implements ISIPResponseProcessor {
|
public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class);
|
private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class);
|
||||||
|
private String method = "REGISTER";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISIPCommanderForPlatform sipCommanderForPlatform;
|
private ISIPCommanderForPlatform sipCommanderForPlatform;
|
||||||
@ -37,18 +37,22 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
public RegisterResponseProcessor() {
|
@Autowired
|
||||||
|
private SIPProcessorObserver sipProcessorObserver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
// 添加消息处理的订阅
|
||||||
|
sipProcessorObserver.addResponseProcessor(method, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理Register响应
|
* 处理Register响应
|
||||||
*
|
*
|
||||||
* @param evt
|
* @param evt 事件
|
||||||
* @param layer
|
|
||||||
* @param config
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
|
public void process(ResponseEvent evt) {
|
||||||
Response response = evt.getResponse();
|
Response response = evt.getResponse();
|
||||||
CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
|
CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
|
||||||
String callId = callIdHeader.getCallId();
|
String callId = callIdHeader.getCallId();
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout;
|
||||||
|
|
||||||
|
import javax.sip.TimeoutEvent;
|
||||||
|
|
||||||
|
public interface ITimeoutProcessor {
|
||||||
|
void process(TimeoutEvent event);
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.TimeoutEvent;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPProcessorObserver processorObserver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
processorObserver.addTimeoutProcessor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(TimeoutEvent event) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
CallIdHeader callIdHeader = event.getClientTransaction().getDialog().getCallId();
|
||||||
|
String callId = callIdHeader.getCallId();
|
||||||
|
SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId);
|
||||||
|
SipSubscribe.EventResult<TimeoutEvent> timeoutEventEventResult = new SipSubscribe.EventResult<>(event);
|
||||||
|
errorSubscribe.response(timeoutEventEventResult);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理接收IPCamera发来的SIP协议请求消息
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:42:22
|
|
||||||
*/
|
|
||||||
public interface ISIPRequestProcessor {
|
|
||||||
|
|
||||||
public void process();
|
|
||||||
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request;
|
|
||||||
|
|
||||||
import javax.sip.PeerUnavailableException;
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
import javax.sip.SipFactory;
|
|
||||||
import javax.sip.SipProvider;
|
|
||||||
import javax.sip.TransactionAlreadyExistsException;
|
|
||||||
import javax.sip.TransactionUnavailableException;
|
|
||||||
import javax.sip.address.AddressFactory;
|
|
||||||
import javax.sip.header.HeaderFactory;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.MessageFactory;
|
|
||||||
import javax.sip.message.Request;
|
|
||||||
|
|
||||||
import gov.nist.javax.sip.SipStackImpl;
|
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
|
||||||
import gov.nist.javax.sip.stack.SIPServerTransaction;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理接收IPCamera发来的SIP协议请求消息
|
|
||||||
* @author: songww
|
|
||||||
* @date: 2020年5月3日 下午4:42:22
|
|
||||||
*/
|
|
||||||
public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcessor {
|
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SIPRequestAbstractProcessor.class);
|
|
||||||
|
|
||||||
protected RequestEvent evt;
|
|
||||||
|
|
||||||
private SipProvider tcpSipProvider;
|
|
||||||
|
|
||||||
private SipProvider udpSipProvider;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process() {
|
|
||||||
this.process(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void process(RequestEvent evt);
|
|
||||||
|
|
||||||
public ServerTransaction getServerTransaction(RequestEvent evt) {
|
|
||||||
Request request = evt.getRequest();
|
|
||||||
ServerTransaction serverTransaction = evt.getServerTransaction();
|
|
||||||
// 判断TCP还是UDP
|
|
||||||
boolean isTcp = false;
|
|
||||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
|
||||||
String transport = reqViaHeader.getTransport();
|
|
||||||
if (transport.equals("TCP")) {
|
|
||||||
isTcp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serverTransaction == null) {
|
|
||||||
try {
|
|
||||||
if (isTcp) {
|
|
||||||
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
|
|
||||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
|
||||||
if (serverTransaction == null) {
|
|
||||||
serverTransaction = tcpSipProvider.getNewServerTransaction(request);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
|
|
||||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
|
||||||
if (serverTransaction == null) {
|
|
||||||
serverTransaction = udpSipProvider.getNewServerTransaction(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (TransactionAlreadyExistsException e) {
|
|
||||||
logger.error(e.getMessage());
|
|
||||||
} catch (TransactionUnavailableException e) {
|
|
||||||
logger.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return serverTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressFactory getAddressFactory() {
|
|
||||||
try {
|
|
||||||
return SipFactory.getInstance().createAddressFactory();
|
|
||||||
} catch (PeerUnavailableException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HeaderFactory getHeaderFactory() {
|
|
||||||
try {
|
|
||||||
return SipFactory.getInstance().createHeaderFactory();
|
|
||||||
} catch (PeerUnavailableException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageFactory getMessageFactory() {
|
|
||||||
try {
|
|
||||||
return SipFactory.getInstance().createMessageFactory();
|
|
||||||
} catch (PeerUnavailableException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestEvent getRequestEvent() {
|
|
||||||
return evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRequestEvent(RequestEvent evt) {
|
|
||||||
this.evt = evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SipProvider getTcpSipProvider() {
|
|
||||||
return tcpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTcpSipProvider(SipProvider tcpSipProvider) {
|
|
||||||
this.tcpSipProvider = tcpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SipProvider getUdpSipProvider() {
|
|
||||||
return udpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUdpSipProvider(SipProvider udpSipProvider) {
|
|
||||||
this.udpSipProvider = udpSipProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:CANCEL请求处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:23
|
|
||||||
*/
|
|
||||||
public class CancelRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理CANCEL请求
|
|
||||||
*
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param transaction
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
// TODO 优先级99 Cancel Request消息实现,此消息一般为级联消息,上级给下级发送请求取消指令
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
|
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:暂不支持的消息请求处理器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午5:32:59
|
|
||||||
*/
|
|
||||||
public class OtherRequestProcessor extends SIPRequestAbstractProcessor {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(OtherRequestProcessor.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Title: process</p>
|
|
||||||
* <p>Description: </p>
|
|
||||||
* @param evt
|
|
||||||
* @param layer
|
|
||||||
* @param transaction
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void process(RequestEvent evt) {
|
|
||||||
logger.info("Unsupported the method: " + evt.getRequest().getMethod());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.response;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:处理接收IPCamera发来的SIP协议响应消息
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月3日 下午4:42:22
|
|
||||||
*/
|
|
||||||
public interface ISIPResponseProcessor {
|
|
||||||
|
|
||||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException;
|
|
||||||
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user