Merge remote-tracking branch 'origin/wvp-28181-2.0' into wvp-28181-2.0

This commit is contained in:
xiaoxie 2021-12-01 22:45:51 +08:00
commit 0765874086
192 changed files with 7403 additions and 18514 deletions

10
.github/ISSUE_TEMPLATE/-------.md vendored Normal file
View File

@ -0,0 +1,10 @@
---
name: "[ 新功能 ]"
about: 新功能
title: ''
labels: ''
assignees: ''
---

29
.github/ISSUE_TEMPLATE/--bug---.md vendored Normal file
View 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
View File

@ -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

View File

@ -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
View File

@ -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>

View File

@ -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)
); );

View File

@ -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;

View File

@ -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;
} }

View File

@ -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";
} }

View 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);
}
}
}

View File

@ -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) {

View File

@ -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
* *

View File

@ -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;

View File

@ -32,5 +32,7 @@ public class SipDeviceRunner implements CommandLineRunner {
for (String deviceId : onlineForAll) { for (String deviceId : onlineForAll) {
storager.online(deviceId); storager.online(deviceId);
} }
// TODO 查询在线设备那些开启了订阅为设备开启定时的目录订阅
} }
} }

View File

@ -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;
}
}

View File

@ -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;
}
} }

View File

@ -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;
}
}

View File

@ -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);
} }
} }

View File

@ -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) {
// 密码过期 // 密码过期

View File

@ -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)) {
// 增加其它无需回复的响应如101180等
} 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
}
} }

View File

@ -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
*/ */

View File

@ -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;
}
} }

View File

@ -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日
*/ */

View File

@ -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;
}
} }

View File

@ -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
*/ */

View File

@ -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
*/ */

View File

@ -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
*/ */

View File

@ -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();
} }

View File

@ -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());

View File

@ -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
*/ */

View File

@ -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
*/ */

View File

@ -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 离线取消订阅
} }
} }

View File

@ -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
*/ */

View File

@ -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 上线添加订阅
} }
} }

View File

@ -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);

View File

@ -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);//十五秒后再次发起注册
} }
} }

View File

@ -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
*/ */

View File

@ -0,0 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit;
import javax.sip.SipListener;
public interface ISIPProcessorObserver extends SipListener {
}

View File

@ -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;
}
}

View File

@ -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日 下午1532
*/
@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)) {
// 增加其它无需回复的响应如101180等
} 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();
}
}

View File

@ -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) {

View File

@ -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());
} }
} }

View File

@ -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() {

View File

@ -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);
} }

View File

@ -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
*/ */

View File

@ -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;
}
} }

View File

@ -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();
}
}
} }

View File

@ -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);

View File

@ -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日 1547
*/
public interface ISIPRequestProcessor {
void process(RequestEvent event);
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;
} }
} }

View File

@ -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;
}
} }

View File

@ -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消息实现此消息一般为级联消息上级给下级发送请求取消指令
}
}

View File

@ -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;
}
} }

View File

@ -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日 1028
*/ */
@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;
}
} }

View File

@ -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) {
} }

View File

@ -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;
}
} }

View File

@ -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请求

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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();
}
}
}

View File

@ -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) {
// 不会收到上级平台的心跳信息
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
// 不会收到上级平台的心跳信息
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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);
}

View File

@ -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 {
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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日 1640
*/ */
@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");

View File

@ -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();

View File

@ -0,0 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout;
import javax.sip.TimeoutEvent;
public interface ITimeoutProcessor {
void process(TimeoutEvent event);
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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消息实现此消息一般为级联消息上级给下级发送请求取消指令
}
}

View File

@ -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());
}
}

View File

@ -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