| | |
| | | import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
|
| | |
|
| | | /**
|
| | | * @Description:Redis中间件配置类
|
| | | * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
| | | * @author: songww
|
| | | * @date: 2019年5月30日 上午10:58:25
|
| | | *
|
| | | */
|
| | | @Configuration
|
| | | // @EnableCaching
|
| | | public class RedisConfig extends CachingConfigurerSupport {
|
| | |
|
| | | @Bean("redisTemplate")
|
| | | public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
| | | RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
| | | template.setConnectionFactory(redisConnectionFactory);
|
| | | ParserConfig.getGlobalInstance().setAutoTypeSupport(true); |
| | | // 使用fastjson进行序列化处理,提高解析效率
|
| | | FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<Object>(Object.class);
|
| | | // value值的序列化采用fastJsonRedisSerializer
|
| | | template.setValueSerializer(serializer);
|
| | |
| | | // key的序列化采用StringRedisSerializer
|
| | | template.setKeySerializer(new StringRedisSerializer());
|
| | | template.setHashKeySerializer(new StringRedisSerializer());
|
| | |
|
| | | template.setConnectionFactory(redisConnectionFactory);
|
| | | // 使用fastjson时需设置此项,否则会报异常not support type
|
| | | ParserConfig.getGlobalInstance().setAutoTypeSupport(true); |
| | | return template;
|
| | | }
|
| | |
|
| | |
| | | container.setConnectionFactory(connectionFactory);
|
| | | 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");
|
| | | // }
|
| | |
|
| | | }
|
| | |
| | | String sipPassword; |
| | | @Value("${media.ip}") |
| | | String mediaIp; |
| | | |
| | | @Value("${media.port}") |
| | | Integer mediaPort; |
| | | |
| | |
| | | |
| | | import java.util.Properties; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import javax.sip.DialogTerminatedEvent; |
| | | import javax.sip.IOExceptionEvent; |
| | | import javax.sip.ListeningPoint; |
| | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import com.genersoft.iot.vmp.conf.SipConfig; |
| | |
| | | import gov.nist.javax.sip.SipStackImpl; |
| | | |
| | | @Component |
| | | public class SipLayer implements SipListener{ |
| | | |
| | | public class SipLayer implements SipListener, Runnable { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); |
| | | |
| | | |
| | | @Autowired |
| | | private SipConfig config; |
| | | |
| | | |
| | | private SipProvider tcpSipProvider; |
| | | |
| | | |
| | | private SipProvider udpSipProvider; |
| | | |
| | | |
| | | @Autowired |
| | | private SIPProcessorFactory processorFactory; |
| | | |
| | | |
| | | private SipStack sipStack; |
| | | |
| | | |
| | | private AddressFactory addressFactory; |
| | | private HeaderFactory headerFactory; |
| | | private MessageFactory messageFactory; |
| | | |
| | | @Bean |
| | | private boolean initSipServer() throws Exception { |
| | | @PostConstruct |
| | | 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.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 { |
| | | 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(); |
| | | startUdpListener(); |
| | | } catch (Exception e) { |
| | | logger.error("Sip Server 启动失败! port {"+config.getSipPort()+"}"); |
| | | logger.error("Sip Server 启动失败! port {" + config.getSipPort() + "}"); |
| | | e.printStackTrace(); |
| | | throw e; |
| | | } |
| | | logger.info("Sip Server 启动成功 port {"+config.getSipPort()+"}"); |
| | | return true; |
| | | logger.info("Sip Server 启动成功 port {" + config.getSipPort() + "}"); |
| | | } |
| | | |
| | | |
| | | private void startTcpListener() throws Exception { |
| | | ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "TCP"); |
| | | tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint); |
| | | tcpSipProvider.addSipListener(this); |
| | | } |
| | | |
| | | private void startUdpListener() throws Exception { |
| | | } |
| | | |
| | | private void startUdpListener() throws Exception { |
| | | ListeningPoint udpListeningPoint = sipStack.createListeningPoint(config.getSipIp(), config.getSipPort(), "UDP"); |
| | | udpSipProvider = sipStack.createSipProvider(udpListeningPoint); |
| | | udpSipProvider.addSipListener(this); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * SIP服务端接收消息的方法 Content 里面是GBK编码 This method is called by the SIP stack when a |
| | |
| | | int status = response.getStatusCode(); |
| | | if ((status >= 200) && (status < 300)) { // Success! |
| | | ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); |
| | | processor.process(evt,this,config); |
| | | processor.process(evt, this, config); |
| | | } else { |
| | | logger.warn("接收到失败的response响应!status:"+status+",message:"+response.getContent().toString()); |
| | | logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getContent().toString()); |
| | | } |
| | | //trying不会回复 |
| | | if(status == Response.TRYING){ |
| | | // trying不会回复 |
| | | if (status == Response.TRYING) { |
| | | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * <p>Title: processTimeout</p> |
| | | * <p>Description: </p> |
| | | * @param timeoutEvent |
| | | */ |
| | | /** |
| | | * <p> |
| | | * Title: processTimeout |
| | | * </p> |
| | | * <p> |
| | | * Description: |
| | | * </p> |
| | | * |
| | | * @param timeoutEvent |
| | | */ |
| | | @Override |
| | | public void processTimeout(TimeoutEvent timeoutEvent) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | |
| | | } |
| | | |
| | | /** |
| | | * <p>Title: processIOException</p> |
| | | * <p>Description: </p> |
| | | * @param exceptionEvent |
| | | */ |
| | | /** |
| | | * <p> |
| | | * Title: processIOException |
| | | * </p> |
| | | * <p> |
| | | * Description: |
| | | * </p> |
| | | * |
| | | * @param exceptionEvent |
| | | */ |
| | | @Override |
| | | public void processIOException(IOExceptionEvent exceptionEvent) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | |
| | | } |
| | | |
| | | /** |
| | | * <p>Title: processTransactionTerminated</p> |
| | | * <p>Description: </p> |
| | | * @param transactionTerminatedEvent |
| | | */ |
| | | /** |
| | | * <p> |
| | | * Title: processTransactionTerminated |
| | | * </p> |
| | | * <p> |
| | | * Description: |
| | | * </p> |
| | | * |
| | | * @param transactionTerminatedEvent |
| | | */ |
| | | @Override |
| | | public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | |
| | | } |
| | | |
| | | /** |
| | | * <p>Title: processDialogTerminated</p> |
| | | * <p>Description: </p> |
| | | * @param dialogTerminatedEvent |
| | | */ |
| | | /** |
| | | * <p> |
| | | * Title: processDialogTerminated |
| | | * </p> |
| | | * <p> |
| | | * Description: |
| | | * </p> |
| | | * |
| | | * @param dialogTerminatedEvent |
| | | */ |
| | | @Override |
| | | public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | private ServerTransaction getServerTransaction(RequestEvent evt) { |
| | | Request request = evt.getRequest(); |
| | | ServerTransaction serverTransaction = evt.getServerTransaction(); |
| | |
| | | |
| | | if (serverTransaction == null) { |
| | | try { |
| | | if (isTcp) { |
| | | serverTransaction = tcpSipProvider.getNewServerTransaction(request); |
| | | } else { |
| | | serverTransaction = udpSipProvider.getNewServerTransaction(request); |
| | | } |
| | | if (isTcp) { |
| | | serverTransaction = tcpSipProvider.getNewServerTransaction(request); |
| | | } else { |
| | | serverTransaction = udpSipProvider.getNewServerTransaction(request); |
| | | } |
| | | } catch (TransactionAlreadyExistsException e) { |
| | | e.printStackTrace(); |
| | | } catch (TransactionUnavailableException e) { |
| | |
| | | } |
| | | return serverTransaction; |
| | | } |
| | | |
| | | |
| | | public AddressFactory getAddressFactory() { |
| | | return addressFactory; |
| | |
| | | public SipProvider getUdpSipProvider() { |
| | | return udpSipProvider; |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | 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);
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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));
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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;
|
| | | }
|
| | | }
|
| | |
| | | /**
|
| | | * 云台方向放控制,使用配置文件中的默认镜头移动速度
|
| | | *
|
| | | * @param deviceId 控制设备
|
| | | * @param device 控制设备
|
| | | * @param channelId 预览通道
|
| | | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
| | | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
| | | * @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 leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
| | | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
| | | * @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 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 inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
| | | * @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 leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
| | | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
| | |
| | | * @param moveSpeed 镜头移动速度
|
| | | * @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 预览通道
|
| | | */
|
| | | public String playStreamCmd(String deviceId,String channelId);
|
| | | public String playStreamCmd(Device device,String channelId);
|
| | |
|
| | | /**
|
| | | * 语音广播
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | */
|
| | | public String audioBroadcastCmd(String deviceId,String channelId);
|
| | | public boolean audioBroadcastCmd(Device device,String channelId);
|
| | |
|
| | | /**
|
| | | * 音视频录像控制
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @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帧
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @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);
|
| | |
|
| | |
|
| | | /**
|
| | |
| | | * 查询录像信息
|
| | | *
|
| | | * @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);
|
| | |
|
| | | /**
|
| | | * 查询报警信息
|
| | |
| | | import javax.sip.message.Request;
|
| | |
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | | import org.springframework.context.ApplicationEventPublisher;
|
| | | import org.springframework.stereotype.Component;
|
| | |
|
| | | import com.genersoft.iot.vmp.conf.SipConfig;
|
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device;
|
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
| | | 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:设备能力接口,用于定义设备的控制、查询能力
|
| | |
| | | @Autowired
|
| | | private SipLayer sipLayer;
|
| | |
|
| | | @Autowired
|
| | | private IVideoManagerStorager storager;
|
| | | |
| | | /**
|
| | | * 云台方向放控制,使用配置文件中的默认镜头移动速度
|
| | | *
|
| | | * @param deviceId 控制设备
|
| | | * @param device 控制设备
|
| | | * @param channelId 预览通道
|
| | | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
| | | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
| | | * @param moveSpeed 镜头移动速度
|
| | | */
|
| | | @Override
|
| | | public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown) {
|
| | | return ptzCmd(deviceId, channelId, leftRight, upDown, 0, config.getSpeed(), 0);
|
| | | public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) {
|
| | | return ptzCmd(device, channelId, leftRight, upDown, 0, config.getSpeed(), 0);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 云台方向放控制
|
| | | *
|
| | | * @param deviceId 控制设备
|
| | | * @param device 控制设备
|
| | | * @param channelId 预览通道
|
| | | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
| | | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
| | | * @param moveSpeed 镜头移动速度
|
| | | */
|
| | | @Override
|
| | | public boolean ptzdirectCmd(String deviceId, String channelId, int leftRight, int upDown, int moveSpeed) {
|
| | | return ptzCmd(deviceId, channelId, leftRight, upDown, 0, moveSpeed, 0);
|
| | | public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) {
|
| | | return ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 云台缩放控制,使用配置文件中的默认镜头缩放速度
|
| | | *
|
| | | * @param deviceId 控制设备
|
| | | * @param device 控制设备
|
| | | * @param channelId 预览通道
|
| | | * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
| | | */
|
| | | @Override
|
| | | public boolean ptzZoomCmd(String deviceId, String channelId, int inOut) {
|
| | | return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, config.getSpeed());
|
| | | public boolean ptzZoomCmd(Device device, String channelId, int inOut) {
|
| | | return ptzCmd(device, channelId, 0, 0, inOut, 0, config.getSpeed());
|
| | | }
|
| | |
|
| | | /**
|
| | | * 云台缩放控制
|
| | | *
|
| | | * @param deviceId 控制设备
|
| | | * @param device 控制设备
|
| | | * @param channelId 预览通道
|
| | | * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
| | | * @param zoomSpeed 镜头缩放速度
|
| | | */
|
| | | @Override
|
| | | public boolean ptzZoomCmd(String deviceId, String channelId, int inOut, int zoomSpeed) {
|
| | | return ptzCmd(deviceId, channelId, 0, 0, inOut, 0, zoomSpeed);
|
| | | public boolean ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) {
|
| | | return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 云台控制,支持方向与缩放控制
|
| | | *
|
| | | * @param deviceId 控制设备
|
| | | * @param device 控制设备
|
| | | * @param channelId 预览通道
|
| | | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
| | | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
| | |
| | | * @param zoomSpeed 镜头缩放速度
|
| | | */
|
| | | @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) {
|
| | | try {
|
| | | Device device = storager.queryVideoDevice(deviceId);
|
| | | StringBuffer ptzXml = new StringBuffer(200);
|
| | | ptzXml.append("<?xml version=\"1.0\" ?>");
|
| | | ptzXml.append("<Control>");
|
| | |
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
|
| | |
|
| | | transmitRequest(device.getTransport(), request);
|
| | | transmitRequest(device, request);
|
| | |
|
| | | return true;
|
| | | } catch (SipException | ParseException | InvalidArgumentException e) {
|
| | |
| | | /**
|
| | | * 请求预览视频流
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | */
|
| | | @Override
|
| | | public String playStreamCmd(String deviceId, String channelId) {
|
| | | public String playStreamCmd(Device device, String channelId) {
|
| | | try {
|
| | | |
| | | Device device = storager.queryVideoDevice(deviceId);
|
| | |
|
| | | //生成ssrc标识数据流 10位数字
|
| | | String ssrc = "";
|
| | |
| | |
|
| | | Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
|
| | |
|
| | | transmitRequest(device.getTransport(), request);
|
| | | transmitRequest(device, request);
|
| | | return ssrc;
|
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | |
| | | /**
|
| | | * 语音广播
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | */
|
| | | @Override
|
| | | public String audioBroadcastCmd(String deviceId, String channelId) {
|
| | | public boolean audioBroadcastCmd(Device device, String channelId) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 音视频录像控制
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | */
|
| | | @Override
|
| | | public String recordCmd(String deviceId, String channelId) {
|
| | | public boolean recordCmd(Device device, String channelId) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 报警布防/撤防命令
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | */
|
| | | @Override
|
| | | public String guardCmd(String deviceId) {
|
| | | public boolean guardCmd(Device device) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 报警复位命令
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | */
|
| | | @Override
|
| | | public String alarmCmd(String deviceId) {
|
| | | public boolean alarmCmd(Device device) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | */
|
| | | @Override
|
| | | public String iFameCmd(String deviceId, String channelId) {
|
| | | public boolean iFameCmd(Device device, String channelId) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 看守位控制命令
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | */
|
| | | @Override
|
| | | public String homePositionCmd(String deviceId) {
|
| | | public boolean homePositionCmd(Device device) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设备配置命令
|
| | | *
|
| | | * @param deviceId 视频设备
|
| | | * @param device 视频设备
|
| | | */
|
| | | @Override
|
| | | public String deviceConfigCmd(String deviceId) {
|
| | | public boolean deviceConfigCmd(Device device) {
|
| | | // TODO Auto-generated method stub
|
| | | return null;
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | catalogXml.append("</Query>");
|
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag");
|
| | | transmitRequest(device, request);
|
| | |
|
| | | transmitRequest(device.getTransport(), request);
|
| | | } catch (SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | | return false;
|
| | |
| | | catalogXml.append("</Query>");
|
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag");
|
| | | |
| | | transmitRequest(device.getTransport(), request);
|
| | |
|
| | | transmitRequest(device, request);
|
| | | } catch (SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | | return false;
|
| | |
| | | * 查询录像信息
|
| | | *
|
| | | * @param device 视频设备
|
| | | * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
| | | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
| | | */
|
| | | @Override
|
| | | public boolean recordInfoQuery(Device device) {
|
| | | // TODO Auto-generated method stub
|
| | | return false;
|
| | | public boolean recordInfoQuery(Device device, String startTime, String endTime) {
|
| | | |
| | | 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;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | private void transmitRequest(String transport, Request request) throws SipException {
|
| | | if(transport.equals("TCP")) {
|
| | | private void transmitRequest(Device device, Request request) throws SipException {
|
| | | if(device.getTransport().equals("TCP")) {
|
| | | sipLayer.getTcpSipProvider().sendRequest(request);
|
| | | } else if(transport.equals("UDP")) {
|
| | | } else if(device.getTransport().equals("UDP")) {
|
| | | sipLayer.getUdpSipProvider().sendRequest(request);
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | import java.io.ByteArrayInputStream;
|
| | | import java.text.ParseException;
|
| | | import java.util.ArrayList;
|
| | | import java.util.HashMap;
|
| | | import java.util.Iterator;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | |
|
| | | import javax.sip.InvalidArgumentException;
|
| | |
| | | import com.genersoft.iot.vmp.gb28181.SipLayer;
|
| | | import com.genersoft.iot.vmp.gb28181.bean.Device;
|
| | | 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.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.request.ISIPRequestProcessor;
|
| | | import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
| | | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
| | |
|
| | |
| | | @Autowired
|
| | | private EventPublisher publisher;
|
| | |
|
| | | @Autowired
|
| | | private DeferredResultHolder deferredResultHolder;
|
| | | |
| | | /**
|
| | | * 处理MESSAGE请求
|
| | | *
|
| | |
| | | processMessageDeviceInfo(evt);
|
| | | } else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) {
|
| | | 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();
|
| | | }
|
| | | }
|
| | |
|
| | | /***
|
| | |
| | | */
|
| | | private void processMessageCatalogList(RequestEvent evt) {
|
| | | try {
|
| | | Request request = evt.getRequest();
|
| | | SAXReader reader = new SAXReader();
|
| | | reader.setEncoding("GB2312");
|
| | | Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
| | | Element rootElement = xml.getRootElement();
|
| | | Element rootElement = getRootElement(evt);
|
| | | Element deviceIdElement = rootElement.element("DeviceID");
|
| | | String deviceId = deviceIdElement.getText().toString();
|
| | | Element deviceListElement = rootElement.element("DeviceList");
|
| | |
| | | }
|
| | | // 更新
|
| | | 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) {
|
| | | e.printStackTrace();
|
| | | }
|
| | | }
|
| | | |
| | | /***
|
| | | * 收到deviceInfo设备信息请求 处理
|
| | | * @param evt
|
| | | */
|
| | | private void processMessageDeviceInfo(RequestEvent evt) {
|
| | | try {
|
| | | Request request = evt.getRequest();
|
| | | SAXReader reader = new SAXReader();
|
| | | // reader.setEncoding("GB2312");
|
| | | Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
| | | Element rootElement = xml.getRootElement();
|
| | | 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);
|
| | | cmder.catalogQuery(device);
|
| | | } catch (DocumentException e) {
|
| | | e.printStackTrace();
|
| | | }
|
| | |
| | | */
|
| | | private void processMessageAlarm(RequestEvent evt) {
|
| | | try {
|
| | | Request request = evt.getRequest();
|
| | | SAXReader reader = new SAXReader();
|
| | | // reader.setEncoding("GB2312");
|
| | | Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
| | | Element rootElement = xml.getRootElement();
|
| | | Element rootElement = getRootElement(evt);
|
| | | Element deviceIdElement = rootElement.element("DeviceID");
|
| | | String deviceId = deviceIdElement.getText().toString();
|
| | |
|
| | |
| | | try {
|
| | | Request request = evt.getRequest();
|
| | | Response response = layer.getMessageFactory().createResponse(Response.OK,request);
|
| | | SAXReader reader = new SAXReader();
|
| | | Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
| | | // reader.setEncoding("GB2312");
|
| | | Element rootElement = xml.getRootElement();
|
| | | Element rootElement = getRootElement(evt);
|
| | | Element deviceIdElement = rootElement.element("DeviceID");
|
| | | transaction.sendResponse(response);
|
| | | publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
| | |
| | | e.printStackTrace();
|
| | | }
|
| | | }
|
| | | |
| | | /***
|
| | | * 收到catalog设备目录列表请求 处理
|
| | | * @param evt
|
| | | */
|
| | | private void processMessageRecordInfo(RequestEvent evt) {
|
| | | try {
|
| | | RecordInfo recordInfo = new RecordInfo();
|
| | | Element rootElement = getRootElement(evt);
|
| | | Element deviceIdElement = rootElement.element("DeviceID");
|
| | | String deviceId = deviceIdElement.getText().toString();
|
| | | recordInfo.setDeviceId(deviceId);
|
| | | 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();
|
| | | }
|
| | | }
|
| | | |
| | | 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();
|
| | | }
|
| | |
|
| | | }
|
| | |
| | | import com.genersoft.iot.vmp.conf.SipConfig;
|
| | | import com.genersoft.iot.vmp.gb28181.SipLayer;
|
| | | 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.Host;
|
| | | 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.storager.IVideoManagerStorager;
|
| | |
|
| | |
| | | private SipConfig config;
|
| | |
|
| | | @Autowired
|
| | | private SIPCommander cmder;
|
| | | private RegisterLogicHandler handler;
|
| | |
|
| | | @Autowired
|
| | | private IVideoManagerStorager storager;
|
| | |
| | | System.out.println("注册成功! deviceId:" + device.getDeviceId());
|
| | | storager.update(device);
|
| | | publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
|
| | | cmder.deviceInfoQuery(device);
|
| | | handler.onRegister(device);
|
| | | } else if (registerFlag == 2) {
|
| | | System.out.println("注销成功! deviceId:" + device.getDeviceId());
|
| | | publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
|
New file |
| | |
| | | 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 "";
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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;
|
| | | }
|
| | | }
|
| | |
| | | package com.genersoft.iot.vmp.vmanager.device; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | |
| | | 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.PostMapping; |
| | | 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.transmit.callback.DeferredResultHolder; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| | | |
| | | @RestController |
| | |
| | | @Autowired |
| | | private IVideoManagerStorager storager; |
| | | |
| | | @Autowired |
| | | private SIPCommander cmder; |
| | | |
| | | @Autowired |
| | | private DeferredResultHolder resultHolder; |
| | | |
| | | @GetMapping("/devices/{deviceId}") |
| | | public ResponseEntity<List<Device>> devices(@PathVariable String deviceId){ |
| | | public ResponseEntity<Device> devices(@PathVariable String deviceId){ |
| | | |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug("查询视频设备API调用,deviceId:" + deviceId); |
| | | } |
| | | |
| | | List<Device> deviceList = new ArrayList<>(); |
| | | deviceList.add(storager.queryVideoDevice(deviceId)); |
| | | return new ResponseEntity<>(deviceList,HttpStatus.OK); |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | return new ResponseEntity<>(device,HttpStatus.OK); |
| | | } |
| | | |
| | | @GetMapping("/devices") |
| | |
| | | List<Device> deviceList = storager.queryVideoDeviceList(null); |
| | | 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; |
| | | } |
| | | } |
| | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | 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.storager.IVideoManagerStorager; |
| | | |
| | | @RestController |
| | | @RequestMapping("/api") |
| | |
| | | @Autowired |
| | | private SIPCommander cmder; |
| | | |
| | | @Autowired |
| | | private IVideoManagerStorager storager; |
| | | |
| | | @GetMapping("/play/{deviceId}_{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()) { |
| | | logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId)); |
| | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | 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.storager.IVideoManagerStorager; |
| | | |
| | | @RestController |
| | | @RequestMapping("/api") |
| | |
| | | |
| | | @Autowired |
| | | private SIPCommander cmder; |
| | | |
| | | @Autowired |
| | | private IVideoManagerStorager storager; |
| | | |
| | | /*** |
| | | * http://localhost:8080/api/ptz/34020000001320000002_34020000001320000008?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=0 |
| | |
| | | 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)); |
| | | } |
| | | 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); |
| | | } |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
| | | } |