xiaoxie
3 years ago
192 changed files with 7401 additions and 18512 deletions
@ -0,0 +1,10 @@ |
|||||
|
--- |
||||
|
name: "[ 新功能 ]" |
||||
|
about: 新功能 |
||||
|
title: '' |
||||
|
labels: '' |
||||
|
assignees: '' |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
|
@ -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. 你做过哪些尝试 |
@ -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 |
||||
|
Binary file not shown.
@ -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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
@ -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; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,6 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit; |
||||
|
|
||||
|
import javax.sip.SipListener; |
||||
|
|
||||
|
public interface ISIPProcessorObserver extends SipListener { |
||||
|
} |
@ -1,243 +0,0 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit; |
|
||||
|
|
||||
import javax.sip.RequestEvent; |
|
||||
import javax.sip.ResponseEvent; |
|
||||
import javax.sip.SipProvider; |
|
||||
import javax.sip.header.CSeqHeader; |
|
||||
import javax.sip.message.Request; |
|
||||
import javax.sip.message.Response; |
|
||||
|
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
|
||||
import com.genersoft.iot.vmp.service.IDeviceAlarmService; |
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService; |
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; |
|
||||
import com.genersoft.iot.vmp.service.IPlayService; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.context.annotation.Lazy; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
import com.genersoft.iot.vmp.conf.SipConfig; |
|
||||
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler; |
|
||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.ISIPRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.AckRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.ByeRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.CancelRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.InviteRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.MessageRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.NotifyRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.OtherRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.impl.SubscribeRequestProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.ByeResponseProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.CancelResponseProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.InviteResponseProcessor; |
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.OtherResponseProcessor; |
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
|
||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory; |
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
|
||||
|
|
||||
/** |
|
||||
* @Description: SIP信令处理分配 |
|
||||
* @author: swwheihei |
|
||||
* @date: 2020年5月3日 下午4:24:37 |
|
||||
*/ |
|
||||
@Component |
|
||||
public class SIPProcessorFactory { |
|
||||
|
|
||||
// private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
|
|
||||
|
|
||||
@Autowired |
|
||||
private SipConfig sipConfig; |
|
||||
|
|
||||
@Autowired |
|
||||
private RegisterLogicHandler handler; |
|
||||
|
|
||||
@Autowired |
|
||||
private IVideoManagerStorager storager; |
|
||||
|
|
||||
@Autowired |
|
||||
private IRedisCatchStorage redisCatchStorage; |
|
||||
|
|
||||
@Autowired |
|
||||
private EventPublisher publisher; |
|
||||
|
|
||||
@Autowired |
|
||||
private SIPCommander cmder; |
|
||||
|
|
||||
@Autowired |
|
||||
private SIPCommanderFroPlatform cmderFroPlatform; |
|
||||
|
|
||||
@Autowired |
|
||||
private IDeviceAlarmService deviceAlarmService; |
|
||||
|
|
||||
@Autowired |
|
||||
private RedisUtil redis; |
|
||||
|
|
||||
@Autowired |
|
||||
private DeferredResultHolder deferredResultHolder; |
|
||||
|
|
||||
@Autowired |
|
||||
private DeviceOffLineDetector offLineDetector; |
|
||||
|
|
||||
@Autowired |
|
||||
private InviteResponseProcessor inviteResponseProcessor; |
|
||||
|
|
||||
@Autowired |
|
||||
private ByeResponseProcessor byeResponseProcessor; |
|
||||
|
|
||||
@Autowired |
|
||||
private CancelResponseProcessor cancelResponseProcessor; |
|
||||
|
|
||||
@Autowired |
|
||||
@Lazy |
|
||||
private RegisterResponseProcessor registerResponseProcessor; |
|
||||
|
|
||||
|
|
||||
@Autowired |
|
||||
private OtherResponseProcessor otherResponseProcessor; |
|
||||
|
|
||||
@Autowired |
|
||||
private IPlayService playService; |
|
||||
|
|
||||
@Autowired |
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory; |
|
||||
|
|
||||
@Autowired |
|
||||
private IMediaServerService mediaServerService; |
|
||||
|
|
||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
|
||||
private SipProvider tcpSipProvider; |
|
||||
|
|
||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
|
||||
private SipProvider udpSipProvider; |
|
||||
|
|
||||
public ISIPRequestProcessor createRequestProcessor(RequestEvent evt) { |
|
||||
Request request = evt.getRequest(); |
|
||||
String method = request.getMethod(); |
|
||||
// logger.info("接收到消息:"+request.getMethod());
|
|
||||
// sipSubscribe.getSubscribe(evt.getServerTransaction().getBranchId()).response(evt);
|
|
||||
if (Request.INVITE.equals(method)) { |
|
||||
InviteRequestProcessor processor = new InviteRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
processor.setTcpSipProvider(getTcpSipProvider()); |
|
||||
processor.setUdpSipProvider(getUdpSipProvider()); |
|
||||
|
|
||||
processor.setCmder(cmder); |
|
||||
processor.setCmderFroPlatform(cmderFroPlatform); |
|
||||
processor.setPlayService(playService); |
|
||||
processor.setStorager(storager); |
|
||||
processor.setRedisCatchStorage(redisCatchStorage); |
|
||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory); |
|
||||
processor.setMediaServerService(mediaServerService); |
|
||||
return processor; |
|
||||
} else if (Request.REGISTER.equals(method)) { |
|
||||
RegisterRequestProcessor processor = new RegisterRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
processor.setTcpSipProvider(getTcpSipProvider()); |
|
||||
processor.setUdpSipProvider(getUdpSipProvider()); |
|
||||
processor.setHandler(handler); |
|
||||
processor.setPublisher(publisher); |
|
||||
processor.setSipConfig(sipConfig); |
|
||||
processor.setVideoManagerStorager(storager); |
|
||||
return processor; |
|
||||
} else if (Request.SUBSCRIBE.equals(method)) { |
|
||||
SubscribeRequestProcessor processor = new SubscribeRequestProcessor(); |
|
||||
processor.setTcpSipProvider(getTcpSipProvider()); |
|
||||
processor.setUdpSipProvider(getUdpSipProvider()); |
|
||||
processor.setRequestEvent(evt); |
|
||||
return processor; |
|
||||
} else if (Request.ACK.equals(method)) { |
|
||||
AckRequestProcessor processor = new AckRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
processor.setRedisCatchStorage(redisCatchStorage); |
|
||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory); |
|
||||
processor.setMediaServerService(mediaServerService); |
|
||||
return processor; |
|
||||
} else if (Request.BYE.equals(method)) { |
|
||||
ByeRequestProcessor processor = new ByeRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
processor.setRedisCatchStorage(redisCatchStorage); |
|
||||
processor.setStorager(storager); |
|
||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory); |
|
||||
processor.setSIPCommander(cmder); |
|
||||
processor.setMediaServerService(mediaServerService); |
|
||||
return processor; |
|
||||
} else if (Request.CANCEL.equals(method)) { |
|
||||
CancelRequestProcessor processor = new CancelRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
return processor; |
|
||||
} else if (Request.MESSAGE.equals(method)) { |
|
||||
MessageRequestProcessor processor = new MessageRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
processor.setTcpSipProvider(getTcpSipProvider()); |
|
||||
processor.setUdpSipProvider(getUdpSipProvider()); |
|
||||
processor.setPublisher(publisher); |
|
||||
processor.setRedis(redis); |
|
||||
processor.setDeferredResultHolder(deferredResultHolder); |
|
||||
processor.setOffLineDetector(offLineDetector); |
|
||||
processor.setCmder(cmder); |
|
||||
processor.setCmderFroPlatform(cmderFroPlatform); |
|
||||
processor.setDeviceAlarmService(deviceAlarmService); |
|
||||
processor.setStorager(storager); |
|
||||
processor.setRedisCatchStorage(redisCatchStorage); |
|
||||
return processor; |
|
||||
} else if (Request.NOTIFY.equalsIgnoreCase(method)) { |
|
||||
NotifyRequestProcessor processor = new NotifyRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
processor.setTcpSipProvider(getTcpSipProvider()); |
|
||||
processor.setUdpSipProvider(getUdpSipProvider()); |
|
||||
processor.setPublisher(publisher); |
|
||||
processor.setRedis(redis); |
|
||||
processor.setDeferredResultHolder(deferredResultHolder); |
|
||||
processor.setOffLineDetector(offLineDetector); |
|
||||
processor.setCmder(cmder); |
|
||||
processor.setStorager(storager); |
|
||||
processor.setRedisCatchStorage(redisCatchStorage); |
|
||||
return processor; |
|
||||
} else { |
|
||||
OtherRequestProcessor processor = new OtherRequestProcessor(); |
|
||||
processor.setRequestEvent(evt); |
|
||||
return processor; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) { |
|
||||
|
|
||||
Response response = evt.getResponse(); |
|
||||
CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
|
||||
String method = cseqHeader.getMethod(); |
|
||||
if(Request.INVITE.equals(method)){ |
|
||||
return inviteResponseProcessor; |
|
||||
} else if (Request.BYE.equals(method)) { |
|
||||
return byeResponseProcessor; |
|
||||
} else if (Request.CANCEL.equals(method)) { |
|
||||
return cancelResponseProcessor; |
|
||||
}else if (Request.REGISTER.equals(method)) { |
|
||||
return registerResponseProcessor; |
|
||||
} else { |
|
||||
return otherResponseProcessor; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private SipProvider getTcpSipProvider() { |
|
||||
if (tcpSipProvider == null) { |
|
||||
tcpSipProvider = (SipProvider) SpringBeanFactory.getBean("tcpSipProvider"); |
|
||||
} |
|
||||
return tcpSipProvider; |
|
||||
} |
|
||||
|
|
||||
private SipProvider getUdpSipProvider() { |
|
||||
if (udpSipProvider == null) { |
|
||||
udpSipProvider = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); |
|
||||
} |
|
||||
return udpSipProvider; |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -0,0 +1,162 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
import org.springframework.scheduling.annotation.Async; |
||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.*; |
||||
|
import javax.sip.header.CSeqHeader; |
||||
|
import javax.sip.header.CallIdHeader; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.util.Map; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
|
||||
|
/** |
||||
|
* @description: SIP信令处理类观察者 |
||||
|
* @author: panlinlin |
||||
|
* @date: 2021年11月5日 下午15:32 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class SIPProcessorObserver implements ISIPProcessorObserver { |
||||
|
|
||||
|
private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class); |
||||
|
|
||||
|
private static Map<String, ISIPRequestProcessor> requestProcessorMap = new ConcurrentHashMap<>(); |
||||
|
private static Map<String, ISIPResponseProcessor> responseProcessorMap = new ConcurrentHashMap<>(); |
||||
|
private static ITimeoutProcessor timeoutProcessor; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipSubscribe sipSubscribe; |
||||
|
|
||||
|
// @Autowired
|
||||
|
// @Qualifier(value = "taskExecutor")
|
||||
|
// private ThreadPoolTaskExecutor poolTaskExecutor;
|
||||
|
|
||||
|
/** |
||||
|
* 添加 request订阅 |
||||
|
* @param method 方法名 |
||||
|
* @param processor 处理程序 |
||||
|
*/ |
||||
|
public void addRequestProcessor(String method, ISIPRequestProcessor processor) { |
||||
|
requestProcessorMap.put(method, processor); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加 response订阅 |
||||
|
* @param method 方法名 |
||||
|
* @param processor 处理程序 |
||||
|
*/ |
||||
|
public void addResponseProcessor(String method, ISIPResponseProcessor processor) { |
||||
|
responseProcessorMap.put(method, processor); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加 超时事件订阅 |
||||
|
* @param processor 处理程序 |
||||
|
*/ |
||||
|
public void addTimeoutProcessor(ITimeoutProcessor processor) { |
||||
|
this.timeoutProcessor = processor; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 分发RequestEvent事件 |
||||
|
* @param requestEvent RequestEvent事件 |
||||
|
*/ |
||||
|
@Override |
||||
|
@Async |
||||
|
public void processRequest(RequestEvent requestEvent) { |
||||
|
String method = requestEvent.getRequest().getMethod(); |
||||
|
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); |
||||
|
if (sipRequestProcessor == null) { |
||||
|
logger.warn("不支持方法{}的request", method); |
||||
|
return; |
||||
|
} |
||||
|
requestProcessorMap.get(method).process(requestEvent); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 分发ResponseEvent事件 |
||||
|
* @param responseEvent responseEvent事件 |
||||
|
*/ |
||||
|
@Override |
||||
|
@Async |
||||
|
public void processResponse(ResponseEvent responseEvent) { |
||||
|
logger.debug(responseEvent.getResponse().toString()); |
||||
|
Response response = responseEvent.getResponse(); |
||||
|
logger.debug(responseEvent.getResponse().toString()); |
||||
|
int status = response.getStatusCode(); |
||||
|
if (((status >= 200) && (status < 300)) || status == 401) { // Success!
|
||||
|
// ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
|
||||
|
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); |
||||
|
String method = cseqHeader.getMethod(); |
||||
|
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method); |
||||
|
if (sipRequestProcessor != null) { |
||||
|
sipRequestProcessor.process(responseEvent); |
||||
|
} |
||||
|
if (responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) { |
||||
|
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); |
||||
|
if (callIdHeader != null) { |
||||
|
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); |
||||
|
if (subscribe != null) { |
||||
|
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); |
||||
|
subscribe.response(eventResult); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} else if ((status >= 100) && (status < 200)) { |
||||
|
// 增加其它无需回复的响应,如101、180等
|
||||
|
} else { |
||||
|
logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); |
||||
|
if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) { |
||||
|
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); |
||||
|
if (callIdHeader != null) { |
||||
|
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); |
||||
|
if (subscribe != null) { |
||||
|
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); |
||||
|
subscribe.response(eventResult); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if (responseEvent.getDialog() != null) { |
||||
|
responseEvent.getDialog().delete(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 向超时订阅发送消息 |
||||
|
* @param timeoutEvent timeoutEvent事件 |
||||
|
*/ |
||||
|
@Override |
||||
|
public void processTimeout(TimeoutEvent timeoutEvent) { |
||||
|
if(timeoutProcessor != null) { |
||||
|
timeoutProcessor.process(timeoutEvent); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void processIOException(IOExceptionEvent exceptionEvent) { |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { |
||||
|
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
/** |
||||
|
* @description: 对SIP事件进行处理,包括request, response, timeout, ioException, transactionTerminated,dialogTerminated |
||||
|
* @author: panlinlin |
||||
|
* @date: 2021年11月5日 15:47 |
||||
|
*/ |
||||
|
public interface ISIPRequestProcessor { |
||||
|
|
||||
|
void process(RequestEvent event); |
||||
|
|
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request; |
||||
|
|
||||
|
import gov.nist.javax.sip.SipProviderImpl; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
|
||||
|
/** |
||||
|
* @description:处理接收IPCamera发来的SIP协议请求消息 |
||||
|
* @author: songww |
||||
|
* @date: 2020年5月3日 下午4:42:22 |
||||
|
*/ |
||||
|
public abstract class SIPRequestProcessorAbstract { |
||||
|
|
||||
|
|
||||
|
@Autowired |
||||
|
@Qualifier(value="tcpSipProvider") |
||||
|
private SipProviderImpl tcpSipProvider; |
||||
|
|
||||
|
@Autowired |
||||
|
@Qualifier(value="udpSipProvider") |
||||
|
private SipProviderImpl udpSipProvider; |
||||
|
|
||||
|
} |
@ -0,0 +1,179 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request; |
||||
|
|
||||
|
import gov.nist.javax.sip.SipProviderImpl; |
||||
|
import gov.nist.javax.sip.SipStackImpl; |
||||
|
import gov.nist.javax.sip.message.SIPRequest; |
||||
|
import gov.nist.javax.sip.stack.SIPServerTransaction; |
||||
|
import org.dom4j.Document; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.dom4j.io.SAXReader; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
|
||||
|
import javax.sip.*; |
||||
|
import javax.sip.address.Address; |
||||
|
import javax.sip.address.AddressFactory; |
||||
|
import javax.sip.address.SipURI; |
||||
|
import javax.sip.header.ContentTypeHeader; |
||||
|
import javax.sip.header.HeaderFactory; |
||||
|
import javax.sip.header.ViaHeader; |
||||
|
import javax.sip.message.MessageFactory; |
||||
|
import javax.sip.message.Request; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.io.ByteArrayInputStream; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
/** |
||||
|
* @description:处理接收IPCamera发来的SIP协议请求消息 |
||||
|
* @author: songww |
||||
|
* @date: 2020年5月3日 下午4:42:22 |
||||
|
*/ |
||||
|
public abstract class SIPRequestProcessorParent { |
||||
|
|
||||
|
private final static Logger logger = LoggerFactory.getLogger(SIPRequestProcessorParent.class); |
||||
|
|
||||
|
@Autowired |
||||
|
@Qualifier(value="tcpSipProvider") |
||||
|
private SipProviderImpl tcpSipProvider; |
||||
|
|
||||
|
@Autowired |
||||
|
@Qualifier(value="udpSipProvider") |
||||
|
private SipProviderImpl udpSipProvider; |
||||
|
|
||||
|
/** |
||||
|
* 根据 RequestEvent 获取 ServerTransaction |
||||
|
* @param evt |
||||
|
* @return |
||||
|
*/ |
||||
|
public ServerTransaction getServerTransaction(RequestEvent evt) { |
||||
|
Request request = evt.getRequest(); |
||||
|
ServerTransaction serverTransaction = evt.getServerTransaction(); |
||||
|
// 判断TCP还是UDP
|
||||
|
boolean isTcp = false; |
||||
|
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
||||
|
String transport = reqViaHeader.getTransport(); |
||||
|
if (transport.equals("TCP")) { |
||||
|
isTcp = true; |
||||
|
} |
||||
|
|
||||
|
if (serverTransaction == null) { |
||||
|
try { |
||||
|
if (isTcp) { |
||||
|
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack(); |
||||
|
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); |
||||
|
if (serverTransaction == null) { |
||||
|
serverTransaction = tcpSipProvider.getNewServerTransaction(request); |
||||
|
} |
||||
|
} else { |
||||
|
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack(); |
||||
|
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); |
||||
|
if (serverTransaction == null) { |
||||
|
serverTransaction = udpSipProvider.getNewServerTransaction(request); |
||||
|
} |
||||
|
} |
||||
|
} catch (TransactionAlreadyExistsException e) { |
||||
|
logger.error(e.getMessage()); |
||||
|
} catch (TransactionUnavailableException e) { |
||||
|
logger.error(e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
return serverTransaction; |
||||
|
} |
||||
|
|
||||
|
public AddressFactory getAddressFactory() { |
||||
|
try { |
||||
|
return SipFactory.getInstance().createAddressFactory(); |
||||
|
} catch (PeerUnavailableException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public HeaderFactory getHeaderFactory() { |
||||
|
try { |
||||
|
return SipFactory.getInstance().createHeaderFactory(); |
||||
|
} catch (PeerUnavailableException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public MessageFactory getMessageFactory() { |
||||
|
try { |
||||
|
return SipFactory.getInstance().createMessageFactory(); |
||||
|
} catch (PeerUnavailableException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/*** |
||||
|
* 回复状态码 |
||||
|
* 100 trying |
||||
|
* 200 OK |
||||
|
* 400 |
||||
|
* 404 |
||||
|
* @param evt |
||||
|
* @throws SipException |
||||
|
* @throws InvalidArgumentException |
||||
|
* @throws ParseException |
||||
|
*/ |
||||
|
public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { |
||||
|
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); |
||||
|
ServerTransaction serverTransaction = getServerTransaction(evt); |
||||
|
serverTransaction.sendResponse(response); |
||||
|
if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) { |
||||
|
|
||||
|
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException { |
||||
|
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); |
||||
|
response.setReasonPhrase(msg); |
||||
|
ServerTransaction serverTransaction = getServerTransaction(evt); |
||||
|
serverTransaction.sendResponse(response); |
||||
|
if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) { |
||||
|
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 回复带sdp的200 |
||||
|
* @param evt |
||||
|
* @param sdp |
||||
|
* @throws SipException |
||||
|
* @throws InvalidArgumentException |
||||
|
* @throws ParseException |
||||
|
*/ |
||||
|
public void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { |
||||
|
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); |
||||
|
SipFactory sipFactory = SipFactory.getInstance(); |
||||
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); |
||||
|
response.setContent(sdp, contentTypeHeader); |
||||
|
|
||||
|
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); |
||||
|
|
||||
|
Address concatAddress = sipFactory.createAddressFactory().createAddress( |
||||
|
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() |
||||
|
)); |
||||
|
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); |
||||
|
getServerTransaction(evt).sendResponse(response); |
||||
|
} |
||||
|
|
||||
|
public Element getRootElement(RequestEvent evt) throws DocumentException { |
||||
|
return getRootElement(evt, "gb2312"); |
||||
|
} |
||||
|
public Element getRootElement(RequestEvent evt, String charset) throws DocumentException { |
||||
|
if (charset == null) charset = "gb2312"; |
||||
|
Request request = evt.getRequest(); |
||||
|
SAXReader reader = new SAXReader(); |
||||
|
reader.setEncoding(charset); |
||||
|
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); |
||||
|
return xml.getRootElement(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -1,142 +1,123 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl; |
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
||||
|
|
||||
import java.util.HashMap; |
import com.genersoft.iot.vmp.common.StreamInfo; |
||||
import java.util.Map; |
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
import javax.sip.*; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
||||
import javax.sip.address.SipURI; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
import javax.sip.header.FromHeader; |
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
||||
import javax.sip.header.HeaderAddress; |
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
||||
import javax.sip.header.ToHeader; |
import com.genersoft.iot.vmp.service.IMediaServerService; |
||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
||||
import com.genersoft.iot.vmp.common.StreamInfo; |
import org.slf4j.Logger; |
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
import org.slf4j.LoggerFactory; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
import org.springframework.beans.factory.InitializingBean; |
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
import org.springframework.stereotype.Component; |
||||
import com.genersoft.iot.vmp.service.IMediaServerService; |
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
import javax.sip.Dialog; |
||||
import org.slf4j.Logger; |
import javax.sip.DialogState; |
||||
import org.slf4j.LoggerFactory; |
import javax.sip.RequestEvent; |
||||
|
import javax.sip.address.SipURI; |
||||
/** |
import javax.sip.header.FromHeader; |
||||
* @Description:ACK请求处理器 |
import javax.sip.header.HeaderAddress; |
||||
* @author: swwheihei |
import javax.sip.header.ToHeader; |
||||
* @date: 2020年5月3日 下午5:31:45 |
import java.util.HashMap; |
||||
*/ |
import java.util.Map; |
||||
public class AckRequestProcessor extends SIPRequestAbstractProcessor { |
|
||||
|
/** |
||||
private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class); |
* SIP命令类型: ACK请求 |
||||
|
*/ |
||||
private IRedisCatchStorage redisCatchStorage; |
@Component |
||||
|
public class AckRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
private ZLMRTPServerFactory zlmrtpServerFactory; |
|
||||
|
private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class); |
||||
private IMediaServerService mediaServerService; |
private String method = "ACK"; |
||||
|
|
||||
/** |
@Autowired |
||||
* 处理 ACK请求 |
private SIPProcessorObserver sipProcessorObserver; |
||||
* |
|
||||
* @param evt |
@Override |
||||
*/ |
public void afterPropertiesSet() throws Exception { |
||||
@Override |
// 添加消息处理的订阅
|
||||
public void process(RequestEvent evt) { |
sipProcessorObserver.addRequestProcessor(method, this); |
||||
//Request request = evt.getRequest();
|
} |
||||
Dialog dialog = evt.getDialog(); |
|
||||
if (dialog == null) return; |
@Autowired |
||||
//DialogState state = dialog.getState();
|
private IRedisCatchStorage redisCatchStorage; |
||||
if (/*request.getMecodewwthod().equals(Request.INVITE) &&*/ dialog.getState()== DialogState.CONFIRMED) { |
|
||||
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); |
@Autowired |
||||
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); |
private ZLMRTPServerFactory zlmrtpServerFactory; |
||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); |
|
||||
String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; |
@Autowired |
||||
String deviceId = sendRtpItem.getDeviceId(); |
private IMediaServerService mediaServerService; |
||||
StreamInfo streamInfo = null; |
|
||||
if (deviceId == null) { |
|
||||
streamInfo = new StreamInfo(); |
/** |
||||
streamInfo.setApp(sendRtpItem.getApp()); |
* 处理 ACK请求 |
||||
streamInfo.setStreamId(sendRtpItem.getStreamId()); |
* |
||||
}else { |
* @param evt |
||||
streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
*/ |
||||
sendRtpItem.setStreamId(streamInfo.getStreamId()); |
@Override |
||||
streamInfo.setApp("rtp"); |
public void process(RequestEvent evt) { |
||||
} |
Dialog dialog = evt.getDialog(); |
||||
|
if (dialog == null) return; |
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
if (dialog.getState()== DialogState.CONFIRMED) { |
||||
logger.info(platformGbId); |
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); |
||||
logger.info(channelId); |
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); |
||||
Map<String, Object> param = new HashMap<>(); |
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); |
||||
param.put("vhost","__defaultVhost__"); |
String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; |
||||
param.put("app",streamInfo.getApp()); |
String deviceId = sendRtpItem.getDeviceId(); |
||||
param.put("stream",streamInfo.getStreamId()); |
StreamInfo streamInfo = null; |
||||
param.put("ssrc", sendRtpItem.getSsrc()); |
if (deviceId == null) { |
||||
param.put("dst_url",sendRtpItem.getIp()); |
streamInfo = new StreamInfo(); |
||||
param.put("dst_port", sendRtpItem.getPort()); |
streamInfo.setApp(sendRtpItem.getApp()); |
||||
param.put("is_udp", is_Udp); |
streamInfo.setStreamId(sendRtpItem.getStreamId()); |
||||
//param.put ("src_port", sendRtpItem.getLocalPort());
|
}else { |
||||
// 设备推流查询,成功后才能转推
|
streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
||||
boolean rtpPushed = false; |
sendRtpItem.setStreamId(streamInfo.getStreamId()); |
||||
long startTime = System.currentTimeMillis(); |
streamInfo.setApp("rtp"); |
||||
while (!rtpPushed) { |
} |
||||
try { |
|
||||
if (System.currentTimeMillis() - startTime < 30 * 1000) { |
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
logger.info(platformGbId); |
||||
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { |
logger.info(channelId); |
||||
rtpPushed = true; |
Map<String, Object> param = new HashMap<>(); |
||||
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", |
param.put("vhost","__defaultVhost__"); |
||||
streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); |
param.put("app",streamInfo.getApp()); |
||||
zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
param.put("stream",streamInfo.getStreamId()); |
||||
} else { |
param.put("ssrc", sendRtpItem.getSsrc()); |
||||
logger.info("等待设备推流[{}/{}].......", |
param.put("dst_url",sendRtpItem.getIp()); |
||||
streamInfo.getApp() ,streamInfo.getStreamId()); |
param.put("dst_port", sendRtpItem.getPort()); |
||||
Thread.sleep(1000); |
param.put("is_udp", is_Udp); |
||||
continue; |
//param.put ("src_port", sendRtpItem.getLocalPort());
|
||||
} |
// 设备推流查询,成功后才能转推
|
||||
} else { |
boolean rtpPushed = false; |
||||
rtpPushed = true; |
long startTime = System.currentTimeMillis(); |
||||
logger.info("设备推流[{}/{}]超时,终止向上级推流", |
while (!rtpPushed) { |
||||
streamInfo.getApp() ,streamInfo.getStreamId()); |
try { |
||||
} |
if (System.currentTimeMillis() - startTime < 30 * 1000) { |
||||
} catch (InterruptedException e) { |
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
||||
e.printStackTrace(); |
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { |
||||
} |
rtpPushed = true; |
||||
} |
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", |
||||
} |
streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); |
||||
// try {
|
zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
||||
// Request ackRequest = null;
|
} else { |
||||
// CSeq csReq = (CSeq) request.getHeader(CSeq.NAME);
|
logger.info("等待设备推流[{}/{}].......", |
||||
// ackRequest = dialog.createAck(csReq.getSeqNumber());
|
streamInfo.getApp() ,streamInfo.getStreamId()); |
||||
// dialog.sendAck(ackRequest);
|
Thread.sleep(1000); |
||||
// logger.info("send ack to callee:" + ackRequest.toString());
|
continue; |
||||
// } catch (SipException e) {
|
} |
||||
// e.printStackTrace();
|
} else { |
||||
// } catch (InvalidArgumentException e) {
|
rtpPushed = true; |
||||
// e.printStackTrace();
|
logger.info("设备推流[{}/{}]超时,终止向上级推流", |
||||
// }
|
streamInfo.getApp() ,streamInfo.getStreamId()); |
||||
|
} |
||||
} |
} catch (InterruptedException e) { |
||||
|
e.printStackTrace(); |
||||
public IRedisCatchStorage getRedisCatchStorage() { |
} |
||||
return redisCatchStorage; |
} |
||||
} |
} |
||||
|
} |
||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { |
} |
||||
this.redisCatchStorage = redisCatchStorage; |
|
||||
} |
|
||||
|
|
||||
public ZLMRTPServerFactory getZlmrtpServerFactory() { |
|
||||
return zlmrtpServerFactory; |
|
||||
} |
|
||||
|
|
||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { |
|
||||
this.zlmrtpServerFactory = zlmrtpServerFactory; |
|
||||
} |
|
||||
|
|
||||
public IMediaServerService getMediaServerService() { |
|
||||
return mediaServerService; |
|
||||
} |
|
||||
|
|
||||
public void setMediaServerService(IMediaServerService mediaServerService) { |
|
||||
this.mediaServerService = mediaServerService; |
|
||||
} |
|
||||
} |
|
@ -1,150 +1,114 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl; |
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
||||
|
|
||||
import javax.sip.*; |
import com.genersoft.iot.vmp.common.StreamInfo; |
||||
import javax.sip.address.SipURI; |
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
import javax.sip.header.FromHeader; |
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
||||
import javax.sip.header.HeaderAddress; |
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
import javax.sip.header.ToHeader; |
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
||||
import javax.sip.message.Response; |
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.common.StreamInfo; |
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
||||
import com.genersoft.iot.vmp.gb28181.bean.Device; |
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
import com.genersoft.iot.vmp.service.IMediaServerService; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
import org.slf4j.Logger; |
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
import org.slf4j.LoggerFactory; |
||||
import com.genersoft.iot.vmp.service.IMediaServerService; |
import org.springframework.beans.factory.InitializingBean; |
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
import org.springframework.stereotype.Component; |
||||
import org.slf4j.Logger; |
|
||||
import org.slf4j.LoggerFactory; |
import javax.sip.*; |
||||
|
import javax.sip.address.SipURI; |
||||
import java.text.ParseException; |
import javax.sip.header.FromHeader; |
||||
import java.util.HashMap; |
import javax.sip.header.HeaderAddress; |
||||
import java.util.Map; |
import javax.sip.header.ToHeader; |
||||
|
import javax.sip.message.Response; |
||||
/** |
import java.text.ParseException; |
||||
* @Description: BYE请求处理器 |
import java.util.HashMap; |
||||
* @author: lawrencehj |
import java.util.Map; |
||||
* @date: 2021年3月9日 |
|
||||
*/ |
/** |
||||
public class ByeRequestProcessor extends SIPRequestAbstractProcessor { |
* SIP命令类型: BYE请求 |
||||
|
*/ |
||||
private Logger logger = LoggerFactory.getLogger(ByeRequestProcessor.class); |
@Component |
||||
|
public class ByeRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
private ISIPCommander cmder; |
|
||||
|
private final Logger logger = LoggerFactory.getLogger(ByeRequestProcessor.class); |
||||
private IRedisCatchStorage redisCatchStorage; |
private final String method = "BYE"; |
||||
|
|
||||
private IVideoManagerStorager storager; |
@Autowired |
||||
|
private ISIPCommander cmder; |
||||
private ZLMRTPServerFactory zlmrtpServerFactory; |
|
||||
|
@Autowired |
||||
private IMediaServerService mediaServerService; |
private IRedisCatchStorage redisCatchStorage; |
||||
|
|
||||
/** |
@Autowired |
||||
* 处理BYE请求 |
private IVideoManagerStorager storager; |
||||
* @param evt |
|
||||
*/ |
@Autowired |
||||
@Override |
private ZLMRTPServerFactory zlmrtpServerFactory; |
||||
public void process(RequestEvent evt) { |
|
||||
try { |
@Autowired |
||||
responseAck(evt); |
private IMediaServerService mediaServerService; |
||||
Dialog dialog = evt.getDialog(); |
|
||||
if (dialog == null) return; |
@Autowired |
||||
if (dialog.getState().equals(DialogState.TERMINATED)) { |
private SIPProcessorObserver sipProcessorObserver; |
||||
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); |
|
||||
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); |
@Override |
||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); |
public void afterPropertiesSet() throws Exception { |
||||
logger.info("收到bye, [{}/{}]", platformGbId, channelId); |
// 添加消息处理的订阅
|
||||
if (sendRtpItem != null){ |
sipProcessorObserver.addRequestProcessor(method, this); |
||||
String streamId = sendRtpItem.getStreamId(); |
} |
||||
Map<String, Object> param = new HashMap<>(); |
|
||||
param.put("vhost","__defaultVhost__"); |
/** |
||||
param.put("app",sendRtpItem.getApp()); |
* 处理BYE请求 |
||||
param.put("stream",streamId); |
* @param evt |
||||
param.put("ssrc",sendRtpItem.getSsrc()); |
*/ |
||||
logger.info("停止向上级推流:" + streamId); |
@Override |
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
public void process(RequestEvent evt) { |
||||
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); |
try { |
||||
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); |
responseAck(evt, Response.OK); |
||||
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { |
Dialog dialog = evt.getDialog(); |
||||
logger.info(streamId + "无其它观看者,通知设备停止推流"); |
if (dialog == null) return; |
||||
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); |
if (dialog.getState().equals(DialogState.TERMINATED)) { |
||||
} |
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); |
||||
} |
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); |
||||
// 可能是设备主动停止
|
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); |
||||
Device device = storager.queryVideoDeviceByChannelId(platformGbId); |
logger.info("收到bye, [{}/{}]", platformGbId, channelId); |
||||
if (device != null) { |
if (sendRtpItem != null){ |
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); |
String streamId = sendRtpItem.getStreamId(); |
||||
if (streamInfo != null) { |
Map<String, Object> param = new HashMap<>(); |
||||
redisCatchStorage.stopPlay(streamInfo); |
param.put("vhost","__defaultVhost__"); |
||||
} |
param.put("app",sendRtpItem.getApp()); |
||||
storager.stopPlay(device.getDeviceId(), channelId); |
param.put("stream",streamId); |
||||
mediaServerService.closeRTPServer(device, channelId); |
param.put("ssrc",sendRtpItem.getSsrc()); |
||||
} |
logger.info("停止向上级推流:" + streamId); |
||||
} |
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
||||
} catch (SipException e) { |
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); |
||||
e.printStackTrace(); |
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); |
||||
} catch (InvalidArgumentException e) { |
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { |
||||
e.printStackTrace(); |
logger.info(streamId + "无其它观看者,通知设备停止推流"); |
||||
} catch (ParseException e) { |
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); |
||||
e.printStackTrace(); |
} |
||||
} |
} |
||||
} |
// 可能是设备主动停止
|
||||
|
Device device = storager.queryVideoDeviceByChannelId(platformGbId); |
||||
/*** |
if (device != null) { |
||||
* 回复200 OK |
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); |
||||
* @param evt |
if (streamInfo != null) { |
||||
* @throws SipException |
redisCatchStorage.stopPlay(streamInfo); |
||||
* @throws InvalidArgumentException |
} |
||||
* @throws ParseException |
storager.stopPlay(device.getDeviceId(), channelId); |
||||
*/ |
mediaServerService.closeRTPServer(device, channelId); |
||||
private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { |
} |
||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); |
} |
||||
ServerTransaction serverTransaction = getServerTransaction(evt); |
} catch (SipException e) { |
||||
serverTransaction.sendResponse(response); |
e.printStackTrace(); |
||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
} catch (InvalidArgumentException e) { |
||||
} |
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
public IRedisCatchStorage getRedisCatchStorage() { |
e.printStackTrace(); |
||||
return redisCatchStorage; |
} |
||||
} |
} |
||||
|
} |
||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { |
|
||||
this.redisCatchStorage = redisCatchStorage; |
|
||||
} |
|
||||
|
|
||||
public ZLMRTPServerFactory getZlmrtpServerFactory() { |
|
||||
return zlmrtpServerFactory; |
|
||||
} |
|
||||
|
|
||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { |
|
||||
this.zlmrtpServerFactory = zlmrtpServerFactory; |
|
||||
} |
|
||||
|
|
||||
public ISIPCommander getSIPCommander() { |
|
||||
return cmder; |
|
||||
} |
|
||||
|
|
||||
public void setSIPCommander(ISIPCommander cmder) { |
|
||||
this.cmder = cmder; |
|
||||
} |
|
||||
|
|
||||
public IMediaServerService getMediaServerService() { |
|
||||
return mediaServerService; |
|
||||
} |
|
||||
|
|
||||
public void setMediaServerService(IMediaServerService mediaServerService) { |
|
||||
this.mediaServerService = mediaServerService; |
|
||||
} |
|
||||
|
|
||||
public IVideoManagerStorager getStorager() { |
|
||||
return storager; |
|
||||
} |
|
||||
|
|
||||
public void setStorager(IVideoManagerStorager storager) { |
|
||||
this.storager = storager; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,40 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
/** |
||||
|
* SIP命令类型: CANCEL请求 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class CancelRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
|
|
||||
|
private String method = "CANCEL"; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPProcessorObserver sipProcessorObserver; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
// 添加消息处理的订阅
|
||||
|
sipProcessorObserver.addRequestProcessor(method, this); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 处理CANCEL请求 |
||||
|
* |
||||
|
* @param evt 事件 |
||||
|
*/ |
||||
|
@Override |
||||
|
public void process(RequestEvent evt) { |
||||
|
// TODO 优先级99 Cancel Request消息实现,此消息一般为级联消息,上级给下级发送请求取消指令
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -1,478 +1,395 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl; |
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
||||
|
|
||||
import javax.sdp.*; |
import com.genersoft.iot.vmp.gb28181.bean.*; |
||||
import javax.sip.*; |
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
import javax.sip.address.Address; |
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
||||
import javax.sip.address.SipURI; |
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
import javax.sip.header.*; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
||||
import javax.sip.message.Request; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
import javax.sip.message.Response; |
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
||||
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
||||
import com.genersoft.iot.vmp.gb28181.bean.*; |
import com.genersoft.iot.vmp.service.IMediaServerService; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
import com.genersoft.iot.vmp.service.IPlayService; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
import gov.nist.javax.sip.address.AddressImpl; |
||||
import com.genersoft.iot.vmp.service.IMediaServerService; |
import gov.nist.javax.sip.address.SipUri; |
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
import org.slf4j.Logger; |
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
import org.slf4j.LoggerFactory; |
||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
import org.springframework.beans.factory.InitializingBean; |
||||
import com.genersoft.iot.vmp.service.IPlayService; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import gov.nist.javax.sip.address.AddressImpl; |
import org.springframework.stereotype.Component; |
||||
import gov.nist.javax.sip.address.SipUri; |
|
||||
import org.slf4j.Logger; |
import javax.sdp.*; |
||||
import org.slf4j.LoggerFactory; |
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
import java.text.ParseException; |
import javax.sip.ServerTransaction; |
||||
import java.util.Vector; |
import javax.sip.SipException; |
||||
|
import javax.sip.address.SipURI; |
||||
/** |
import javax.sip.header.FromHeader; |
||||
* @Description:处理INVITE请求 |
import javax.sip.message.Request; |
||||
* @author: panll |
import javax.sip.message.Response; |
||||
* @date: 2021年1月14日 |
import java.text.ParseException; |
||||
*/ |
import java.util.Vector; |
||||
@SuppressWarnings("rawtypes") |
|
||||
public class InviteRequestProcessor extends SIPRequestAbstractProcessor { |
/** |
||||
|
* SIP命令类型: INVITE请求 |
||||
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); |
*/ |
||||
|
@SuppressWarnings("rawtypes") |
||||
private SIPCommanderFroPlatform cmderFroPlatform; |
@Component |
||||
|
public class InviteRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
private IVideoManagerStorager storager; |
|
||||
|
private final static Logger logger = LoggerFactory.getLogger(InviteRequestProcessor.class); |
||||
private IRedisCatchStorage redisCatchStorage; |
|
||||
|
private String method = "INVITE"; |
||||
private SIPCommander cmder; |
|
||||
|
@Autowired |
||||
private IPlayService playService; |
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory; |
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
private IMediaServerService mediaServerService; |
|
||||
|
@Autowired |
||||
public ZLMRTPServerFactory getZlmrtpServerFactory() { |
private IRedisCatchStorage redisCatchStorage; |
||||
return zlmrtpServerFactory; |
|
||||
} |
@Autowired |
||||
|
private SIPCommander cmder; |
||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { |
|
||||
this.zlmrtpServerFactory = zlmrtpServerFactory; |
@Autowired |
||||
} |
private IPlayService playService; |
||||
|
|
||||
/** |
@Autowired |
||||
* 处理invite请求 |
private ZLMRTPServerFactory zlmrtpServerFactory; |
||||
* |
|
||||
* @param evt |
@Autowired |
||||
* 请求消息 |
private IMediaServerService mediaServerService; |
||||
*/ |
|
||||
@Override |
@Autowired |
||||
public void process(RequestEvent evt) { |
private SIPProcessorObserver sipProcessorObserver; |
||||
// Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
|
|
||||
try { |
@Override |
||||
Request request = evt.getRequest(); |
public void afterPropertiesSet() throws Exception { |
||||
SipURI sipURI = (SipURI) request.getRequestURI(); |
// 添加消息处理的订阅
|
||||
String channelId = sipURI.getUser(); |
sipProcessorObserver.addRequestProcessor(method, this); |
||||
String requesterId = null; |
} |
||||
|
|
||||
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); |
/** |
||||
AddressImpl address = (AddressImpl) fromHeader.getAddress(); |
* 处理invite请求 |
||||
SipUri uri = (SipUri) address.getURI(); |
* |
||||
requesterId = uri.getUser(); |
* @param evt |
||||
|
* 请求消息 |
||||
if (requesterId == null || channelId == null) { |
*/ |
||||
logger.info("无法从FromHeader的Address中获取到平台id,返回400"); |
@Override |
||||
responseAck(evt, Response.BAD_REQUEST); // 参数不全, 发400,请求错误
|
public void process(RequestEvent evt) { |
||||
return; |
// Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
|
||||
} |
try { |
||||
|
Request request = evt.getRequest(); |
||||
// 查询请求方是否上级平台
|
SipURI sipURI = (SipURI) request.getRequestURI(); |
||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
String channelId = sipURI.getUser(); |
||||
if (platform != null) { |
String requesterId = null; |
||||
// 查询平台下是否有该通道
|
|
||||
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); |
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); |
||||
GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); |
AddressImpl address = (AddressImpl) fromHeader.getAddress(); |
||||
MediaServerItem mediaServerItem = null; |
SipUri uri = (SipUri) address.getURI(); |
||||
// 不是通道可能是直播流
|
requesterId = uri.getUser(); |
||||
if (channel != null && gbStream == null ) { |
|
||||
if (channel.getStatus() == 0) { |
if (requesterId == null || channelId == null) { |
||||
logger.info("通道离线,返回400"); |
logger.info("无法从FromHeader的Address中获取到平台id,返回400"); |
||||
responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); |
responseAck(evt, Response.BAD_REQUEST); // 参数不全, 发400,请求错误
|
||||
return; |
return; |
||||
} |
} |
||||
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
|
||||
}else if(channel == null && gbStream != null){ |
// 查询请求方是否上级平台
|
||||
String mediaServerId = gbStream.getMediaServerId(); |
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
||||
mediaServerItem = mediaServerService.getOne(mediaServerId); |
if (platform != null) { |
||||
if (mediaServerItem == null) { |
// 查询平台下是否有该通道
|
||||
logger.info("[ app={}, stream={} ]zlm找不到,返回410",gbStream.getApp(), gbStream.getStream()); |
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); |
||||
responseAck(evt, Response.GONE, "media server not found"); |
GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); |
||||
return; |
MediaServerItem mediaServerItem = null; |
||||
} |
// 不是通道可能是直播流
|
||||
Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); |
if (channel != null && gbStream == null ) { |
||||
if (!streamReady ) { |
if (channel.getStatus() == 0) { |
||||
logger.info("[ app={}, stream={} ]通道离线,返回400",gbStream.getApp(), gbStream.getStream()); |
logger.info("通道离线,返回400"); |
||||
responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); |
responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); |
||||
return; |
return; |
||||
} |
} |
||||
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
||||
}else { |
}else if(channel == null && gbStream != null){ |
||||
logger.info("通道不存在,返回404"); |
String mediaServerId = gbStream.getMediaServerId(); |
||||
responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
|
mediaServerItem = mediaServerService.getOne(mediaServerId); |
||||
return; |
if (mediaServerItem == null) { |
||||
} |
logger.info("[ app={}, stream={} ]找不到zlm {},返回410",gbStream.getApp(), gbStream.getStream(), mediaServerId); |
||||
// 解析sdp消息, 使用jainsip 自带的sdp解析方式
|
responseAck(evt, Response.GONE, "media server not found"); |
||||
String contentString = new String(request.getRawContent()); |
return; |
||||
|
} |
||||
// jainSip不支持y=字段, 移除移除以解析。
|
Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); |
||||
int ssrcIndex = contentString.indexOf("y="); |
if (!streamReady ) { |
||||
//ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
|
logger.info("[ app={}, stream={} ]通道离线,返回400",gbStream.getApp(), gbStream.getStream()); |
||||
String ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); |
||||
String substring = contentString.substring(0, contentString.indexOf("y=")); |
return; |
||||
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
} |
||||
|
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
||||
// 获取支持的格式
|
}else { |
||||
Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
logger.info("通道不存在,返回404"); |
||||
// 查看是否支持PS 负载96
|
responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
|
||||
//String ip = null;
|
return; |
||||
int port = -1; |
} |
||||
//boolean recvonly = false;
|
// 解析sdp消息, 使用jainsip 自带的sdp解析方式
|
||||
boolean mediaTransmissionTCP = false; |
String contentString = new String(request.getRawContent()); |
||||
Boolean tcpActive = null; |
|
||||
for (Object description : mediaDescriptions) { |
// jainSip不支持y=字段, 移除以解析。
|
||||
MediaDescription mediaDescription = (MediaDescription) description; |
int ssrcIndex = contentString.indexOf("y="); |
||||
Media media = mediaDescription.getMedia(); |
// 检查是否有y字段
|
||||
|
String ssrcDefault = "0000000000"; |
||||
Vector mediaFormats = media.getMediaFormats(false); |
String ssrc; |
||||
if (mediaFormats.contains("96")) { |
SessionDescription sdp; |
||||
port = media.getMediaPort(); |
if (ssrcIndex >= 0) { |
||||
//String mediaType = media.getMediaType();
|
//ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
|
||||
String protocol = media.getProtocol(); |
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
||||
|
String substring = contentString.substring(0, contentString.indexOf("y=")); |
||||
// 区分TCP发流还是udp, 当前默认udp
|
sdp = SdpFactory.getInstance().createSessionDescription(substring); |
||||
if ("TCP/RTP/AVP".equals(protocol)) { |
}else { |
||||
String setup = mediaDescription.getAttribute("setup"); |
ssrc = ssrcDefault; |
||||
if (setup != null) { |
sdp = SdpFactory.getInstance().createSessionDescription(contentString); |
||||
mediaTransmissionTCP = true; |
} |
||||
if ("active".equals(setup)) { |
|
||||
tcpActive = true; |
// 获取支持的格式
|
||||
} else if ("passive".equals(setup)) { |
Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
||||
tcpActive = false; |
// 查看是否支持PS 负载96
|
||||
} |
//String ip = null;
|
||||
} |
int port = -1; |
||||
} |
//boolean recvonly = false;
|
||||
break; |
boolean mediaTransmissionTCP = false; |
||||
} |
Boolean tcpActive = null; |
||||
} |
for (Object description : mediaDescriptions) { |
||||
if (port == -1) { |
MediaDescription mediaDescription = (MediaDescription) description; |
||||
logger.info("不支持的媒体格式,返回415"); |
Media media = mediaDescription.getMedia(); |
||||
// 回复不支持的格式
|
|
||||
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
|
Vector mediaFormats = media.getMediaFormats(false); |
||||
return; |
if (mediaFormats.contains("96")) { |
||||
} |
port = media.getMediaPort(); |
||||
String username = sdp.getOrigin().getUsername(); |
//String mediaType = media.getMediaType();
|
||||
String addressStr = sdp.getOrigin().getAddress(); |
String protocol = media.getProtocol(); |
||||
//String sessionName = sdp.getSessionName().getValue();
|
|
||||
logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc); |
// 区分TCP发流还是udp, 当前默认udp
|
||||
Device device = null; |
if ("TCP/RTP/AVP".equals(protocol)) { |
||||
// 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标
|
String setup = mediaDescription.getAttribute("setup"); |
||||
if (channel != null) { |
if (setup != null) { |
||||
device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); |
mediaTransmissionTCP = true; |
||||
if (device == null) { |
if ("active".equals(setup)) { |
||||
logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel); |
tcpActive = true; |
||||
responseAck(evt, Response.SERVER_INTERNAL_ERROR); |
} else if ("passive".equals(setup)) { |
||||
return; |
tcpActive = false; |
||||
} |
} |
||||
mediaServerItem = playService.getNewMediaServerItem(device); |
} |
||||
if (mediaServerItem == null) { |
} |
||||
logger.warn("未找到可用的zlm"); |
break; |
||||
responseAck(evt, Response.BUSY_HERE); |
} |
||||
return; |
} |
||||
} |
if (port == -1) { |
||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
logger.info("不支持的媒体格式,返回415"); |
||||
device.getDeviceId(), channelId, |
// 回复不支持的格式
|
||||
mediaTransmissionTCP); |
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
|
||||
if (tcpActive != null) { |
return; |
||||
sendRtpItem.setTcpActive(tcpActive); |
} |
||||
} |
String username = sdp.getOrigin().getUsername(); |
||||
if (sendRtpItem == null) { |
String addressStr = sdp.getOrigin().getAddress(); |
||||
logger.warn("服务器端口资源不足"); |
//String sessionName = sdp.getSessionName().getValue();
|
||||
responseAck(evt, Response.BUSY_HERE); |
logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc); |
||||
return; |
Device device = null; |
||||
} |
// 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标
|
||||
|
if (channel != null) { |
||||
// 写入redis, 超时时回复
|
device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); |
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
if (device == null) { |
||||
// 通知下级推流,
|
logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel); |
||||
PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{ |
responseAck(evt, Response.SERVER_INTERNAL_ERROR); |
||||
// 收到推流, 回复200OK, 等待ack
|
return; |
||||
// if (sendRtpItem == null) return;
|
} |
||||
sendRtpItem.setStatus(1); |
mediaServerItem = playService.getNewMediaServerItem(device); |
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
if (mediaServerItem == null) { |
||||
// TODO 添加对tcp的支持
|
logger.warn("未找到可用的zlm"); |
||||
|
responseAck(evt, Response.BUSY_HERE); |
||||
StringBuffer content = new StringBuffer(200); |
return; |
||||
content.append("v=0\r\n"); |
} |
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); |
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
||||
content.append("s=Play\r\n"); |
device.getDeviceId(), channelId, |
||||
content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); |
mediaTransmissionTCP); |
||||
content.append("t=0 0\r\n"); |
if (tcpActive != null) { |
||||
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); |
sendRtpItem.setTcpActive(tcpActive); |
||||
content.append("a=sendonly\r\n"); |
} |
||||
content.append("a=rtpmap:96 PS/90000\r\n"); |
if (sendRtpItem == null) { |
||||
content.append("y="+ ssrc + "\r\n"); |
logger.warn("服务器端口资源不足"); |
||||
content.append("f=\r\n"); |
responseAck(evt, Response.BUSY_HERE); |
||||
|
return; |
||||
try { |
} |
||||
responseAck(evt, content.toString()); |
|
||||
} catch (SipException e) { |
// 写入redis, 超时时回复
|
||||
e.printStackTrace(); |
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
||||
} catch (InvalidArgumentException e) { |
// 通知下级推流,
|
||||
e.printStackTrace(); |
PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{ |
||||
} catch (ParseException e) { |
// 收到推流, 回复200OK, 等待ack
|
||||
e.printStackTrace(); |
// if (sendRtpItem == null) return;
|
||||
} |
sendRtpItem.setStatus(1); |
||||
} ,((event) -> { |
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
||||
// 未知错误。直接转发设备点播的错误
|
// TODO 添加对tcp的支持
|
||||
Response response = null; |
|
||||
try { |
StringBuffer content = new StringBuffer(200); |
||||
response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest()); |
content.append("v=0\r\n"); |
||||
ServerTransaction serverTransaction = getServerTransaction(evt); |
content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); |
||||
serverTransaction.sendResponse(response); |
content.append("s=Play\r\n"); |
||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); |
||||
} catch (ParseException | SipException | InvalidArgumentException e) { |
content.append("t=0 0\r\n"); |
||||
e.printStackTrace(); |
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); |
||||
} |
content.append("a=sendonly\r\n"); |
||||
})); |
content.append("a=rtpmap:96 PS/90000\r\n"); |
||||
if (logger.isDebugEnabled()) { |
content.append("y="+ ssrc + "\r\n"); |
||||
logger.debug(playResult.getResult().toString()); |
content.append("f=\r\n"); |
||||
} |
|
||||
|
try { |
||||
}else if (gbStream != null) { |
responseAck(evt, content.toString()); |
||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
} catch (SipException e) { |
||||
gbStream.getApp(), gbStream.getStream(), channelId, |
e.printStackTrace(); |
||||
mediaTransmissionTCP); |
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
if (tcpActive != null) { |
} catch (ParseException e) { |
||||
sendRtpItem.setTcpActive(tcpActive); |
e.printStackTrace(); |
||||
} |
} |
||||
if (sendRtpItem == null) { |
} ,((event) -> { |
||||
logger.warn("服务器端口资源不足"); |
// 未知错误。直接转发设备点播的错误
|
||||
responseAck(evt, Response.BUSY_HERE); |
Response response = null; |
||||
return; |
try { |
||||
} |
response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); |
||||
|
ServerTransaction serverTransaction = getServerTransaction(evt); |
||||
// 写入redis, 超时时回复
|
serverTransaction.sendResponse(response); |
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
||||
|
} catch (ParseException | SipException | InvalidArgumentException e) { |
||||
sendRtpItem.setStatus(1); |
e.printStackTrace(); |
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
} |
||||
// TODO 添加对tcp的支持
|
})); |
||||
StringBuffer content = new StringBuffer(200); |
if (logger.isDebugEnabled()) { |
||||
content.append("v=0\r\n"); |
logger.debug(playResult.getResult().toString()); |
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
} |
||||
content.append("s=Play\r\n"); |
|
||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
}else if (gbStream != null) { |
||||
content.append("t=0 0\r\n"); |
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
||||
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); |
gbStream.getApp(), gbStream.getStream(), channelId, |
||||
content.append("a=sendonly\r\n"); |
mediaTransmissionTCP); |
||||
content.append("a=rtpmap:96 PS/90000\r\n"); |
|
||||
content.append("y="+ ssrc + "\r\n"); |
if (tcpActive != null) { |
||||
content.append("f=\r\n"); |
sendRtpItem.setTcpActive(tcpActive); |
||||
|
} |
||||
try { |
if (sendRtpItem == null) { |
||||
responseAck(evt, content.toString()); |
logger.warn("服务器端口资源不足"); |
||||
} catch (SipException e) { |
responseAck(evt, Response.BUSY_HERE); |
||||
e.printStackTrace(); |
return; |
||||
} catch (InvalidArgumentException e) { |
} |
||||
e.printStackTrace(); |
|
||||
} catch (ParseException e) { |
// 写入redis, 超时时回复
|
||||
e.printStackTrace(); |
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
||||
} |
|
||||
} |
sendRtpItem.setStatus(1); |
||||
|
redisCatchStorage.updateSendRTPSever(sendRtpItem); |
||||
} else { |
// TODO 添加对tcp的支持
|
||||
// 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
|
StringBuffer content = new StringBuffer(200); |
||||
Device device = storager.queryVideoDevice(requesterId); |
content.append("v=0\r\n"); |
||||
if (device != null) { |
content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
||||
logger.info("收到设备" + requesterId + "的语音广播Invite请求"); |
content.append("s=Play\r\n"); |
||||
responseAck(evt, Response.TRYING); |
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
||||
|
content.append("t=0 0\r\n"); |
||||
String contentString = new String(request.getRawContent()); |
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); |
||||
// jainSip不支持y=字段, 移除移除以解析。
|
content.append("a=sendonly\r\n"); |
||||
String substring = contentString; |
content.append("a=rtpmap:96 PS/90000\r\n"); |
||||
String ssrc = "0000000404"; |
content.append("y="+ ssrc + "\r\n"); |
||||
int ssrcIndex = contentString.indexOf("y="); |
content.append("f=\r\n"); |
||||
if (ssrcIndex > 0) { |
|
||||
substring = contentString.substring(0, ssrcIndex); |
try { |
||||
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
responseAck(evt, content.toString()); |
||||
} |
} catch (SipException e) { |
||||
ssrcIndex = substring.indexOf("f="); |
e.printStackTrace(); |
||||
if (ssrcIndex > 0) { |
} catch (InvalidArgumentException e) { |
||||
substring = contentString.substring(0, ssrcIndex); |
e.printStackTrace(); |
||||
} |
} catch (ParseException e) { |
||||
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
e.printStackTrace(); |
||||
|
} |
||||
// 获取支持的格式
|
} |
||||
Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
|
||||
// 查看是否支持PS 负载96
|
} else { |
||||
int port = -1; |
// 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
|
||||
//boolean recvonly = false;
|
Device device = storager.queryVideoDevice(requesterId); |
||||
boolean mediaTransmissionTCP = false; |
if (device != null) { |
||||
Boolean tcpActive = null; |
logger.info("收到设备" + requesterId + "的语音广播Invite请求"); |
||||
for (int i = 0; i < mediaDescriptions.size(); i++) { |
responseAck(evt, Response.TRYING); |
||||
MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); |
|
||||
Media media = mediaDescription.getMedia(); |
String contentString = new String(request.getRawContent()); |
||||
|
// jainSip不支持y=字段, 移除移除以解析。
|
||||
Vector mediaFormats = media.getMediaFormats(false); |
String substring = contentString; |
||||
if (mediaFormats.contains("8")) { |
String ssrc = "0000000404"; |
||||
port = media.getMediaPort(); |
int ssrcIndex = contentString.indexOf("y="); |
||||
String protocol = media.getProtocol(); |
if (ssrcIndex > 0) { |
||||
// 区分TCP发流还是udp, 当前默认udp
|
substring = contentString.substring(0, ssrcIndex); |
||||
if ("TCP/RTP/AVP".equals(protocol)) { |
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
||||
String setup = mediaDescription.getAttribute("setup"); |
} |
||||
if (setup != null) { |
ssrcIndex = substring.indexOf("f="); |
||||
mediaTransmissionTCP = true; |
if (ssrcIndex > 0) { |
||||
if ("active".equals(setup)) { |
substring = contentString.substring(0, ssrcIndex); |
||||
tcpActive = true; |
} |
||||
} else if ("passive".equals(setup)) { |
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
||||
tcpActive = false; |
|
||||
} |
// 获取支持的格式
|
||||
} |
Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
||||
} |
// 查看是否支持PS 负载96
|
||||
break; |
int port = -1; |
||||
} |
//boolean recvonly = false;
|
||||
} |
boolean mediaTransmissionTCP = false; |
||||
if (port == -1) { |
Boolean tcpActive = null; |
||||
logger.info("不支持的媒体格式,返回415"); |
for (int i = 0; i < mediaDescriptions.size(); i++) { |
||||
// 回复不支持的格式
|
MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); |
||||
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
|
Media media = mediaDescription.getMedia(); |
||||
return; |
|
||||
} |
Vector mediaFormats = media.getMediaFormats(false); |
||||
String username = sdp.getOrigin().getUsername(); |
if (mediaFormats.contains("8")) { |
||||
String addressStr = sdp.getOrigin().getAddress(); |
port = media.getMediaPort(); |
||||
logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); |
String protocol = media.getProtocol(); |
||||
|
// 区分TCP发流还是udp, 当前默认udp
|
||||
} else { |
if ("TCP/RTP/AVP".equals(protocol)) { |
||||
logger.warn("来自无效设备/平台的请求"); |
String setup = mediaDescription.getAttribute("setup"); |
||||
responseAck(evt, Response.BAD_REQUEST); |
if (setup != null) { |
||||
} |
mediaTransmissionTCP = true; |
||||
} |
if ("active".equals(setup)) { |
||||
|
tcpActive = true; |
||||
} catch (SipException | InvalidArgumentException | ParseException e) { |
} else if ("passive".equals(setup)) { |
||||
e.printStackTrace(); |
tcpActive = false; |
||||
logger.warn("sdp解析错误"); |
} |
||||
e.printStackTrace(); |
} |
||||
} catch (SdpParseException e) { |
} |
||||
e.printStackTrace(); |
break; |
||||
} catch (SdpException e) { |
} |
||||
e.printStackTrace(); |
} |
||||
} |
if (port == -1) { |
||||
} |
logger.info("不支持的媒体格式,返回415"); |
||||
|
// 回复不支持的格式
|
||||
|
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
|
||||
/*** |
return; |
||||
* 回复状态码 |
} |
||||
* 100 trying |
String username = sdp.getOrigin().getUsername(); |
||||
* 200 OK |
String addressStr = sdp.getOrigin().getAddress(); |
||||
* 400 |
logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); |
||||
* 404 |
|
||||
* @param evt |
} else { |
||||
* @throws SipException |
logger.warn("来自无效设备/平台的请求"); |
||||
* @throws InvalidArgumentException |
responseAck(evt, Response.BAD_REQUEST); |
||||
* @throws ParseException |
} |
||||
*/ |
} |
||||
private void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { |
|
||||
Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); |
} catch (SipException | InvalidArgumentException | ParseException e) { |
||||
ServerTransaction serverTransaction = getServerTransaction(evt); |
e.printStackTrace(); |
||||
serverTransaction.sendResponse(response); |
logger.warn("sdp解析错误"); |
||||
if (statusCode >= 200) { |
e.printStackTrace(); |
||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
} catch (SdpParseException e) { |
||||
} |
e.printStackTrace(); |
||||
} |
} catch (SdpException e) { |
||||
|
e.printStackTrace(); |
||||
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; |
|
||||
} |
|
||||
} |
|
File diff suppressed because it is too large
@ -1,201 +1,197 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl; |
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
||||
|
|
||||
import java.security.NoSuchAlgorithmException; |
import com.genersoft.iot.vmp.common.VideoManagerConstants; |
||||
import java.text.ParseException; |
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
import java.util.Calendar; |
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; |
||||
import java.util.Locale; |
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
import javax.sip.InvalidArgumentException; |
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; |
||||
import javax.sip.RequestEvent; |
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
import javax.sip.ServerTransaction; |
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
import javax.sip.SipException; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
||||
import javax.sip.header.AuthorizationHeader; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
import javax.sip.header.ContactHeader; |
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
import javax.sip.header.ExpiresHeader; |
import gov.nist.javax.sip.RequestEventExt; |
||||
import javax.sip.header.FromHeader; |
import gov.nist.javax.sip.address.AddressImpl; |
||||
import javax.sip.header.ViaHeader; |
import gov.nist.javax.sip.address.SipUri; |
||||
import javax.sip.message.Request; |
import gov.nist.javax.sip.header.Expires; |
||||
import javax.sip.message.Response; |
import gov.nist.javax.sip.header.SIPDateHeader; |
||||
|
import org.slf4j.Logger; |
||||
import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; |
import org.slf4j.LoggerFactory; |
||||
import gov.nist.javax.sip.RequestEventExt; |
import org.springframework.beans.factory.InitializingBean; |
||||
import gov.nist.javax.sip.header.SIPDateHeader; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.slf4j.Logger; |
import org.springframework.stereotype.Component; |
||||
import org.slf4j.LoggerFactory; |
import org.springframework.util.StringUtils; |
||||
import org.springframework.util.StringUtils; |
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants; |
import javax.sip.RequestEvent; |
||||
import com.genersoft.iot.vmp.conf.SipConfig; |
import javax.sip.ServerTransaction; |
||||
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; |
import javax.sip.SipException; |
||||
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler; |
import javax.sip.header.*; |
||||
import com.genersoft.iot.vmp.gb28181.bean.Device; |
import javax.sip.message.Request; |
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
import javax.sip.message.Response; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
import java.security.NoSuchAlgorithmException; |
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
import java.text.ParseException; |
||||
|
import java.util.Calendar; |
||||
import gov.nist.javax.sip.address.AddressImpl; |
import java.util.Locale; |
||||
import gov.nist.javax.sip.address.SipUri; |
|
||||
import gov.nist.javax.sip.header.Expires; |
/** |
||||
|
* SIP命令类型: REGISTER请求 |
||||
/** |
*/ |
||||
* @Description:收到注册请求 处理 |
@Component |
||||
* @author: swwheihei |
public class RegisterRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
* @date: 2020年5月3日 下午4:47:25 |
|
||||
*/ |
private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class); |
||||
public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { |
|
||||
|
public String method = "REGISTER"; |
||||
private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class); |
|
||||
|
@Autowired |
||||
private SipConfig sipConfig; |
private SipConfig sipConfig; |
||||
|
|
||||
private RegisterLogicHandler handler; |
@Autowired |
||||
|
private RegisterLogicHandler handler; |
||||
private IVideoManagerStorager storager; |
|
||||
|
@Autowired |
||||
private EventPublisher publisher; |
private IVideoManagerStorager storager; |
||||
|
|
||||
/** |
@Autowired |
||||
* 收到注册请求 处理 |
private EventPublisher publisher; |
||||
* @param evt |
|
||||
*/ |
@Autowired |
||||
@Override |
private SIPProcessorObserver sipProcessorObserver; |
||||
public void process(RequestEvent evt) { |
|
||||
try { |
@Override |
||||
RequestEventExt evtExt = (RequestEventExt)evt; |
public void afterPropertiesSet() throws Exception { |
||||
String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); |
// 添加消息处理的订阅
|
||||
logger.info("[{}] 收到注册请求,开始处理", requestAddress); |
sipProcessorObserver.addRequestProcessor(method, this); |
||||
Request request = evt.getRequest(); |
} |
||||
|
|
||||
Response response = null; |
/** |
||||
boolean passwordCorrect = false; |
* 收到注册请求 处理 |
||||
// 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
|
* @param evt |
||||
int registerFlag = 0; |
*/ |
||||
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); |
@Override |
||||
AddressImpl address = (AddressImpl) fromHeader.getAddress(); |
public void process(RequestEvent evt) { |
||||
SipUri uri = (SipUri) address.getURI(); |
try { |
||||
String deviceId = uri.getUser(); |
RequestEventExt evtExt = (RequestEventExt)evt; |
||||
Device device = storager.queryVideoDevice(deviceId); |
String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); |
||||
AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
logger.info("[{}] 收到注册请求,开始处理", requestAddress); |
||||
// 校验密码是否正确
|
Request request = evt.getRequest(); |
||||
if (authorhead != null) { |
|
||||
passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, |
Response response = null; |
||||
sipConfig.getPassword()); |
boolean passwordCorrect = false; |
||||
} |
// 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
|
||||
if (StringUtils.isEmpty(sipConfig.getPassword())){ |
int registerFlag = 0; |
||||
passwordCorrect = true; |
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); |
||||
} |
AddressImpl address = (AddressImpl) fromHeader.getAddress(); |
||||
|
SipUri uri = (SipUri) address.getURI(); |
||||
// 未携带授权头或者密码错误 回复401
|
String deviceId = uri.getUser(); |
||||
if (authorhead == null ) { |
Device device = storager.queryVideoDevice(deviceId); |
||||
|
AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
||||
logger.info("[{}] 未携带授权头 回复401", requestAddress); |
// 校验密码是否正确
|
||||
response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); |
if (authorhead != null) { |
||||
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); |
passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, |
||||
}else { |
sipConfig.getPassword()); |
||||
if (!passwordCorrect){ |
} |
||||
// 注册失败
|
if (StringUtils.isEmpty(sipConfig.getPassword())){ |
||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request); |
passwordCorrect = true; |
||||
response.setReasonPhrase("wrong password"); |
} |
||||
logger.info("[{}] 密码错误 回复403", requestAddress); |
|
||||
}else { |
// 未携带授权头或者密码错误 回复401
|
||||
// 携带授权头并且密码正确
|
if (authorhead == null ) { |
||||
response = getMessageFactory().createResponse(Response.OK, request); |
|
||||
// 添加date头
|
logger.info("[{}] 未携带授权头 回复401", requestAddress); |
||||
SIPDateHeader dateHeader = new SIPDateHeader(); |
response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); |
||||
// 使用自己修改的
|
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); |
||||
WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); |
}else { |
||||
dateHeader.setDate(wvpSipDate); |
if (!passwordCorrect){ |
||||
response.addHeader(dateHeader); |
// 注册失败
|
||||
|
response = getMessageFactory().createResponse(Response.FORBIDDEN, request); |
||||
ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); |
response.setReasonPhrase("wrong password"); |
||||
if (expiresHeader == null) { |
logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress); |
||||
response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); |
}else { |
||||
ServerTransaction serverTransaction = getServerTransaction(evt); |
// 携带授权头并且密码正确
|
||||
serverTransaction.sendResponse(response); |
response = getMessageFactory().createResponse(Response.OK, request); |
||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
// 添加date头
|
||||
return; |
SIPDateHeader dateHeader = new SIPDateHeader(); |
||||
} |
// 使用自己修改的
|
||||
// 添加Contact头
|
WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); |
||||
response.addHeader(request.getHeader(ContactHeader.NAME)); |
dateHeader.setDate(wvpSipDate); |
||||
// 添加Expires头
|
response.addHeader(dateHeader); |
||||
response.addHeader(request.getExpires()); |
|
||||
|
ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); |
||||
// 获取到通信地址等信息
|
if (expiresHeader == null) { |
||||
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); |
||||
String received = viaHeader.getReceived(); |
ServerTransaction serverTransaction = getServerTransaction(evt); |
||||
int rPort = viaHeader.getRPort(); |
serverTransaction.sendResponse(response); |
||||
// 解析本地地址替代
|
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
||||
if (StringUtils.isEmpty(received) || rPort == -1) { |
return; |
||||
received = viaHeader.getHost(); |
} |
||||
rPort = viaHeader.getPort(); |
// 添加Contact头
|
||||
} |
response.addHeader(request.getHeader(ContactHeader.NAME)); |
||||
//
|
// 添加Expires头
|
||||
|
response.addHeader(request.getExpires()); |
||||
if (device == null) { |
|
||||
device = new Device(); |
// 获取到通信地址等信息
|
||||
device.setStreamMode("UDP"); |
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
||||
device.setCharset("gb2312"); |
String received = viaHeader.getReceived(); |
||||
device.setDeviceId(deviceId); |
int rPort = viaHeader.getRPort(); |
||||
device.setFirsRegister(true); |
// 解析本地地址替代
|
||||
} |
if (StringUtils.isEmpty(received) || rPort == -1) { |
||||
device.setIp(received); |
received = viaHeader.getHost(); |
||||
device.setPort(rPort); |
rPort = viaHeader.getPort(); |
||||
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); |
} |
||||
// 注销成功
|
//
|
||||
if (expiresHeader.getExpires() == 0) { |
|
||||
registerFlag = 2; |
if (device == null) { |
||||
} |
device = new Device(); |
||||
// 注册成功
|
device.setStreamMode("UDP"); |
||||
else { |
device.setCharset("gb2312"); |
||||
device.setExpires(expiresHeader.getExpires()); |
device.setDeviceId(deviceId); |
||||
registerFlag = 1; |
device.setFirsRegister(true); |
||||
// 判断TCP还是UDP
|
} |
||||
boolean isTcp = false; |
device.setIp(received); |
||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
device.setPort(rPort); |
||||
String transport = reqViaHeader.getTransport(); |
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); |
||||
if (transport.equals("TCP")) { |
// 注销成功
|
||||
isTcp = true; |
if (expiresHeader.getExpires() == 0) { |
||||
} |
registerFlag = 2; |
||||
device.setTransport(isTcp ? "TCP" : "UDP"); |
} |
||||
} |
// 注册成功
|
||||
} |
else { |
||||
} |
device.setExpires(expiresHeader.getExpires()); |
||||
|
registerFlag = 1; |
||||
ServerTransaction serverTransaction = getServerTransaction(evt); |
// 判断TCP还是UDP
|
||||
serverTransaction.sendResponse(response); |
boolean isTcp = false; |
||||
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
||||
// 注册成功
|
String transport = reqViaHeader.getTransport(); |
||||
// 保存到redis
|
if (transport.equals("TCP")) { |
||||
// 下发catelog查询目录
|
isTcp = true; |
||||
if (registerFlag == 1 ) { |
} |
||||
logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress); |
device.setTransport(isTcp ? "TCP" : "UDP"); |
||||
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER); |
} |
||||
// 重新注册更新设备和通道,以免设备替换或更新后信息无法更新
|
} |
||||
handler.onRegister(device); |
} |
||||
} else if (registerFlag == 2) { |
|
||||
logger.info("[{}] 注销成功! deviceId:" + device.getDeviceId(), requestAddress); |
ServerTransaction serverTransaction = getServerTransaction(evt); |
||||
publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); |
serverTransaction.sendResponse(response); |
||||
} |
if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); |
||||
} catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { |
// 注册成功
|
||||
e.printStackTrace(); |
// 保存到redis
|
||||
} |
// 下发catelog查询目录
|
||||
|
if (registerFlag == 1 ) { |
||||
} |
logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress); |
||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER); |
||||
public void setSipConfig(SipConfig sipConfig) { |
// 重新注册更新设备和通道,以免设备替换或更新后信息无法更新
|
||||
this.sipConfig = sipConfig; |
handler.onRegister(device); |
||||
} |
} else if (registerFlag == 2) { |
||||
|
logger.info("[{}] 注销成功! deviceId:" + device.getDeviceId(), requestAddress); |
||||
public void setHandler(RegisterLogicHandler handler) { |
publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); |
||||
this.handler = handler; |
} |
||||
} |
} catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { |
||||
|
e.printStackTrace(); |
||||
public void setVideoManagerStorager(IVideoManagerStorager storager) { |
} |
||||
this.storager = storager; |
|
||||
} |
} |
||||
|
|
||||
public void setPublisher(EventPublisher publisher) { |
} |
||||
this.publisher = publisher; |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,62 +1,75 @@ |
|||||
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 javax.sip.InvalidArgumentException; |
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
import javax.sip.RequestEvent; |
import org.slf4j.Logger; |
||||
import javax.sip.ServerTransaction; |
import org.slf4j.LoggerFactory; |
||||
import javax.sip.SipException; |
import org.springframework.beans.factory.InitializingBean; |
||||
import javax.sip.header.ExpiresHeader; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import javax.sip.message.Request; |
import org.springframework.stereotype.Component; |
||||
import javax.sip.message.Response; |
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
import javax.sip.RequestEvent; |
||||
import org.slf4j.Logger; |
import javax.sip.ServerTransaction; |
||||
import org.slf4j.LoggerFactory; |
import javax.sip.SipException; |
||||
|
import javax.sip.header.ExpiresHeader; |
||||
/** |
import javax.sip.message.Request; |
||||
* @Description:SUBSCRIBE请求处理器 |
import javax.sip.message.Response; |
||||
* @author: swwheihei |
import java.text.ParseException; |
||||
* @date: 2020年5月3日 下午5:31:20 |
|
||||
*/ |
/** |
||||
public class SubscribeRequestProcessor extends SIPRequestAbstractProcessor { |
* SIP命令类型: SUBSCRIBE请求 |
||||
|
*/ |
||||
private Logger logger = LoggerFactory.getLogger(SubscribeRequestProcessor.class); |
@Component |
||||
|
public class SubscribeRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
/** |
|
||||
* 处理SUBSCRIBE请求 |
private Logger logger = LoggerFactory.getLogger(SubscribeRequestProcessor.class); |
||||
* |
private String method = "SUBSCRIBE"; |
||||
* @param evt |
|
||||
*/ |
@Autowired |
||||
@Override |
private SIPProcessorObserver sipProcessorObserver; |
||||
public void process(RequestEvent evt) { |
|
||||
Request request = evt.getRequest(); |
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
try { |
// 添加消息处理的订阅
|
||||
Response response = null; |
sipProcessorObserver.addRequestProcessor(method, this); |
||||
response = getMessageFactory().createResponse(200, request); |
} |
||||
if (response != null) { |
|
||||
ExpiresHeader expireHeader = getHeaderFactory().createExpiresHeader(30); |
/** |
||||
response.setExpires(expireHeader); |
* 处理SUBSCRIBE请求 |
||||
} |
* |
||||
logger.info("response : " + response.toString()); |
* @param evt |
||||
ServerTransaction transaction = getServerTransaction(evt); |
*/ |
||||
if (transaction != null) { |
@Override |
||||
transaction.sendResponse(response); |
public void process(RequestEvent evt) { |
||||
transaction.getDialog().delete(); |
Request request = evt.getRequest(); |
||||
transaction.terminate(); |
|
||||
} else { |
try { |
||||
logger.info("processRequest serverTransactionId is null."); |
Response response = null; |
||||
} |
response = getMessageFactory().createResponse(200, request); |
||||
|
if (response != null) { |
||||
} catch (ParseException e) { |
ExpiresHeader expireHeader = getHeaderFactory().createExpiresHeader(30); |
||||
e.printStackTrace(); |
response.setExpires(expireHeader); |
||||
} catch (SipException e) { |
} |
||||
e.printStackTrace(); |
logger.info("response : " + response.toString()); |
||||
} catch (InvalidArgumentException e) { |
ServerTransaction transaction = getServerTransaction(evt); |
||||
e.printStackTrace(); |
if (transaction != null) { |
||||
} |
transaction.sendResponse(response); |
||||
|
transaction.getDialog().delete(); |
||||
} |
transaction.terminate(); |
||||
|
} else { |
||||
} |
logger.info("processRequest serverTransactionId is null."); |
||||
|
} |
||||
|
|
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import org.dom4j.Element; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
public interface IMessageHandler { |
||||
|
/** |
||||
|
* 处理来自设备的信息 |
||||
|
* @param evt |
||||
|
* @param device |
||||
|
*/ |
||||
|
void handForDevice(RequestEvent evt, Device device, Element element); |
||||
|
|
||||
|
/** |
||||
|
* 处理来自平台的信息 |
||||
|
* @param evt |
||||
|
* @param parentPlatform |
||||
|
*/ |
||||
|
void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element); |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import org.dom4j.Element; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
import java.util.Map; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent implements IMessageHandler{ |
||||
|
|
||||
|
public Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
public void addHandler(String cmdType, IMessageHandler messageHandler) { |
||||
|
messageHandlerMap.put(cmdType, messageHandler); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
String cmd = getText(element, "CmdType"); |
||||
|
IMessageHandler messageHandler = messageHandlerMap.get(cmd); |
||||
|
if (messageHandler != null) { |
||||
|
messageHandler.handForDevice(evt, device, element); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
String cmd = getText(element, "CmdType"); |
||||
|
IMessageHandler messageHandler = messageHandlerMap.get(cmd); |
||||
|
if (messageHandler != null) { |
||||
|
messageHandler.handForPlatform(evt, parentPlatform, element); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,91 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
import java.util.Map; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
|
||||
|
@Component |
||||
|
public class MessageRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { |
||||
|
|
||||
|
private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); |
||||
|
|
||||
|
private final String method = "MESSAGE"; |
||||
|
|
||||
|
private static Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPProcessorObserver sipProcessorObserver; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storage; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
// 添加消息处理的订阅
|
||||
|
sipProcessorObserver.addRequestProcessor(method, this); |
||||
|
} |
||||
|
|
||||
|
public void addHandler(String name, IMessageHandler handler) { |
||||
|
messageHandlerMap.put(name, handler); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void process(RequestEvent evt) { |
||||
|
logger.debug("接收到消息:" + evt.getRequest()); |
||||
|
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); |
||||
|
// 查询设备是否存在
|
||||
|
Device device = storage.queryVideoDevice(deviceId); |
||||
|
// 查询上级平台是否存在
|
||||
|
ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); |
||||
|
try { |
||||
|
if (device == null && parentPlatform == null) { |
||||
|
// 不存在则回复404
|
||||
|
responseAck(evt, Response.NOT_FOUND, "device id not found"); |
||||
|
}else { |
||||
|
Element rootElement = getRootElement(evt); |
||||
|
String name = rootElement.getName(); |
||||
|
IMessageHandler messageHandler = messageHandlerMap.get(name); |
||||
|
if (messageHandler != null) { |
||||
|
if (device != null) { |
||||
|
messageHandler.handForDevice(evt, device, rootElement); |
||||
|
}else { // 由于上面已经判断都为null则直接返回,所以这里device和parentPlatform必有一个不为null
|
||||
|
messageHandler.handForPlatform(evt, parentPlatform, rootElement); |
||||
|
} |
||||
|
}else { |
||||
|
// 不支持的message
|
||||
|
// 不存在则回复415
|
||||
|
responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response"); |
||||
|
} |
||||
|
} |
||||
|
} catch (SipException e) { |
||||
|
logger.warn("SIP 回复错误", e); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
logger.warn("参数无效", e); |
||||
|
} catch (ParseException e) { |
||||
|
logger.warn("SIP回复时解析异常", e); |
||||
|
} catch (DocumentException e) { |
||||
|
logger.warn("解析XML消息内容异常", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
/** |
||||
|
* 命令类型: 控制命令 |
||||
|
* 命令类型: 设备控制: 远程启动, 录像控制(TODO), 报警布防/撤防命令(TODO), 报警复位命令(TODO), |
||||
|
* 强制关键帧命令(TODO), 拉框放大/缩小控制命令(TODO), 看守位控制(TODO), 报警复位(TODO) |
||||
|
* 命令类型: 设备配置: SVAC编码配置(TODO), 音频参数(TODO), SVAC解码配置(TODO) |
||||
|
*/ |
||||
|
@Component |
||||
|
public class ControlMessageHandler extends MessageHandlerAbstract implements InitializingBean { |
||||
|
|
||||
|
private final String messageType = "Control"; |
||||
|
|
||||
|
@Autowired |
||||
|
private MessageRequestProcessor messageRequestProcessor; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
messageRequestProcessor.addHandler(messageType, this); |
||||
|
} |
||||
|
} |
@ -0,0 +1,112 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.VManageBootstrap; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.ControlMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.utils.SpringBeanFactory; |
||||
|
import gov.nist.javax.sip.SipStackImpl; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import javax.sip.ListeningPoint; |
||||
|
import javax.sip.ObjectInUseException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipProvider; |
||||
|
import javax.sip.address.SipURI; |
||||
|
import javax.sip.header.HeaderAddress; |
||||
|
import javax.sip.header.ToHeader; |
||||
|
import java.util.Iterator; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceControlQueryMessageHandler.class); |
||||
|
private final String cmdType = "DeviceControl"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ControlMessageHandler controlMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommander cmder; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
controlMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
// 此处是上级发出的DeviceControl指令
|
||||
|
String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); |
||||
|
String channelId = getText(rootElement, "DeviceID"); |
||||
|
// 远程启动功能
|
||||
|
if (!StringUtils.isEmpty(getText(rootElement, "TeleBoot"))) { |
||||
|
if (parentPlatform.getServerGBId().equals(targetGBId)) { |
||||
|
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
|
||||
|
logger.info("执行远程启动本平台命令"); |
||||
|
cmderFroPlatform.unregister(parentPlatform, null, null); |
||||
|
|
||||
|
Thread restartThread = new Thread(new Runnable() { |
||||
|
@Override |
||||
|
public void run() { |
||||
|
try { |
||||
|
Thread.sleep(3000); |
||||
|
SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); |
||||
|
SipStackImpl stack = (SipStackImpl)up.getSipStack(); |
||||
|
stack.stop(); |
||||
|
Iterator listener = stack.getListeningPoints(); |
||||
|
while (listener.hasNext()) { |
||||
|
stack.deleteListeningPoint((ListeningPoint) listener.next()); |
||||
|
} |
||||
|
Iterator providers = stack.getSipProviders(); |
||||
|
while (providers.hasNext()) { |
||||
|
stack.deleteSipProvider((SipProvider) providers.next()); |
||||
|
} |
||||
|
VManageBootstrap.restart(); |
||||
|
} catch (InterruptedException ignored) { |
||||
|
} catch (ObjectInUseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
restartThread.setDaemon(false); |
||||
|
restartThread.start(); |
||||
|
} else { |
||||
|
// 远程启动指定设备
|
||||
|
} |
||||
|
} |
||||
|
// 云台/前端控制命令
|
||||
|
if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) { |
||||
|
String cmdString = getText(rootElement,"PTZCmd"); |
||||
|
Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); |
||||
|
cmder.fronEndCmd(deviceForPlatform, channelId, cmdString); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,25 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
/** |
||||
|
* 命令类型: 通知命令 |
||||
|
* 命令类型: 状态信息(心跳)报送, 报警通知, 媒体通知, 移动设备位置数据,语音广播通知(TODO), 设备预置位(TODO) |
||||
|
*/ |
||||
|
@Component |
||||
|
public class NotifyMessageHandler extends MessageHandlerAbstract implements InitializingBean { |
||||
|
|
||||
|
private final String messageType = "Notify"; |
||||
|
|
||||
|
@Autowired |
||||
|
private MessageRequestProcessor messageRequestProcessor; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
messageRequestProcessor.addHandler(messageType, this); |
||||
|
} |
||||
|
} |
@ -0,0 +1,114 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.UserSetup; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.*; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; |
||||
|
import com.genersoft.iot.vmp.service.IDeviceAlarmService; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.utils.GpsUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class); |
||||
|
private final String cmdType = "Alarm"; |
||||
|
|
||||
|
@Autowired |
||||
|
private NotifyMessageHandler notifyMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Autowired |
||||
|
private UserSetup userSetup; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private IDeviceAlarmService deviceAlarmService; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeviceOffLineDetector offLineDetector; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
notifyMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
Element deviceIdElement = rootElement.element("DeviceID"); |
||||
|
String channelId = deviceIdElement.getText().toString(); |
||||
|
DeviceAlarm deviceAlarm = new DeviceAlarm(); |
||||
|
deviceAlarm.setDeviceId(device.getDeviceId()); |
||||
|
deviceAlarm.setChannelId(channelId); |
||||
|
deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority")); |
||||
|
deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod")); |
||||
|
deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime")); |
||||
|
if (getText(rootElement, "AlarmDescription") == null) { |
||||
|
deviceAlarm.setAlarmDescription(""); |
||||
|
} else { |
||||
|
deviceAlarm.setAlarmDescription(getText(rootElement, "AlarmDescription")); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Longitude"))) { |
||||
|
deviceAlarm.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); |
||||
|
} else { |
||||
|
deviceAlarm.setLongitude(0.00); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Latitude"))) { |
||||
|
deviceAlarm.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); |
||||
|
} else { |
||||
|
deviceAlarm.setLatitude(0.00); |
||||
|
} |
||||
|
|
||||
|
if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) { |
||||
|
if ( deviceAlarm.getAlarmMethod().equals("4")) { |
||||
|
MobilePosition mobilePosition = new MobilePosition(); |
||||
|
mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); |
||||
|
mobilePosition.setTime(deviceAlarm.getAlarmTime()); |
||||
|
mobilePosition.setLongitude(deviceAlarm.getLongitude()); |
||||
|
mobilePosition.setLatitude(deviceAlarm.getLatitude()); |
||||
|
mobilePosition.setReportSource("GPS Alarm"); |
||||
|
BaiduPoint bp = new BaiduPoint(); |
||||
|
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); |
||||
|
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); |
||||
|
mobilePosition.setGeodeticSystem("BD-09"); |
||||
|
mobilePosition.setCnLng(bp.getBdLng()); |
||||
|
mobilePosition.setCnLat(bp.getBdLat()); |
||||
|
if (!userSetup.getSavePositionHistory()) { |
||||
|
storager.clearMobilePositionsByDeviceId(device.getDeviceId()); |
||||
|
} |
||||
|
storager.insertMobilePosition(mobilePosition); |
||||
|
} |
||||
|
} |
||||
|
logger.debug("存储报警信息、报警分类"); |
||||
|
// 存储报警信息、报警分类
|
||||
|
deviceAlarmService.add(deviceAlarm); |
||||
|
|
||||
|
if (offLineDetector.isOnline(device.getDeviceId())) { |
||||
|
publisher.deviceAlarmEventPublish(deviceAlarm); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,117 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.header.FromHeader; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Component |
||||
|
public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(CatalogNotifyMessageHandler.class); |
||||
|
private final String cmdType = "Catalog"; |
||||
|
|
||||
|
@Autowired |
||||
|
private NotifyMessageHandler notifyMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
notifyMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId(); |
||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
||||
|
try { |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
Element snElement = rootElement.element("SN"); |
||||
|
String sn = snElement.getText(); |
||||
|
// 准备回复通道信息
|
||||
|
List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); |
||||
|
// 查询关联的直播通道
|
||||
|
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); |
||||
|
int size = channelReduces.size() + gbStreams.size(); |
||||
|
// 回复级联的通道
|
||||
|
if (channelReduces.size() > 0) { |
||||
|
for (ChannelReduce channelReduce : channelReduces) { |
||||
|
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); |
||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
||||
|
} |
||||
|
} |
||||
|
// 回复直播的通道
|
||||
|
if (gbStreams.size() > 0) { |
||||
|
for (GbStream gbStream : gbStreams) { |
||||
|
DeviceChannel deviceChannel = new DeviceChannel(); |
||||
|
deviceChannel.setChannelId(gbStream.getGbId()); |
||||
|
deviceChannel.setName(gbStream.getName()); |
||||
|
deviceChannel.setLongitude(gbStream.getLongitude()); |
||||
|
deviceChannel.setLatitude(gbStream.getLatitude()); |
||||
|
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); |
||||
|
deviceChannel.setManufacture("wvp-pro"); |
||||
|
deviceChannel.setStatus(gbStream.isStatus()?1:0); |
||||
|
// deviceChannel.setParentId(parentPlatform.getDeviceGBId());
|
||||
|
deviceChannel.setRegisterWay(1); |
||||
|
deviceChannel.setCivilCode(config.getDomain()); |
||||
|
deviceChannel.setModel("live"); |
||||
|
deviceChannel.setOwner("wvp-pro"); |
||||
|
deviceChannel.setParental(0); |
||||
|
deviceChannel.setSecrecy("0"); |
||||
|
deviceChannel.setSecrecy("0"); |
||||
|
|
||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
||||
|
} |
||||
|
} |
||||
|
if (size == 0) { |
||||
|
// 回复无通道
|
||||
|
cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size); |
||||
|
} |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
@Component |
||||
|
public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class); |
||||
|
private final String cmdType = "Keepalive"; |
||||
|
|
||||
|
@Autowired |
||||
|
private NotifyMessageHandler notifyMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
notifyMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
// 检查设备是否存在并在线, 不在线则设置为在线
|
||||
|
try { |
||||
|
if (device != null ) { |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); |
||||
|
} |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
// 不会收到上级平台的心跳信息
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,74 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.common.StreamInfo; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(MediaStatusNotifyMessageHandler.class); |
||||
|
private final String cmdType = "MediaStatus"; |
||||
|
|
||||
|
@Autowired |
||||
|
private NotifyMessageHandler notifyMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommander cmder; |
||||
|
|
||||
|
@Autowired |
||||
|
private IRedisCatchStorage redisCatchStorage; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
notifyMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
|
||||
|
// 回复200 OK
|
||||
|
try { |
||||
|
responseAck(evt, Response.OK); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
String NotifyType =getText(rootElement, "NotifyType"); |
||||
|
if (NotifyType.equals("121")){ |
||||
|
logger.info("媒体播放完毕,通知关流"); |
||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*"); |
||||
|
if (streamInfo != null) { |
||||
|
redisCatchStorage.stopPlayback(streamInfo); |
||||
|
cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.UserSetup; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.utils.GpsUtil; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(MobilePositionNotifyMessageHandler.class); |
||||
|
private final String cmdType = "MobilePosition"; |
||||
|
|
||||
|
@Autowired |
||||
|
private NotifyMessageHandler notifyMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private UserSetup userSetup; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
notifyMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
|
||||
|
try { |
||||
|
rootElement = getRootElement(evt, device.getCharset()); |
||||
|
|
||||
|
MobilePosition mobilePosition = new MobilePosition(); |
||||
|
if (!StringUtils.isEmpty(device.getName())) { |
||||
|
mobilePosition.setDeviceName(device.getName()); |
||||
|
} |
||||
|
mobilePosition.setDeviceId(device.getDeviceId()); |
||||
|
mobilePosition.setChannelId(getText(rootElement, "DeviceID")); |
||||
|
mobilePosition.setTime(getText(rootElement, "Time")); |
||||
|
mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); |
||||
|
mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Speed"))) { |
||||
|
mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed"))); |
||||
|
} else { |
||||
|
mobilePosition.setSpeed(0.0); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Direction"))) { |
||||
|
mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction"))); |
||||
|
} else { |
||||
|
mobilePosition.setDirection(0.0); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) { |
||||
|
mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude"))); |
||||
|
} else { |
||||
|
mobilePosition.setAltitude(0.0); |
||||
|
} |
||||
|
mobilePosition.setReportSource("Mobile Position"); |
||||
|
BaiduPoint bp = new BaiduPoint(); |
||||
|
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); |
||||
|
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); |
||||
|
mobilePosition.setGeodeticSystem("BD-09"); |
||||
|
mobilePosition.setCnLng(bp.getBdLng()); |
||||
|
mobilePosition.setCnLat(bp.getBdLat()); |
||||
|
if (!userSetup.getSavePositionHistory()) { |
||||
|
storager.clearMobilePositionsByDeviceId(device.getDeviceId()); |
||||
|
} |
||||
|
storager.insertMobilePosition(mobilePosition); |
||||
|
//回复 200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,25 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
/** |
||||
|
* 命令类型: 查询指令 |
||||
|
* 命令类型: 设备状态, 设备目录信息, 设备信息, 文件目录检索(TODO), 报警(TODO), 设备配置(TODO), 设备预置位(TODO), 移动设备位置数据(TODO) |
||||
|
*/ |
||||
|
@Component |
||||
|
public class QueryMessageHandler extends MessageHandlerAbstract implements InitializingBean { |
||||
|
|
||||
|
private final String messageType = "Query"; |
||||
|
|
||||
|
@Autowired |
||||
|
private MessageRequestProcessor messageRequestProcessor; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
messageRequestProcessor.addHandler(messageType, this); |
||||
|
} |
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.header.FromHeader; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Component |
||||
|
public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(AlarmQueryMessageHandler.class); |
||||
|
private final String cmdType = "Alarm"; |
||||
|
|
||||
|
@Autowired |
||||
|
private QueryMessageHandler queryMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
queryMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
logger.info("不支持alarm查询"); |
||||
|
try { |
||||
|
responseAck(evt, Response.NOT_FOUND, "not support alarm query"); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,120 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.header.FromHeader; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Component |
||||
|
public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(CatalogQueryMessageHandler.class); |
||||
|
private final String cmdType = "Catalog"; |
||||
|
|
||||
|
@Autowired |
||||
|
private QueryMessageHandler queryMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
queryMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId(); |
||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
||||
|
try { |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
Element snElement = rootElement.element("SN"); |
||||
|
String sn = snElement.getText(); |
||||
|
// 准备回复通道信息
|
||||
|
List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); |
||||
|
// 查询关联的直播通道
|
||||
|
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); |
||||
|
int size = channelReduces.size() + gbStreams.size(); |
||||
|
// 回复级联的通道
|
||||
|
if (channelReduces.size() > 0) { |
||||
|
for (ChannelReduce channelReduce : channelReduces) { |
||||
|
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); |
||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
||||
|
} |
||||
|
} |
||||
|
// 回复直播的通道
|
||||
|
if (gbStreams.size() > 0) { |
||||
|
for (GbStream gbStream : gbStreams) { |
||||
|
DeviceChannel deviceChannel = new DeviceChannel(); |
||||
|
deviceChannel.setChannelId(gbStream.getGbId()); |
||||
|
deviceChannel.setName(gbStream.getName()); |
||||
|
deviceChannel.setLongitude(gbStream.getLongitude()); |
||||
|
deviceChannel.setLatitude(gbStream.getLatitude()); |
||||
|
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); |
||||
|
deviceChannel.setManufacture("wvp-pro"); |
||||
|
deviceChannel.setStatus(gbStream.isStatus()?1:0); |
||||
|
// deviceChannel.setParentId(parentPlatform.getDeviceGBId());
|
||||
|
deviceChannel.setRegisterWay(1); |
||||
|
deviceChannel.setCivilCode(config.getDomain()); |
||||
|
deviceChannel.setModel("live"); |
||||
|
deviceChannel.setOwner("wvp-pro"); |
||||
|
deviceChannel.setParental(0); |
||||
|
deviceChannel.setSecrecy("0"); |
||||
|
deviceChannel.setSecrecy("0"); |
||||
|
|
||||
|
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
||||
|
} |
||||
|
} |
||||
|
if (size == 0) { |
||||
|
// 回复无通道
|
||||
|
cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size); |
||||
|
} |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,62 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.header.FromHeader; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceInfoQueryMessageHandler.class); |
||||
|
private final String cmdType = "DeviceInfo"; |
||||
|
|
||||
|
@Autowired |
||||
|
private QueryMessageHandler queryMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
queryMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
logger.info("接收到DeviceInfo查询消息"); |
||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
||||
|
try { |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
String sn = rootElement.element("SN").getText(); |
||||
|
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag()); |
||||
|
} |
||||
|
} |
@ -0,0 +1,75 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.header.FromHeader; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceStatusQueryMessageHandler.class); |
||||
|
private final String cmdType = "DeviceStatus"; |
||||
|
|
||||
|
@Autowired |
||||
|
private QueryMessageHandler queryMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPCommanderFroPlatform cmderFroPlatform; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
queryMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
logger.info("接收到DeviceStatus查询消息"); |
||||
|
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
||||
|
// 回复200 OK
|
||||
|
try { |
||||
|
responseAck(evt, Response.OK); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
String sn = rootElement.element("SN").getText(); |
||||
|
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag()); |
||||
|
} |
||||
|
} |
@ -0,0 +1,25 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageHandlerAbstract; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.MessageRequestProcessor; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
/** |
||||
|
* 命令类型: 请求动作的应答 |
||||
|
* 命令类型: 设备控制, 报警通知, 设备目录信息查询, 目录信息查询, 目录收到, 设备信息查询, 设备状态信息查询 ...... |
||||
|
*/ |
||||
|
@Component |
||||
|
public class ResponseMessageHandler extends MessageHandlerAbstract implements InitializingBean { |
||||
|
|
||||
|
private final String messageType = "Response"; |
||||
|
|
||||
|
@Autowired |
||||
|
private MessageRequestProcessor messageRequestProcessor; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
messageRequestProcessor.addHandler(messageType, this); |
||||
|
} |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
@Component |
||||
|
public class AlarmResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(AlarmResponseMessageHandler.class); |
||||
|
private final String cmdType = "Alarm"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
Element deviceIdElement = rootElement.element("DeviceID"); |
||||
|
String channelId = deviceIdElement.getText().toString(); |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + device.getDeviceId() + channelId; |
||||
|
JSONObject json = new JSONObject(); |
||||
|
XmlUtil.node2Json(rootElement, json); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug(json.toJSONString()); |
||||
|
} |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(json); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,72 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(BroadcastResponseMessageHandler.class); |
||||
|
private final String cmdType = "Broadcast"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
try { |
||||
|
String channelId = getText(rootElement, "DeviceID"); |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId; |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
// 此处是对本平台发出Broadcast指令的应答
|
||||
|
JSONObject json = new JSONObject(); |
||||
|
XmlUtil.node2Json(rootElement, json); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug(json.toJSONString()); |
||||
|
} |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(json); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
|
||||
|
|
||||
|
} catch (ParseException | SipException | InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,182 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants; |
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
import java.util.Iterator; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class); |
||||
|
private final String cmdType = "Catalog"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeviceOffLineDetector offLineDetector; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + device.getDeviceId(); |
||||
|
Element rootElement = null; |
||||
|
try { |
||||
|
rootElement = getRootElement(evt, device.getCharset()); |
||||
|
Element deviceListElement = rootElement.element("DeviceList"); |
||||
|
Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); |
||||
|
if (deviceListIterator != null) { |
||||
|
|
||||
|
// 遍历DeviceList
|
||||
|
while (deviceListIterator.hasNext()) { |
||||
|
Element itemDevice = deviceListIterator.next(); |
||||
|
Element channelDeviceElement = itemDevice.element("DeviceID"); |
||||
|
if (channelDeviceElement == null) { |
||||
|
continue; |
||||
|
} |
||||
|
String channelDeviceId = channelDeviceElement.getText(); |
||||
|
Element channdelNameElement = itemDevice.element("Name"); |
||||
|
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; |
||||
|
Element statusElement = itemDevice.element("Status"); |
||||
|
String status = statusElement != null ? statusElement.getText().toString() : "ON"; |
||||
|
DeviceChannel deviceChannel = new DeviceChannel(); |
||||
|
deviceChannel.setName(channelName); |
||||
|
deviceChannel.setChannelId(channelDeviceId); |
||||
|
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
|
||||
|
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { |
||||
|
deviceChannel.setStatus(1); |
||||
|
} |
||||
|
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { |
||||
|
deviceChannel.setStatus(0); |
||||
|
} |
||||
|
|
||||
|
deviceChannel.setManufacture(getText(itemDevice, "Manufacturer")); |
||||
|
deviceChannel.setModel(getText(itemDevice, "Model")); |
||||
|
deviceChannel.setOwner(getText(itemDevice, "Owner")); |
||||
|
deviceChannel.setCivilCode(getText(itemDevice, "CivilCode")); |
||||
|
deviceChannel.setBlock(getText(itemDevice, "Block")); |
||||
|
deviceChannel.setAddress(getText(itemDevice, "Address")); |
||||
|
if (getText(itemDevice, "Parental") == null || getText(itemDevice, "Parental") == "") { |
||||
|
deviceChannel.setParental(0); |
||||
|
} else { |
||||
|
deviceChannel.setParental(Integer.parseInt(getText(itemDevice, "Parental"))); |
||||
|
} |
||||
|
deviceChannel.setParentId(getText(itemDevice, "ParentID")); |
||||
|
if (getText(itemDevice, "SafetyWay") == null || getText(itemDevice, "SafetyWay") == "") { |
||||
|
deviceChannel.setSafetyWay(0); |
||||
|
} else { |
||||
|
deviceChannel.setSafetyWay(Integer.parseInt(getText(itemDevice, "SafetyWay"))); |
||||
|
} |
||||
|
if (getText(itemDevice, "RegisterWay") == null || getText(itemDevice, "RegisterWay") == "") { |
||||
|
deviceChannel.setRegisterWay(1); |
||||
|
} else { |
||||
|
deviceChannel.setRegisterWay(Integer.parseInt(getText(itemDevice, "RegisterWay"))); |
||||
|
} |
||||
|
deviceChannel.setCertNum(getText(itemDevice, "CertNum")); |
||||
|
if (getText(itemDevice, "Certifiable") == null || getText(itemDevice, "Certifiable") == "") { |
||||
|
deviceChannel.setCertifiable(0); |
||||
|
} else { |
||||
|
deviceChannel.setCertifiable(Integer.parseInt(getText(itemDevice, "Certifiable"))); |
||||
|
} |
||||
|
if (getText(itemDevice, "ErrCode") == null || getText(itemDevice, "ErrCode") == "") { |
||||
|
deviceChannel.setErrCode(0); |
||||
|
} else { |
||||
|
deviceChannel.setErrCode(Integer.parseInt(getText(itemDevice, "ErrCode"))); |
||||
|
} |
||||
|
deviceChannel.setEndTime(getText(itemDevice, "EndTime")); |
||||
|
deviceChannel.setSecrecy(getText(itemDevice, "Secrecy")); |
||||
|
deviceChannel.setIpAddress(getText(itemDevice, "IPAddress")); |
||||
|
if (getText(itemDevice, "Port") == null || getText(itemDevice, "Port") == "") { |
||||
|
deviceChannel.setPort(0); |
||||
|
} else { |
||||
|
deviceChannel.setPort(Integer.parseInt(getText(itemDevice, "Port"))); |
||||
|
} |
||||
|
deviceChannel.setPassword(getText(itemDevice, "Password")); |
||||
|
if (NumericUtil.isDouble(getText(itemDevice, "Longitude"))) { |
||||
|
deviceChannel.setLongitude(Double.parseDouble(getText(itemDevice, "Longitude"))); |
||||
|
} else { |
||||
|
deviceChannel.setLongitude(0.00); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(itemDevice, "Latitude"))) { |
||||
|
deviceChannel.setLatitude(Double.parseDouble(getText(itemDevice, "Latitude"))); |
||||
|
} else { |
||||
|
deviceChannel.setLatitude(0.00); |
||||
|
} |
||||
|
if (getText(itemDevice, "PTZType") == null || getText(itemDevice, "PTZType") == "") { |
||||
|
deviceChannel.setPTZType(0); |
||||
|
} else { |
||||
|
deviceChannel.setPTZType(Integer.parseInt(getText(itemDevice, "PTZType"))); |
||||
|
} |
||||
|
deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
|
||||
|
storager.updateChannel(device.getDeviceId(), deviceChannel); |
||||
|
} |
||||
|
|
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(device); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
if (offLineDetector.isOnline(device.getDeviceId())) { |
||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
||||
|
} |
||||
|
} |
||||
|
} catch (DocumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,81 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(ConfigDownloadResponseMessageHandler.class); |
||||
|
private final String cmdType = "ConfigDownload"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
String channelId = getText(element, "DeviceID"); |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId; |
||||
|
try { |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||
|
JSONObject json = new JSONObject(); |
||||
|
XmlUtil.node2Json(element, json); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug(json.toJSONString()); |
||||
|
} |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(json); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
// 不会收到上级平台的心跳信息
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceConfigResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceConfigResponseMessageHandler.class); |
||||
|
private final String cmdType = "DeviceConfig"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
JSONObject json = new JSONObject(); |
||||
|
XmlUtil.node2Json(element, json); |
||||
|
String channelId = getText(element, "DeviceID"); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug(json.toJSONString()); |
||||
|
} |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + device.getDeviceId() + channelId; |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(json); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
} |
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.RequestEvent; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceControlResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceControlResponseMessageHandler.class); |
||||
|
private final String cmdType = "DeviceControl"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
// 此处是对本平台发出DeviceControl指令的应答
|
||||
|
JSONObject json = new JSONObject(); |
||||
|
String channelId = getText(element, "DeviceID"); |
||||
|
XmlUtil.node2Json(element, json); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug(json.toJSONString()); |
||||
|
} |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + device.getDeviceId() + channelId; |
||||
|
msg.setKey(key); |
||||
|
msg.setData(json); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants; |
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceInfoResponseMessageHandler.class); |
||||
|
private final String cmdType = "DeviceInfo"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeviceOffLineDetector offLineDetector; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
logger.debug("接收到DeviceInfo应答消息"); |
||||
|
try { |
||||
|
rootElement = getRootElement(evt, device.getCharset()); |
||||
|
Element deviceIdElement = rootElement.element("DeviceID"); |
||||
|
String channelId = deviceIdElement.getTextTrim(); |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + device.getDeviceId() + channelId; |
||||
|
device.setName(getText(rootElement, "DeviceName")); |
||||
|
|
||||
|
device.setManufacturer(getText(rootElement, "Manufacturer")); |
||||
|
device.setModel(getText(rootElement, "Model")); |
||||
|
device.setFirmware(getText(rootElement, "Firmware")); |
||||
|
if (StringUtils.isEmpty(device.getStreamMode())) { |
||||
|
device.setStreamMode("UDP"); |
||||
|
} |
||||
|
storager.updateDevice(device); |
||||
|
|
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(device); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
// 回复200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
if (offLineDetector.isOnline(device.getDeviceId())) { |
||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
||||
|
} |
||||
|
} catch (DocumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,89 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
||||
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
@Component |
||||
|
public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(DeviceStatusResponseMessageHandler.class); |
||||
|
private final String cmdType = "DeviceStatus"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeviceOffLineDetector offLineDetector; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Autowired |
||||
|
private EventPublisher publisher; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element element) { |
||||
|
logger.info("接收到DeviceStatus应答消息"); |
||||
|
// 检查设备是否存在, 不存在则不回复
|
||||
|
// 回复200 OK
|
||||
|
try { |
||||
|
responseAck(evt, Response.OK); |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
Element deviceIdElement = element.element("DeviceID"); |
||||
|
String channelId = deviceIdElement.getText(); |
||||
|
JSONObject json = new JSONObject(); |
||||
|
XmlUtil.node2Json(element, json); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug(json.toJSONString()); |
||||
|
} |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId() + channelId); |
||||
|
msg.setData(json); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
|
||||
|
if (offLineDetector.isOnline(device.getDeviceId())) { |
||||
|
publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); |
||||
|
} else { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.UserSetup; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.BaiduPoint; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; |
||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
||||
|
import com.genersoft.iot.vmp.utils.GpsUtil; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class MobilePositionResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(MobilePositionResponseMessageHandler.class); |
||||
|
private final String cmdType = "MobilePosition"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private UserSetup userSetup; |
||||
|
|
||||
|
@Autowired |
||||
|
private IVideoManagerStorager storager; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
|
||||
|
try { |
||||
|
rootElement = getRootElement(evt, device.getCharset()); |
||||
|
|
||||
|
MobilePosition mobilePosition = new MobilePosition(); |
||||
|
if (!StringUtils.isEmpty(device.getName())) { |
||||
|
mobilePosition.setDeviceName(device.getName()); |
||||
|
} |
||||
|
mobilePosition.setDeviceId(device.getDeviceId()); |
||||
|
mobilePosition.setChannelId(getText(rootElement, "DeviceID")); |
||||
|
mobilePosition.setTime(getText(rootElement, "Time")); |
||||
|
mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); |
||||
|
mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Speed"))) { |
||||
|
mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed"))); |
||||
|
} else { |
||||
|
mobilePosition.setSpeed(0.0); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Direction"))) { |
||||
|
mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction"))); |
||||
|
} else { |
||||
|
mobilePosition.setDirection(0.0); |
||||
|
} |
||||
|
if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) { |
||||
|
mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude"))); |
||||
|
} else { |
||||
|
mobilePosition.setAltitude(0.0); |
||||
|
} |
||||
|
mobilePosition.setReportSource("Mobile Position"); |
||||
|
BaiduPoint bp = new BaiduPoint(); |
||||
|
bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); |
||||
|
logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); |
||||
|
mobilePosition.setGeodeticSystem("BD-09"); |
||||
|
mobilePosition.setCnLng(bp.getBdLng()); |
||||
|
mobilePosition.setCnLat(bp.getBdLat()); |
||||
|
if (!userSetup.getSavePositionHistory()) { |
||||
|
storager.clearMobilePositionsByDeviceId(device.getDeviceId()); |
||||
|
} |
||||
|
storager.insertMobilePosition(mobilePosition); |
||||
|
//回复 200 OK
|
||||
|
responseAck(evt, Response.OK); |
||||
|
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,151 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; |
||||
|
import com.genersoft.iot.vmp.gb28181.bean.RecordItem; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; |
||||
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil; |
||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
||||
|
import org.dom4j.DocumentException; |
||||
|
import org.dom4j.Element; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.InvalidArgumentException; |
||||
|
import javax.sip.RequestEvent; |
||||
|
import javax.sip.SipException; |
||||
|
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Iterator; |
||||
|
import java.util.List; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
||||
|
|
||||
|
@Component |
||||
|
public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(RecordInfoResponseMessageHandler.class); |
||||
|
public static volatile List<String> threadNameList = new ArrayList(); |
||||
|
private final String cmdType = "RecordInfo"; |
||||
|
private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_"; |
||||
|
|
||||
|
@Autowired |
||||
|
private ResponseMessageHandler responseMessageHandler; |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisUtil redis; |
||||
|
|
||||
|
@Autowired |
||||
|
private DeferredResultHolder deferredResultHolder; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
responseMessageHandler.addHandler(cmdType, this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
||||
|
|
||||
|
// 回复200 OK
|
||||
|
try { |
||||
|
responseAck(evt, Response.OK); |
||||
|
|
||||
|
rootElement = getRootElement(evt, device.getCharset()); |
||||
|
String uuid = UUID.randomUUID().toString().replace("-", ""); |
||||
|
RecordInfo recordInfo = new RecordInfo(); |
||||
|
String sn = getText(rootElement, "SN"); |
||||
|
String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + sn; |
||||
|
recordInfo.setDeviceId(device.getDeviceId()); |
||||
|
recordInfo.setSn(sn); |
||||
|
recordInfo.setName(getText(rootElement, "Name")); |
||||
|
if (getText(rootElement, "SumNum") == null || getText(rootElement, "SumNum") == "") { |
||||
|
recordInfo.setSumNum(0); |
||||
|
} else { |
||||
|
recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum"))); |
||||
|
} |
||||
|
Element recordListElement = rootElement.element("RecordList"); |
||||
|
if (recordListElement == null || recordInfo.getSumNum() == 0) { |
||||
|
logger.info("无录像数据"); |
||||
|
RequestMessage msg = new RequestMessage(); |
||||
|
msg.setKey(key); |
||||
|
msg.setData(recordInfo); |
||||
|
deferredResultHolder.invokeAllResult(msg); |
||||
|
} else { |
||||
|
Iterator<Element> recordListIterator = recordListElement.elementIterator(); |
||||
|
List<RecordItem> recordList = new ArrayList<RecordItem>(); |
||||
|
if (recordListIterator != null) { |
||||
|
RecordItem record = new RecordItem(); |
||||
|
logger.info("处理录像列表数据..."); |
||||
|
// 遍历DeviceList
|
||||
|
while (recordListIterator.hasNext()) { |
||||
|
Element itemRecord = recordListIterator.next(); |
||||
|
Element recordElement = itemRecord.element("DeviceID"); |
||||
|
if (recordElement == null) { |
||||
|
logger.info("记录为空,下一个..."); |
||||
|
continue; |
||||
|
} |
||||
|
record = new RecordItem(); |
||||
|
record.setDeviceId(getText(itemRecord, "DeviceID")); |
||||
|
record.setName(getText(itemRecord, "Name")); |
||||
|
record.setFilePath(getText(itemRecord, "FilePath")); |
||||
|
record.setAddress(getText(itemRecord, "Address")); |
||||
|
record.setStartTime( |
||||
|
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "StartTime"))); |
||||
|
record.setEndTime( |
||||
|
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "EndTime"))); |
||||
|
record.setSecrecy(itemRecord.element("Secrecy") == null ? 0 |
||||
|
: Integer.parseInt(getText(itemRecord, "Secrecy"))); |
||||
|
record.setType(getText(itemRecord, "Type")); |
||||
|
record.setRecorderId(getText(itemRecord, "RecorderID")); |
||||
|
recordList.add(record); |
||||
|
} |
||||
|
recordInfo.setRecordList(recordList); |
||||
|
} |
||||
|
|
||||
|
// 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题
|
||||
|
String cacheKey = CACHE_RECORDINFO_KEY + device.getDeviceId() + sn; |
||||
|
redis.set(cacheKey + "_" + uuid, recordList, 90); |
||||
|
if (!threadNameList.contains(cacheKey)) { |
||||
|
threadNameList.add(cacheKey); |
||||
|
CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo); |
||||
|
chk.setName(cacheKey); |
||||
|
chk.setDeferredResultHolder(deferredResultHolder); |
||||
|
chk.setRedis(redis); |
||||
|
chk.setLogger(logger); |
||||
|
chk.start(); |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug("Start Thread " + cacheKey + "."); |
||||
|
} |
||||
|
} else { |
||||
|
if (logger.isDebugEnabled()) { |
||||
|
logger.debug("Thread " + cacheKey + " already started."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} catch (SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (InvalidArgumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (DocumentException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response; |
||||
|
|
||||
|
import javax.sip.ResponseEvent; |
||||
|
|
||||
|
/** |
||||
|
* @description:处理接收IPCamera发来的SIP协议响应消息 |
||||
|
* @author: swwheihei |
||||
|
* @date: 2020年5月3日 下午4:42:22 |
||||
|
*/ |
||||
|
public interface ISIPResponseProcessor { |
||||
|
|
||||
|
void process(ResponseEvent evt); |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response; |
||||
|
|
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
|
||||
|
public abstract class SIPResponseProcessorAbstract implements InitializingBean, ISIPResponseProcessor { |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.SipLayer; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.ResponseEvent; |
||||
|
|
||||
|
/** |
||||
|
* @description: BYE请求响应器 |
||||
|
* @author: swwheihei |
||||
|
* @date: 2020年5月3日 下午5:32:05 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class ByeResponseProcessor extends SIPResponseProcessorAbstract { |
||||
|
|
||||
|
private String method = "BYE"; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipLayer sipLayer; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
|
||||
|
@Autowired |
||||
|
private SIPProcessorObserver sipProcessorObserver; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
// 添加消息处理的订阅
|
||||
|
sipProcessorObserver.addResponseProcessor(method, this); |
||||
|
} |
||||
|
/** |
||||
|
* 处理BYE响应 |
||||
|
* |
||||
|
* @param evt |
||||
|
*/ |
||||
|
@Override |
||||
|
public void process(ResponseEvent evt) { |
||||
|
// TODO Auto-generated method stub
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,47 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.SipLayer; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.ResponseEvent; |
||||
|
|
||||
|
/** |
||||
|
* @description: CANCEL响应处理器 |
||||
|
* @author: panlinlin |
||||
|
* @date: 2021年11月5日 16:35 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class CancelResponseProcessor extends SIPResponseProcessorAbstract { |
||||
|
|
||||
|
private String method = "CANCEL"; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipLayer sipLayer; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipConfig config; |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPProcessorObserver sipProcessorObserver; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
// 添加消息处理的订阅
|
||||
|
sipProcessorObserver.addResponseProcessor(method, this); |
||||
|
} |
||||
|
/** |
||||
|
* 处理CANCEL响应 |
||||
|
* |
||||
|
* @param evt |
||||
|
*/ |
||||
|
@Override |
||||
|
public void process(ResponseEvent evt) { |
||||
|
// TODO Auto-generated method stub
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -1,75 +1,97 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl; |
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; |
||||
|
|
||||
import java.text.ParseException; |
import com.genersoft.iot.vmp.conf.SipConfig; |
||||
|
import com.genersoft.iot.vmp.gb28181.SipLayer; |
||||
import javax.sip.*; |
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
||||
import javax.sip.address.SipURI; |
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
import javax.sip.header.CSeqHeader; |
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; |
||||
import javax.sip.message.Request; |
import gov.nist.javax.sip.ResponseEventExt; |
||||
import javax.sip.message.Response; |
import gov.nist.javax.sip.stack.SIPDialog; |
||||
|
import org.slf4j.Logger; |
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
import org.slf4j.LoggerFactory; |
||||
import gov.nist.javax.sip.ResponseEventExt; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import gov.nist.javax.sip.stack.SIPDialog; |
import org.springframework.stereotype.Component; |
||||
import org.slf4j.Logger; |
|
||||
import org.slf4j.LoggerFactory; |
import javax.sip.InvalidArgumentException; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
import javax.sip.ResponseEvent; |
||||
import org.springframework.stereotype.Component; |
import javax.sip.SipException; |
||||
|
import javax.sip.address.SipURI; |
||||
import com.genersoft.iot.vmp.conf.SipConfig; |
import javax.sip.header.CSeqHeader; |
||||
import com.genersoft.iot.vmp.gb28181.SipLayer; |
import javax.sip.message.Request; |
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; |
import javax.sip.message.Response; |
||||
|
import java.text.ParseException; |
||||
|
|
||||
/** |
|
||||
* @Description:处理INVITE响应 |
/** |
||||
* @author: swwheihei |
* @description: 处理INVITE响应 |
||||
* @date: 2020年5月3日 下午4:43:52 |
* @author: panlinlin |
||||
*/ |
* @date: 2021年11月5日 16:40 |
||||
@Component |
*/ |
||||
public class InviteResponseProcessor implements ISIPResponseProcessor { |
@Component |
||||
|
public class InviteResponseProcessor extends SIPResponseProcessorAbstract { |
||||
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class); |
|
||||
|
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class); |
||||
@Autowired |
private String method = "INVITE"; |
||||
private VideoStreamSessionManager streamSession; |
|
||||
|
@Autowired |
||||
/** |
private SipLayer sipLayer; |
||||
* 处理invite响应 |
|
||||
* |
@Autowired |
||||
* @param evt 响应消息 |
private SipConfig config; |
||||
* @throws ParseException |
|
||||
*/ |
|
||||
@Override |
@Autowired |
||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException { |
private SIPProcessorObserver sipProcessorObserver; |
||||
try { |
|
||||
Response response = evt.getResponse(); |
@Override |
||||
int statusCode = response.getStatusCode(); |
public void afterPropertiesSet() throws Exception { |
||||
// trying不会回复
|
// 添加消息处理的订阅
|
||||
if (statusCode == Response.TRYING) { |
sipProcessorObserver.addResponseProcessor(method, this); |
||||
} |
} |
||||
// 成功响应
|
|
||||
// 下发ack
|
@Autowired |
||||
if (statusCode == Response.OK) { |
private VideoStreamSessionManager streamSession; |
||||
ResponseEventExt event = (ResponseEventExt)evt; |
|
||||
SIPDialog dialog = (SIPDialog)evt.getDialog(); |
/** |
||||
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
* 处理invite响应 |
||||
Request reqAck = dialog.createAck(cseq.getSeqNumber()); |
* |
||||
SipURI requestURI = (SipURI) reqAck.getRequestURI(); |
* @param evt 响应消息 |
||||
requestURI.setHost(event.getRemoteIpAddress()); |
* @throws ParseException |
||||
requestURI.setPort(event.getRemotePort()); |
*/ |
||||
reqAck.setRequestURI(requestURI); |
@Override |
||||
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack"); |
public void process(ResponseEvent evt ){ |
||||
SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI(); |
try { |
||||
String deviceId = requestURI.getUser(); |
Response response = evt.getResponse(); |
||||
String channelId = sipURI.getUser(); |
int statusCode = response.getStatusCode(); |
||||
|
// trying不会回复
|
||||
dialog.sendAck(reqAck); |
if (statusCode == Response.TRYING) { |
||||
|
} |
||||
} |
// 成功响应
|
||||
} catch (InvalidArgumentException | SipException e) { |
// 下发ack
|
||||
e.printStackTrace(); |
if (statusCode == Response.OK) { |
||||
} |
ResponseEventExt event = (ResponseEventExt)evt; |
||||
} |
SIPDialog dialog = (SIPDialog)evt.getDialog(); |
||||
|
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
||||
} |
Request reqAck = dialog.createAck(cseq.getSeqNumber()); |
||||
|
SipURI requestURI = (SipURI) reqAck.getRequestURI(); |
||||
|
try { |
||||
|
requestURI.setHost(event.getRemoteIpAddress()); |
||||
|
} catch (ParseException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
requestURI.setPort(event.getRemotePort()); |
||||
|
reqAck.setRequestURI(requestURI); |
||||
|
logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack"); |
||||
|
SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI(); |
||||
|
String deviceId = requestURI.getUser(); |
||||
|
String channelId = sipURI.getUser(); |
||||
|
|
||||
|
dialog.sendAck(reqAck); |
||||
|
|
||||
|
} |
||||
|
} catch (InvalidArgumentException | SipException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout; |
||||
|
|
||||
|
import javax.sip.TimeoutEvent; |
||||
|
|
||||
|
public interface ITimeoutProcessor { |
||||
|
void process(TimeoutEvent event); |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl; |
||||
|
|
||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
||||
|
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; |
||||
|
import org.springframework.beans.factory.InitializingBean; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.sip.TimeoutEvent; |
||||
|
import javax.sip.header.CallIdHeader; |
||||
|
|
||||
|
@Component |
||||
|
public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor { |
||||
|
|
||||
|
@Autowired |
||||
|
private SIPProcessorObserver processorObserver; |
||||
|
|
||||
|
@Autowired |
||||
|
private SipSubscribe sipSubscribe; |
||||
|
|
||||
|
@Override |
||||
|
public void afterPropertiesSet() throws Exception { |
||||
|
processorObserver.addTimeoutProcessor(this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void process(TimeoutEvent event) { |
||||
|
// TODO Auto-generated method stub
|
||||
|
CallIdHeader callIdHeader = event.getClientTransaction().getDialog().getCallId(); |
||||
|
String callId = callIdHeader.getCallId(); |
||||
|
SipSubscribe.Event errorSubscribe = sipSubscribe.getErrorSubscribe(callId); |
||||
|
SipSubscribe.EventResult<TimeoutEvent> timeoutEventEventResult = new SipSubscribe.EventResult<>(event); |
||||
|
errorSubscribe.response(timeoutEventEventResult); |
||||
|
} |
||||
|
} |
@ -1,12 +0,0 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request; |
|
||||
|
|
||||
/** |
|
||||
* @Description:处理接收IPCamera发来的SIP协议请求消息 |
|
||||
* @author: swwheihei |
|
||||
* @date: 2020年5月3日 下午4:42:22 |
|
||||
*/ |
|
||||
public interface ISIPRequestProcessor { |
|
||||
|
|
||||
public void process(); |
|
||||
|
|
||||
} |
|
@ -1,131 +0,0 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request; |
|
||||
|
|
||||
import javax.sip.PeerUnavailableException; |
|
||||
import javax.sip.RequestEvent; |
|
||||
import javax.sip.ServerTransaction; |
|
||||
import javax.sip.SipFactory; |
|
||||
import javax.sip.SipProvider; |
|
||||
import javax.sip.TransactionAlreadyExistsException; |
|
||||
import javax.sip.TransactionUnavailableException; |
|
||||
import javax.sip.address.AddressFactory; |
|
||||
import javax.sip.header.HeaderFactory; |
|
||||
import javax.sip.header.ViaHeader; |
|
||||
import javax.sip.message.MessageFactory; |
|
||||
import javax.sip.message.Request; |
|
||||
|
|
||||
import gov.nist.javax.sip.SipStackImpl; |
|
||||
import gov.nist.javax.sip.message.SIPRequest; |
|
||||
import gov.nist.javax.sip.stack.SIPServerTransaction; |
|
||||
import org.slf4j.Logger; |
|
||||
import org.slf4j.LoggerFactory; |
|
||||
|
|
||||
/** |
|
||||
* @Description:处理接收IPCamera发来的SIP协议请求消息 |
|
||||
* @author: songww |
|
||||
* @date: 2020年5月3日 下午4:42:22 |
|
||||
*/ |
|
||||
public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcessor { |
|
||||
|
|
||||
private final static Logger logger = LoggerFactory.getLogger(SIPRequestAbstractProcessor.class); |
|
||||
|
|
||||
protected RequestEvent evt; |
|
||||
|
|
||||
private SipProvider tcpSipProvider; |
|
||||
|
|
||||
private SipProvider udpSipProvider; |
|
||||
|
|
||||
@Override |
|
||||
public void process() { |
|
||||
this.process(evt); |
|
||||
} |
|
||||
|
|
||||
public abstract void process(RequestEvent evt); |
|
||||
|
|
||||
public ServerTransaction getServerTransaction(RequestEvent evt) { |
|
||||
Request request = evt.getRequest(); |
|
||||
ServerTransaction serverTransaction = evt.getServerTransaction(); |
|
||||
// 判断TCP还是UDP
|
|
||||
boolean isTcp = false; |
|
||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); |
|
||||
String transport = reqViaHeader.getTransport(); |
|
||||
if (transport.equals("TCP")) { |
|
||||
isTcp = true; |
|
||||
} |
|
||||
|
|
||||
if (serverTransaction == null) { |
|
||||
try { |
|
||||
if (isTcp) { |
|
||||
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack(); |
|
||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); |
|
||||
if (serverTransaction == null) { |
|
||||
serverTransaction = tcpSipProvider.getNewServerTransaction(request); |
|
||||
} |
|
||||
} else { |
|
||||
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack(); |
|
||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); |
|
||||
if (serverTransaction == null) { |
|
||||
serverTransaction = udpSipProvider.getNewServerTransaction(request); |
|
||||
} |
|
||||
} |
|
||||
} catch (TransactionAlreadyExistsException e) { |
|
||||
logger.error(e.getMessage()); |
|
||||
} catch (TransactionUnavailableException e) { |
|
||||
logger.error(e.getMessage()); |
|
||||
} |
|
||||
} |
|
||||
return serverTransaction; |
|
||||
} |
|
||||
|
|
||||
public AddressFactory getAddressFactory() { |
|
||||
try { |
|
||||
return SipFactory.getInstance().createAddressFactory(); |
|
||||
} catch (PeerUnavailableException e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public HeaderFactory getHeaderFactory() { |
|
||||
try { |
|
||||
return SipFactory.getInstance().createHeaderFactory(); |
|
||||
} catch (PeerUnavailableException e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public MessageFactory getMessageFactory() { |
|
||||
try { |
|
||||
return SipFactory.getInstance().createMessageFactory(); |
|
||||
} catch (PeerUnavailableException e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public RequestEvent getRequestEvent() { |
|
||||
return evt; |
|
||||
} |
|
||||
|
|
||||
public void setRequestEvent(RequestEvent evt) { |
|
||||
this.evt = evt; |
|
||||
} |
|
||||
|
|
||||
public SipProvider getTcpSipProvider() { |
|
||||
return tcpSipProvider; |
|
||||
} |
|
||||
|
|
||||
public void setTcpSipProvider(SipProvider tcpSipProvider) { |
|
||||
this.tcpSipProvider = tcpSipProvider; |
|
||||
} |
|
||||
|
|
||||
public SipProvider getUdpSipProvider() { |
|
||||
return udpSipProvider; |
|
||||
} |
|
||||
|
|
||||
public void setUdpSipProvider(SipProvider udpSipProvider) { |
|
||||
this.udpSipProvider = udpSipProvider; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
@ -1,28 +0,0 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl; |
|
||||
|
|
||||
import javax.sip.RequestEvent; |
|
||||
|
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
|
||||
|
|
||||
/** |
|
||||
* @Description:CANCEL请求处理器 |
|
||||
* @author: swwheihei |
|
||||
* @date: 2020年5月3日 下午5:32:23 |
|
||||
*/ |
|
||||
public class CancelRequestProcessor extends SIPRequestAbstractProcessor { |
|
||||
|
|
||||
/** |
|
||||
* 处理CANCEL请求 |
|
||||
* |
|
||||
* @param evt |
|
||||
* @param layer |
|
||||
* @param transaction |
|
||||
* @param config |
|
||||
*/ |
|
||||
@Override |
|
||||
public void process(RequestEvent evt) { |
|
||||
// TODO 优先级99 Cancel Request消息实现,此消息一般为级联消息,上级给下级发送请求取消指令
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,31 +0,0 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.request.impl; |
|
||||
|
|
||||
import javax.sip.RequestEvent; |
|
||||
|
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; |
|
||||
import org.slf4j.Logger; |
|
||||
import org.slf4j.LoggerFactory; |
|
||||
|
|
||||
/** |
|
||||
* @Description:暂不支持的消息请求处理器 |
|
||||
* @author: swwheihei |
|
||||
* @date: 2020年5月3日 下午5:32:59 |
|
||||
*/ |
|
||||
public class OtherRequestProcessor extends SIPRequestAbstractProcessor { |
|
||||
|
|
||||
private Logger logger = LoggerFactory.getLogger(OtherRequestProcessor.class); |
|
||||
|
|
||||
/** |
|
||||
* <p>Title: process</p> |
|
||||
* <p>Description: </p> |
|
||||
* @param evt |
|
||||
* @param layer |
|
||||
* @param transaction |
|
||||
* @param config |
|
||||
*/ |
|
||||
@Override |
|
||||
public void process(RequestEvent evt) { |
|
||||
logger.info("Unsupported the method: " + evt.getRequest().getMethod()); |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,19 +0,0 @@ |
|||||
package com.genersoft.iot.vmp.gb28181.transmit.response; |
|
||||
|
|
||||
import java.text.ParseException; |
|
||||
|
|
||||
import javax.sip.ResponseEvent; |
|
||||
|
|
||||
import com.genersoft.iot.vmp.conf.SipConfig; |
|
||||
import com.genersoft.iot.vmp.gb28181.SipLayer; |
|
||||
|
|
||||
/** |
|
||||
* @Description:处理接收IPCamera发来的SIP协议响应消息 |
|
||||
* @author: swwheihei |
|
||||
* @date: 2020年5月3日 下午4:42:22 |
|
||||
*/ |
|
||||
public interface ISIPResponseProcessor { |
|
||||
|
|
||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) throws ParseException; |
|
||||
|
|
||||
} |
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue