Browse Source

优化代码结构,提供NVR录像检索接口

pull/1/head
songww 5 years ago
parent
commit
bf7ab3fe2b
  1. 30
      src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
  2. 1
      src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
  3. 119
      src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
  4. 26
      src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
  5. 51
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
  6. 99
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
  7. 42
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
  8. 51
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
  9. 56
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
  10. 126
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
  11. 154
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
  12. 6
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
  13. 40
      src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java
  14. 152
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  15. 34
      src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
  16. 8
      src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
  17. 8
      src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java
  18. 47
      src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java

30
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java

@ -12,20 +12,19 @@ import com.alibaba.fastjson.parser.ParserConfig;
import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
/** /**
* @Description:Redis中间件配置类 * @Description:Redis中间件配置类使用spring-data-redis集成自动从application.yml中加载redis配置
* @author: songww * @author: songww
* @date: 2019年5月30日 上午10:58:25 * @date: 2019年5月30日 上午10:58:25
* *
*/ */
@Configuration @Configuration
// @EnableCaching
public class RedisConfig extends CachingConfigurerSupport { public class RedisConfig extends CachingConfigurerSupport {
@Bean("redisTemplate") @Bean("redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>(); RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory); template.setConnectionFactory(redisConnectionFactory);
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 使用fastjson进行序列化处理,提高解析效率
FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<Object>(Object.class); FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<Object>(Object.class);
// value值的序列化采用fastJsonRedisSerializer // value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(serializer); template.setValueSerializer(serializer);
@ -33,8 +32,9 @@ public class RedisConfig extends CachingConfigurerSupport {
// key的序列化采用StringRedisSerializer // key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer()); template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory); template.setConnectionFactory(redisConnectionFactory);
// 使用fastjson时需设置此项,否则会报异常not support type
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
return template; return template;
} }
@ -53,27 +53,5 @@ public class RedisConfig extends CachingConfigurerSupport {
container.setConnectionFactory(connectionFactory); container.setConnectionFactory(connectionFactory);
return container; return container;
} }
// @Bean
// RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
// MessageListenerAdapter listenerAdapter) {
//
// RedisMessageListenerContainer container = new RedisMessageListenerContainer();
// container.setConnectionFactory(connectionFactory);
// // 订阅了一个叫通道
// container.addMessageListener(listenerAdapter, new PatternTopic(VideoManagerConstants.KEEPLIVEKEY_PREFIX+"*"));
// // 这个container 可以添加多个 messageListener
// return container;
// }
// /**
// * 消息监听器适配器,绑定消息处理器,利用反射技术调用消息处理器的业务方法
// * @param receiver
// * @return
// */
// @Bean
// MessageListenerAdapter listenerAdapter(MessageReceiver receiver) {
// //这个地方 是给messageListenerAdapter 传入一个消息接受的处理器,利用反射的方法调用“receiveMessage”
// //也有好几个重载方法,这边默认调用处理器的方法 叫handleMessage 可以自己到源码里面看
// return new MessageListenerAdapter(receiver, "receiveMessage");
// }
} }

1
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java

@ -16,7 +16,6 @@ public class SipConfig {
String sipPassword; String sipPassword;
@Value("${media.ip}") @Value("${media.ip}")
String mediaIp; String mediaIp;
@Value("${media.port}") @Value("${media.port}")
Integer mediaPort; Integer mediaPort;

119
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181;
import java.util.Properties; import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.sip.DialogTerminatedEvent; import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent; import javax.sip.IOExceptionEvent;
import javax.sip.ListeningPoint; import javax.sip.ListeningPoint;
@ -26,7 +27,6 @@ import javax.sip.message.Response;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
@ -37,7 +37,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
@Component @Component
public class SipLayer implements SipListener{ public class SipLayer implements SipListener, Runnable {
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
@ -57,50 +57,58 @@ public class SipLayer implements SipListener{
private HeaderFactory headerFactory; private HeaderFactory headerFactory;
private MessageFactory messageFactory; private MessageFactory messageFactory;
@Bean @PostConstruct
private boolean initSipServer() throws Exception { private void initSipServer() {
Thread thread=new Thread(this);
thread.setDaemon(true);
thread.setName("sip server thread start");
thread.start();
}
@Override
public void run() {
SipFactory sipFactory = SipFactory.getInstance(); SipFactory sipFactory = SipFactory.getInstance();
sipFactory.setPathName("gov.nist"); sipFactory.setPathName("gov.nist");
headerFactory = sipFactory.createHeaderFactory();
addressFactory = sipFactory.createAddressFactory();
messageFactory = sipFactory.createMessageFactory();
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
properties.setProperty("javax.sip.IP_ADDRESS", config.getSipIp());
/**
* sip_server_log.log sip_debug_log.log public static final int TRACE_NONE =
* 0; public static final int TRACE_MESSAGES = 16; public static final int
* TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
*/
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "16");
properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
try { try {
headerFactory = sipFactory.createHeaderFactory();
addressFactory = sipFactory.createAddressFactory();
messageFactory = sipFactory.createMessageFactory();
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
properties.setProperty("javax.sip.IP_ADDRESS", config.getSipIp());
properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
/**
* sip_server_log.log sip_debug_log.log public static final int TRACE_NONE =
* 0; public static final int TRACE_MESSAGES = 16; public static final int
* TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
*/
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0");
properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
startTcpListener(); startTcpListener();
startUdpListener(); startUdpListener();
} catch (Exception e) { } catch (Exception e) {
logger.error("Sip Server 启动失败! port {"+config.getSipPort()+"}"); logger.error("Sip Server 启动失败! port {" + config.getSipPort() + "}");
e.printStackTrace(); e.printStackTrace();
throw e;
} }
logger.info("Sip Server 启动成功 port {"+config.getSipPort()+"}"); logger.info("Sip Server 启动成功 port {" + config.getSipPort() + "}");
return true;
} }
private void startTcpListener() throws Exception { private void startTcpListener() throws Exception {
ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "TCP"); ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "TCP");
tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint); tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
tcpSipProvider.addSipListener(this); tcpSipProvider.addSipListener(this);
} }
private void startUdpListener() throws Exception { private void startUdpListener() throws Exception {
ListeningPoint udpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "UDP"); ListeningPoint udpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "UDP");
udpSipProvider = sipStack.createSipProvider(udpListeningPoint); udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
udpSipProvider.addSipListener(this); udpSipProvider.addSipListener(this);
} }
/** /**
* SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a * SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a
@ -118,19 +126,24 @@ public class SipLayer implements SipListener{
int status = response.getStatusCode(); int status = response.getStatusCode();
if ((status >= 200) && (status < 300)) { // Success! if ((status >= 200) && (status < 300)) { // Success!
ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
processor.process(evt,this,config); processor.process(evt, this, config);
} else { } else {
logger.warn("接收到失败的response响应!status:"+status+",message:"+response.getContent().toString()); logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getContent().toString());
} }
//trying不会回复 // trying不会回复
if(status == Response.TRYING){ if (status == Response.TRYING) {
} }
} }
/** /**
* <p>Title: processTimeout</p> * <p>
* <p>Description: </p> * Title: processTimeout
* </p>
* <p>
* Description:
* </p>
*
* @param timeoutEvent * @param timeoutEvent
*/ */
@Override @Override
@ -140,8 +153,13 @@ public class SipLayer implements SipListener{
} }
/** /**
* <p>Title: processIOException</p> * <p>
* <p>Description: </p> * Title: processIOException
* </p>
* <p>
* Description:
* </p>
*
* @param exceptionEvent * @param exceptionEvent
*/ */
@Override @Override
@ -151,8 +169,13 @@ public class SipLayer implements SipListener{
} }
/** /**
* <p>Title: processTransactionTerminated</p> * <p>
* <p>Description: </p> * Title: processTransactionTerminated
* </p>
* <p>
* Description:
* </p>
*
* @param transactionTerminatedEvent * @param transactionTerminatedEvent
*/ */
@Override @Override
@ -162,8 +185,13 @@ public class SipLayer implements SipListener{
} }
/** /**
* <p>Title: processDialogTerminated</p> * <p>
* <p>Description: </p> * Title: processDialogTerminated
* </p>
* <p>
* Description:
* </p>
*
* @param dialogTerminatedEvent * @param dialogTerminatedEvent
*/ */
@Override @Override
@ -185,11 +213,11 @@ public class SipLayer implements SipListener{
if (serverTransaction == null) { if (serverTransaction == null) {
try { try {
if (isTcp) { if (isTcp) {
serverTransaction = tcpSipProvider.getNewServerTransaction(request); serverTransaction = tcpSipProvider.getNewServerTransaction(request);
} else { } else {
serverTransaction = udpSipProvider.getNewServerTransaction(request); serverTransaction = udpSipProvider.getNewServerTransaction(request);
} }
} catch (TransactionAlreadyExistsException e) { } catch (TransactionAlreadyExistsException e) {
e.printStackTrace(); e.printStackTrace();
} catch (TransactionUnavailableException e) { } catch (TransactionUnavailableException e) {
@ -199,7 +227,6 @@ public class SipLayer implements SipListener{
return serverTransaction; return serverTransaction;
} }
public AddressFactory getAddressFactory() { public AddressFactory getAddressFactory() {
return addressFactory; return addressFactory;
} }

26
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java

@ -0,0 +1,26 @@
package com.genersoft.iot.vmp.gb28181.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
/**
* @Description:注册逻辑处理当设备注册后触发逻辑
* @author: songww
* @date: 2020年5月8日 下午9:41:46
*/
@Component
public class RegisterLogicHandler {
@Autowired
private SIPCommander cmder;
public void onRegister(Device device) {
// TODO 后续处理,只有第一次注册时调用查询设备信息,如需更新调用更新API接口
cmder.deviceInfoQuery(device);
cmder.catalogQuery(device);
}
}

51
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java

@ -0,0 +1,51 @@
package com.genersoft.iot.vmp.gb28181.bean;
import java.util.List;
/**
* @Description:设备录像信息bean
* @author: songww
* @date: 2020年5月8日 下午2:05:56
*/
public class RecordInfo {
private String deviceId;
private String name;
private int sumNum;
private List<RecordItem> recordList;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSumNum() {
return sumNum;
}
public void setSumNum(int sumNum) {
this.sumNum = sumNum;
}
public List<RecordItem> getRecordList() {
return recordList;
}
public void setRecordList(List<RecordItem> recordList) {
this.recordList = recordList;
}
}

99
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java

@ -0,0 +1,99 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* @Description:设备录像bean
* @author: songww
* @date: 2020年5月8日 下午2:06:54
*/
public class RecordItem {
private String deviceId;
private String name;
private String filePath;
private String address;
private String startTime;
private String endTime;
private int secrecy;
private String type;
private String recordId;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public int getSecrecy() {
return secrecy;
}
public void setSecrecy(int secrecy) {
this.secrecy = secrecy;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRecordId() {
return recordId;
}
public void setRecordId(String recordId) {
this.recordId = recordId;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}

42
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java

@ -0,0 +1,42 @@
package com.genersoft.iot.vmp.gb28181.transmit.callback;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;
/**
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: songww
* @date: 2020年5月8日 下午7:59:05
*/
@Component
public class DeferredResultHolder {
public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
private Map<String, DeferredResult> map = new HashMap<String, DeferredResult>();
public void put(String key, DeferredResult result) {
map.put(key, result);
}
public DeferredResult get(String key) {
return map.get(key);
}
public void invokeResult(RequestMessage msg) {
DeferredResult result = map.get(msg.getId());
if (result == null) {
return;
}
result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
}
}

51
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java

@ -0,0 +1,51 @@
package com.genersoft.iot.vmp.gb28181.transmit.callback;
/**
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: songww
* @date: 2020年5月8日 下午1:09:18
*/
public class RequestMessage {
private String id;
private String deviceId;
private String type;
private Object data;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
this.id = type + deviceId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
this.id = type + deviceId;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}

56
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java

@ -12,48 +12,48 @@ public interface ISIPCommander {
/** /**
* 云台方向放控制使用配置文件中的默认镜头移动速度 * 云台方向放控制使用配置文件中的默认镜头移动速度
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param moveSpeed 镜头移动速度 * @param moveSpeed 镜头移动速度
*/ */
public boolean ptzdirectCmd(String deviceId,String channelId,int leftRight, int upDown); public boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown);
/** /**
* 云台方向放控制 * 云台方向放控制
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param moveSpeed 镜头移动速度 * @param moveSpeed 镜头移动速度
*/ */
public boolean ptzdirectCmd(String deviceId,String channelId,int leftRight, int upDown, int moveSpeed); public boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed);
/** /**
* 云台缩放控制使用配置文件中的默认镜头缩放速度 * 云台缩放控制使用配置文件中的默认镜头缩放速度
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
*/ */
public boolean ptzZoomCmd(String deviceId,String channelId,int inOut); public boolean ptzZoomCmd(Device device,String channelId,int inOut);
/** /**
* 云台缩放控制 * 云台缩放控制
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
* @param zoomSpeed 镜头缩放速度 * @param zoomSpeed 镜头缩放速度
*/ */
public boolean ptzZoomCmd(String deviceId,String channelId,int inOut, int moveSpeed); public boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed);
/** /**
* 云台控制支持方向与缩放控制 * 云台控制支持方向与缩放控制
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
@ -61,67 +61,67 @@ public interface ISIPCommander {
* @param moveSpeed 镜头移动速度 * @param moveSpeed 镜头移动速度
* @param zoomSpeed 镜头缩放速度 * @param zoomSpeed 镜头缩放速度
*/ */
public boolean ptzCmd(String deviceId,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed); public boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
/** /**
* 请求预览视频流 * 请求预览视频流
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
public String playStreamCmd(String deviceId,String channelId); public String playStreamCmd(Device device,String channelId);
/** /**
* 语音广播 * 语音广播
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
public String audioBroadcastCmd(String deviceId,String channelId); public boolean audioBroadcastCmd(Device device,String channelId);
/** /**
* 音视频录像控制 * 音视频录像控制
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
public String recordCmd(String deviceId,String channelId); public boolean recordCmd(Device device,String channelId);
/** /**
* 报警布防/撤防命令 * 报警布防/撤防命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
public String guardCmd(String deviceId); public boolean guardCmd(Device device);
/** /**
* 报警复位命令 * 报警复位命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
public String alarmCmd(String deviceId); public boolean alarmCmd(Device device);
/** /**
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
public String iFameCmd(String deviceId,String channelId); public boolean iFameCmd(Device device,String channelId);
/** /**
* 看守位控制命令 * 看守位控制命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
public String homePositionCmd(String deviceId); public boolean homePositionCmd(Device device);
/** /**
* 设备配置命令 * 设备配置命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
public String deviceConfigCmd(String deviceId); public boolean deviceConfigCmd(Device device);
/** /**
@ -150,8 +150,10 @@ public interface ISIPCommander {
* 查询录像信息 * 查询录像信息
* *
* @param device 视频设备 * @param device 视频设备
* @param startTime 开始时间,格式要求yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss
*/ */
public boolean recordInfoQuery(Device device); public boolean recordInfoQuery(Device device, String startTime, String endTime);
/** /**
* 查询报警信息 * 查询报警信息

126
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@ -8,6 +8,7 @@ import javax.sip.SipException;
import javax.sip.message.Request; import javax.sip.message.Request;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
@ -15,7 +16,7 @@ import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
/** /**
* @Description:设备能力接口用于定义设备的控制查询能力 * @Description:设备能力接口用于定义设备的控制查询能力
@ -34,66 +35,63 @@ public class SIPCommander implements ISIPCommander {
@Autowired @Autowired
private SipLayer sipLayer; private SipLayer sipLayer;
@Autowired
private IVideoManagerStorager storager;
/** /**
* 云台方向放控制使用配置文件中的默认镜头移动速度 * 云台方向放控制使用配置文件中的默认镜头移动速度
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param moveSpeed 镜头移动速度 * @param moveSpeed 镜头移动速度
*/ */
@Override @Override
public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown) { public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) {
return ptzCmd(deviceId, channelId, leftRight, upDown, 0, config.getSpeed(), 0); return ptzCmd(device, channelId, leftRight, upDown, 0, config.getSpeed(), 0);
} }
/** /**
* 云台方向放控制 * 云台方向放控制
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param moveSpeed 镜头移动速度 * @param moveSpeed 镜头移动速度
*/ */
@Override @Override
public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown, int moveSpeed) { public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) {
return ptzCmd(deviceId, channelId, leftRight, upDown, 0, moveSpeed, 0); return ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);
} }
/** /**
* 云台缩放控制使用配置文件中的默认镜头缩放速度 * 云台缩放控制使用配置文件中的默认镜头缩放速度
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
*/ */
@Override @Override
public boolean ptzZoomCmd(String deviceId, String channelId, int inOut) { public boolean ptzZoomCmd(Device device, String channelId, int inOut) {
return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, config.getSpeed()); return ptzCmd(device, channelId, 0, 0, inOut, 0, config.getSpeed());
} }
/** /**
* 云台缩放控制 * 云台缩放控制
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
* @param zoomSpeed 镜头缩放速度 * @param zoomSpeed 镜头缩放速度
*/ */
@Override @Override
public boolean ptzZoomCmd(String deviceId, String channelId, int inOut, int zoomSpeed) { public boolean ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) {
return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, zoomSpeed); return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
} }
/** /**
* 云台控制支持方向与缩放控制 * 云台控制支持方向与缩放控制
* *
* @param deviceId 控制设备 * @param device 控制设备
* @param channelId 预览通道 * @param channelId 预览通道
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
@ -102,10 +100,9 @@ public class SIPCommander implements ISIPCommander {
* @param zoomSpeed 镜头缩放速度 * @param zoomSpeed 镜头缩放速度
*/ */
@Override @Override
public boolean ptzCmd(String deviceId, String channelId, int leftRight, int upDown, int inOut, int moveSpeed, public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
int zoomSpeed) { int zoomSpeed) {
try { try {
Device device = storager.queryVideoDevice(deviceId);
StringBuffer ptzXml = new StringBuffer(200); StringBuffer ptzXml = new StringBuffer(200);
ptzXml.append("<?xml version=\"1.0\" ?>"); ptzXml.append("<?xml version=\"1.0\" ?>");
ptzXml.append("<Control>"); ptzXml.append("<Control>");
@ -119,7 +116,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag"); Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
transmitRequest(device.getTransport(), request); transmitRequest(device, request);
return true; return true;
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
@ -131,15 +128,13 @@ public class SIPCommander implements ISIPCommander {
/** /**
* 请求预览视频流 * 请求预览视频流
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
@Override @Override
public String playStreamCmd(String deviceId, String channelId) { public String playStreamCmd(Device device, String channelId) {
try { try {
Device device = storager.queryVideoDevice(deviceId);
//生成ssrc标识数据流 10位数字 //生成ssrc标识数据流 10位数字
String ssrc = ""; String ssrc = "";
Random random = new Random(); Random random = new Random();
@ -170,7 +165,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null); Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
transmitRequest(device.getTransport(), request); transmitRequest(device, request);
return ssrc; return ssrc;
} catch ( SipException | ParseException | InvalidArgumentException e) { } catch ( SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace(); e.printStackTrace();
@ -181,81 +176,81 @@ public class SIPCommander implements ISIPCommander {
/** /**
* 语音广播 * 语音广播
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
@Override @Override
public String audioBroadcastCmd(String deviceId, String channelId) { public boolean audioBroadcastCmd(Device device, String channelId) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
* 音视频录像控制 * 音视频录像控制
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
@Override @Override
public String recordCmd(String deviceId, String channelId) { public boolean recordCmd(Device device, String channelId) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
* 报警布防/撤防命令 * 报警布防/撤防命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
@Override @Override
public String guardCmd(String deviceId) { public boolean guardCmd(Device device) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
* 报警复位命令 * 报警复位命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
@Override @Override
public String alarmCmd(String deviceId) { public boolean alarmCmd(Device device) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
* *
* @param deviceId 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
@Override @Override
public String iFameCmd(String deviceId, String channelId) { public boolean iFameCmd(Device device, String channelId) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
* 看守位控制命令 * 看守位控制命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
@Override @Override
public String homePositionCmd(String deviceId) { public boolean homePositionCmd(Device device) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
* 设备配置命令 * 设备配置命令
* *
* @param deviceId 视频设备 * @param device 视频设备
*/ */
@Override @Override
public String deviceConfigCmd(String deviceId) { public boolean deviceConfigCmd(Device device) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
/** /**
@ -286,8 +281,8 @@ public class SIPCommander implements ISIPCommander {
catalogXml.append("</Query>"); catalogXml.append("</Query>");
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag"); Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag");
transmitRequest(device, request);
transmitRequest(device.getTransport(), request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
@ -312,9 +307,7 @@ public class SIPCommander implements ISIPCommander {
catalogXml.append("</Query>"); catalogXml.append("</Query>");
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag"); Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag");
transmitRequest(device, request);
transmitRequest(device.getTransport(), request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
@ -326,11 +319,32 @@ public class SIPCommander implements ISIPCommander {
* 查询录像信息 * 查询录像信息
* *
* @param device 视频设备 * @param device 视频设备
* @param startTime 开始时间,格式要求yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss
*/ */
@Override @Override
public boolean recordInfoQuery(Device device) { public boolean recordInfoQuery(Device device, String startTime, String endTime) {
// TODO Auto-generated method stub
return false; try {
StringBuffer catalogXml = new StringBuffer(200);
catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>");
catalogXml.append("<Query>");
catalogXml.append("<CmdType>RecordInfo</CmdType>");
catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>");
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>");
catalogXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>");
catalogXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>");
// 大华NVR要求必须增加一个值为all的文本元素节点Type
catalogXml.append("<Type>all</Type>");
catalogXml.append("</Query>");
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", "ToRecordInfoTag");
transmitRequest(device, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
} }
/** /**
@ -377,10 +391,10 @@ public class SIPCommander implements ISIPCommander {
return false; return false;
} }
private void transmitRequest(String transport, Request request) throws SipException { private void transmitRequest(Device device, Request request) throws SipException {
if(transport.equals("TCP")) { if(device.getTransport().equals("TCP")) {
sipLayer.getTcpSipProvider().sendRequest(request); sipLayer.getTcpSipProvider().sendRequest(request);
} else if(transport.equals("UDP")) { } else if(device.getTransport().equals("UDP")) {
sipLayer.getUdpSipProvider().sendRequest(request); sipLayer.getUdpSipProvider().sendRequest(request);
} }
} }

154
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java

@ -2,8 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
@ -24,9 +26,14 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.gb28181.SipLayer; import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 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.cmd.impl.SIPCommander; 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.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@ -51,6 +58,9 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
@Autowired @Autowired
private EventPublisher publisher; private EventPublisher publisher;
@Autowired
private DeferredResultHolder deferredResultHolder;
/** /**
* 处理MESSAGE请求 * 处理MESSAGE请求
* *
@ -74,21 +84,49 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
processMessageDeviceInfo(evt); processMessageDeviceInfo(evt);
} else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) { } else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) {
processMessageAlarm(evt); processMessageAlarm(evt);
} else if (new String(request.getRawContent()).contains("<CmdType>recordInfo</CmdType>")) {
processMessageRecordInfo(evt);
} }
} }
/**
* 收到deviceInfo设备信息请求 处理
* @param evt
*/
private void processMessageDeviceInfo(RequestEvent evt) {
try {
Element rootElement = getRootElement(evt);
Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getText().toString();
Device device = storager.queryVideoDevice(deviceId);
if (device == null) {
return;
}
device.setName(XmlUtil.getText(rootElement,"DeviceName"));
device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));
device.setModel(XmlUtil.getText(rootElement,"Model"));
device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));
storager.update(device);
RequestMessage msg = new RequestMessage();
msg.setDeviceId(deviceId);
msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO);
msg.setData(device);
deferredResultHolder.invokeResult(msg);
} catch (DocumentException e) {
e.printStackTrace();
}
}
/*** /***
* 收到catalog设备目录列表请求 处理 * 收到catalog设备目录列表请求 处理
* @param evt * @param evt
*/ */
private void processMessageCatalogList(RequestEvent evt) { private void processMessageCatalogList(RequestEvent evt) {
try { try {
Request request = evt.getRequest(); Element rootElement = getRootElement(evt);
SAXReader reader = new SAXReader();
reader.setEncoding("GB2312");
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
Element rootElement = xml.getRootElement();
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getText().toString(); String deviceId = deviceIdElement.getText().toString();
Element deviceListElement = rootElement.element("DeviceList"); Element deviceListElement = rootElement.element("DeviceList");
@ -152,6 +190,11 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
} }
// 更新 // 更新
storager.update(device); storager.update(device);
RequestMessage msg = new RequestMessage();
msg.setDeviceId(deviceId);
msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
msg.setData(device);
deferredResultHolder.invokeResult(msg);
} }
} catch (DocumentException e) { } catch (DocumentException e) {
e.printStackTrace(); e.printStackTrace();
@ -159,16 +202,12 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
} }
/*** /***
* 收到deviceInfo设备信息请求 处理 * 收到alarm设备报警信息 处理
* @param evt * @param evt
*/ */
private void processMessageDeviceInfo(RequestEvent evt) { private void processMessageAlarm(RequestEvent evt) {
try { try {
Request request = evt.getRequest(); Element rootElement = getRootElement(evt);
SAXReader reader = new SAXReader();
// reader.setEncoding("GB2312");
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
Element rootElement = xml.getRootElement();
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getText().toString(); String deviceId = deviceIdElement.getText().toString();
@ -188,52 +227,83 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
} }
/*** /***
* 收到alarm设备报警信息 处理 * 收到keepalive请求 处理
* @param evt * @param evt
*/ */
private void processMessageAlarm(RequestEvent evt) { private void processMessageKeepAlive(RequestEvent evt){
try { try {
Request request = evt.getRequest(); Request request = evt.getRequest();
SAXReader reader = new SAXReader(); Response response = layer.getMessageFactory().createResponse(Response.OK,request);
// reader.setEncoding("GB2312"); Element rootElement = getRootElement(evt);
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
Element rootElement = xml.getRootElement();
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
String deviceId = deviceIdElement.getText().toString(); transaction.sendResponse(response);
publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
Device device = storager.queryVideoDevice(deviceId); } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
if (device == null) {
return;
}
device.setName(XmlUtil.getText(rootElement,"DeviceName"));
device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));
device.setModel(XmlUtil.getText(rootElement,"Model"));
device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));
storager.update(device);
cmder.catalogQuery(device);
} catch (DocumentException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
/*** /***
* 收到keepalive请求 处理 * 收到catalog设备目录列表请求 处理
* @param evt * @param evt
*/ */
private void processMessageKeepAlive(RequestEvent evt){ private void processMessageRecordInfo(RequestEvent evt) {
try { try {
Request request = evt.getRequest(); RecordInfo recordInfo = new RecordInfo();
Response response = layer.getMessageFactory().createResponse(Response.OK,request); Element rootElement = getRootElement(evt);
SAXReader reader = new SAXReader();
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
// reader.setEncoding("GB2312");
Element rootElement = xml.getRootElement();
Element deviceIdElement = rootElement.element("DeviceID"); Element deviceIdElement = rootElement.element("DeviceID");
transaction.sendResponse(response); String deviceId = deviceIdElement.getText().toString();
publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); recordInfo.setDeviceId(deviceId);
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { recordInfo.setName(XmlUtil.getText(rootElement,"Name"));
recordInfo.setSumNum(Integer.parseInt(XmlUtil.getText(rootElement,"SumNum")));
Element recordListElement = rootElement.element("RecordList");
if (recordListElement == null) {
return;
}
Iterator<Element> recordListIterator = recordListElement.elementIterator();
if (recordListIterator != null) {
List<RecordItem> recordList = new ArrayList<RecordItem>();
RecordItem record = new RecordItem();
// 遍历DeviceList
while (recordListIterator.hasNext()) {
Element itemRecord = recordListIterator.next();
Element recordElement = itemRecord.element("DeviceID");
if (recordElement == null) {
continue;
}
record.setDeviceId(XmlUtil.getText(itemRecord,"DeviceID"));
record.setName(XmlUtil.getText(itemRecord,"Name"));
record.setFilePath(XmlUtil.getText(itemRecord,"FilePath"));
record.setAddress(XmlUtil.getText(itemRecord,"Address"));
record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord,"StartTime")));
record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord,"EndTime")));
record.setSecrecy(itemRecord.element("Secrecy") == null? 0:Integer.parseInt(XmlUtil.getText(itemRecord,"Secrecy")));
record.setType(XmlUtil.getText(itemRecord,"Type"));
record.setRecordId(XmlUtil.getText(itemRecord,"RecordID"));
recordList.add(record);
}
recordInfo.setRecordList(recordList);
}
RequestMessage msg = new RequestMessage();
msg.setDeviceId(deviceId);
msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
msg.setData(recordInfo);
deferredResultHolder.invokeResult(msg);
} catch (DocumentException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
private Element getRootElement(RequestEvent evt) throws DocumentException {
Request request = evt.getRequest();
SAXReader reader = new SAXReader();
reader.setEncoding("GB2312");
Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
return xml.getRootElement();
}
} }

6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java

@ -25,10 +25,10 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.SipLayer; import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Host; import com.genersoft.iot.vmp.gb28181.bean.Host;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
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.ISIPRequestProcessor;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@ -48,7 +48,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
private SipConfig config; private SipConfig config;
@Autowired @Autowired
private SIPCommander cmder; private RegisterLogicHandler handler;
@Autowired @Autowired
private IVideoManagerStorager storager; private IVideoManagerStorager storager;
@ -149,7 +149,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
System.out.println("注册成功! deviceId:" + device.getDeviceId()); System.out.println("注册成功! deviceId:" + device.getDeviceId());
storager.update(device); storager.update(device);
publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER); publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
cmder.deviceInfoQuery(device); handler.onRegister(device);
} else if (registerFlag == 2) { } else if (registerFlag == 2) {
System.out.println("注销成功! deviceId:" + device.getDeviceId()); System.out.println("注销成功! deviceId:" + device.getDeviceId());
publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);

40
src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java

@ -0,0 +1,40 @@
package com.genersoft.iot.vmp.gb28181.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
/**
* @Description:时间工具类主要处理ISO 8601格式转换
* @author: songww
* @date: 2020年5月8日 下午3:24:42
*/
public class DateUtil {
private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
private static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {
SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());
SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());
try {
return newsdf.format(oldsdf.parse(formatTime));
} catch (ParseException e) {
e.printStackTrace();
}
return "";
}
public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) {
SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());
SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());
try {
return newsdf.format(oldsdf.parse(formatTime));
} catch (ParseException e) {
e.printStackTrace();
}
return "";
}
}

152
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@ -0,0 +1,152 @@
package com.genersoft.iot.vmp.media.zlm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:针对 ZLMediaServer的hook事件监听
* @author: songww
* @date: 2020年5月8日 上午10:46:48
*/
@RestController
@RequestMapping("/hook/zlm")
public class ZLMHttpHookListener {
private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
/**
* 流量统计事件播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件阈值通过配置文件general.flowThreshold配置此事件对回复不敏感
*
*/
@PostMapping("/on_flow_report")
public ResponseEntity onFlowReport(){
// TODO Auto-generated method stub
return null;
}
/**
* 访问http文件服务器上hls之外的文件时触发
*
*/
@PostMapping("/on_http_access")
public ResponseEntity onHttpAccess(){
// TODO Auto-generated method stub
return null;
}
/**
* 播放器鉴权事件rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件
*
*/
@PostMapping("/on_play")
public ResponseEntity onPlay(){
// TODO Auto-generated method stub
return null;
}
/**
* rtsp/rtmp/rtp推流鉴权事件
*
*/
@PostMapping("/on_publish")
public ResponseEntity onPublish(){
// TODO Auto-generated method stub
return null;
}
/**
* 录制mp4完成后通知事件此事件对回复不敏感
*
*/
@PostMapping("/on_record_mp4")
public ResponseEntity onRecordMp4(){
// TODO Auto-generated method stub
return null;
}
/**
* 该rtsp流是否开启rtsp专用方式的鉴权事件开启后才会触发on_rtsp_auth事件需要指出的是rtsp也支持url参数鉴权它支持两种方式鉴权
*
*/
@PostMapping("/on_rtsp_auth")
public ResponseEntity onRtspAuth(){
// TODO Auto-generated method stub
return null;
}
/**
* rtsp专用的鉴权事件先触发on_rtsp_realm事件然后才会触发on_rtsp_auth事件
*
*/
@PostMapping("/on_rtsp_realm")
public ResponseEntity onRtspRealm(){
// TODO Auto-generated method stub
return null;
}
/**
* shell登录鉴权ZLMediaKit提供简单的telnet调试方式使用telnet 127.0.0.1 9000能进入MediaServer进程的shell界面
*
*/
@PostMapping("/on_shell_login")
public ResponseEntity onShellLogin(){
// TODO Auto-generated method stub
return null;
}
/**
* rtsp/rtmp流注册或注销时触发此事件此事件对回复不敏感
*
*/
@PostMapping("/on_stream_changed")
public ResponseEntity onStreamChanged(){
// TODO Auto-generated method stub
return null;
}
/**
* 流无人观看时事件用户可以通过此事件选择是否关闭无人看的流
*
*/
@PostMapping("/on_stream_none_reader")
public ResponseEntity onStreamNoneReader(){
// TODO Auto-generated method stub
return null;
}
/**
* 流未找到事件用户可以在此事件触发时立即去拉流这样可以实现按需拉流此事件对回复不敏感
*
*/
@PostMapping("/on_stream_not_found")
public ResponseEntity onStreamNotFound(){
// TODO Auto-generated method stub
return null;
}
/**
* 服务器启动事件可以用于监听服务器崩溃重启此事件对回复不敏感
*
*/
@PostMapping("/on_server_started")
public ResponseEntity onServerStarted(){
// TODO Auto-generated method stub
return null;
}
}

34
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java

@ -1,7 +1,8 @@
package com.genersoft.iot.vmp.vmanager.device; package com.genersoft.iot.vmp.vmanager.device;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -10,10 +11,14 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@RestController @RestController
@ -25,16 +30,21 @@ public class DeviceController {
@Autowired @Autowired
private IVideoManagerStorager storager; private IVideoManagerStorager storager;
@Autowired
private SIPCommander cmder;
@Autowired
private DeferredResultHolder resultHolder;
@GetMapping("/devices/{deviceId}") @GetMapping("/devices/{deviceId}")
public ResponseEntity<List<Device>> devices(@PathVariable String deviceId){ public ResponseEntity<Device> devices(@PathVariable String deviceId){
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("查询视频设备API调用,deviceId:" + deviceId); logger.debug("查询视频设备API调用,deviceId:" + deviceId);
} }
List<Device> deviceList = new ArrayList<>(); Device device = storager.queryVideoDevice(deviceId);
deviceList.add(storager.queryVideoDevice(deviceId)); return new ResponseEntity<>(device,HttpStatus.OK);
return new ResponseEntity<>(deviceList,HttpStatus.OK);
} }
@GetMapping("/devices") @GetMapping("/devices")
@ -47,4 +57,18 @@ public class DeviceController {
List<Device> deviceList = storager.queryVideoDeviceList(null); List<Device> deviceList = storager.queryVideoDeviceList(null);
return new ResponseEntity<>(deviceList,HttpStatus.OK); return new ResponseEntity<>(deviceList,HttpStatus.OK);
} }
@PostMapping("/devices/{deviceId}/sync")
public DeferredResult<ResponseEntity<Device>> devicesSync(@PathVariable String deviceId){
if (logger.isDebugEnabled()) {
logger.debug("设备信息同步API调用,deviceId:" + deviceId);
}
Device device = storager.queryVideoDevice(deviceId);
cmder.catalogQuery(device);
DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>();
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
return result;
}
} }

8
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java

@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api")
@ -21,10 +23,14 @@ public class PlayController {
@Autowired @Autowired
private SIPCommander cmder; private SIPCommander cmder;
@Autowired
private IVideoManagerStorager storager;
@GetMapping("/play/{deviceId}_{channelId}") @GetMapping("/play/{deviceId}_{channelId}")
public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){ public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){
String ssrc = cmder.playStreamCmd(deviceId, channelId); Device device = storager.queryVideoDevice(deviceId);
String ssrc = cmder.playStreamCmd(device, channelId);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId)); logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId));

8
src/main/java/com/genersoft/iot/vmp/vmanager/ptz/PtzController.java

@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api")
@ -21,6 +23,9 @@ public class PtzController {
@Autowired @Autowired
private SIPCommander cmder; private SIPCommander cmder;
@Autowired
private IVideoManagerStorager storager;
/*** /***
* http://localhost:8080/api/ptz/34020000001320000002_34020000001320000008?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=0 * http://localhost:8080/api/ptz/34020000001320000002_34020000001320000008?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=0
* @param deviceId * @param deviceId
@ -38,8 +43,9 @@ public class PtzController {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,leftRight:%d ,upDown:%d ,inOut:%d ,moveSpeed:%d ,zoomSpeed:%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed)); logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,leftRight:%d ,upDown:%d ,inOut:%d ,moveSpeed:%d ,zoomSpeed:%d",deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed));
} }
Device device = storager.queryVideoDevice(deviceId);
cmder.ptzCmd(deviceId, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed); cmder.ptzCmd(device, channelId, leftRight, upDown, inOut, moveSpeed, zoomSpeed);
return new ResponseEntity<String>("success",HttpStatus.OK); return new ResponseEntity<String>("success",HttpStatus.OK);
} }
} }

47
src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java

@ -0,0 +1,47 @@
package com.genersoft.iot.vmp.vmanager.record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@RestController
@RequestMapping("/api")
public class RecordController {
private final static Logger logger = LoggerFactory.getLogger(RecordController.class);
@Autowired
private SIPCommander cmder;
@Autowired
private IVideoManagerStorager storager;
@Autowired
private DeferredResultHolder resultHolder;
@GetMapping("/recordinfo/{deviceId}")
public DeferredResult<ResponseEntity<RecordInfo>> recordinfo(@PathVariable String deviceId, String startTime, String endTime){
if (logger.isDebugEnabled()) {
logger.debug(String.format("录像信息 API调用,deviceId:%s ,startTime:%s, startTime:%s",deviceId, startTime, endTime));
}
Device device = storager.queryVideoDevice(deviceId);
cmder.recordInfoQuery(device, startTime, endTime);
DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<ResponseEntity<RecordInfo>>();
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
return result;
}
}
Loading…
Cancel
Save