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

This commit is contained in:
songww
2020-05-08 21:57:07 +08:00
parent ab45f1a13f
commit bf7ab3fe2b
18 changed files with 871 additions and 237 deletions

View File

@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.ListeningPoint;
@@ -26,7 +27,6 @@ import javax.sip.message.Response;
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;
@@ -37,70 +37,78 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
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
@@ -118,60 +126,80 @@ public class SipLayer implements SipListener{
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();
@@ -185,11 +213,11 @@ public class SipLayer implements SipListener{
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) {
@@ -199,7 +227,6 @@ public class SipLayer implements SipListener{
return serverTransaction;
}
public AddressFactory getAddressFactory() {
return addressFactory;
}
@@ -219,5 +246,5 @@ public class SipLayer implements SipListener{
public SipProvider getUdpSipProvider() {
return udpSipProvider;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,48 +12,48 @@ public interface ISIPCommander {
/**
* 云台方向放控制,使用配置文件中的默认镜头移动速度
*
* @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:下移
@@ -61,67 +61,67 @@ public interface ISIPCommander {
* @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);
/**
@@ -150,8 +150,10 @@ public interface ISIPCommander {
* 查询录像信息
*
* @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);
/**
* 查询报警信息

View File

@@ -8,6 +8,7 @@ import javax.sip.SipException;
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;
@@ -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.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:设备能力接口,用于定义设备的控制、查询能力
@@ -34,66 +35,63 @@ public class SIPCommander implements ISIPCommander {
@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:下移
@@ -102,10 +100,9 @@ public class SIPCommander implements ISIPCommander {
* @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>");
@@ -119,7 +116,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
transmitRequest(device.getTransport(), request);
transmitRequest(device, request);
return true;
} catch (SipException | ParseException | InvalidArgumentException e) {
@@ -131,15 +128,13 @@ public class SIPCommander implements ISIPCommander {
/**
* 请求预览视频流
*
* @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 = "";
Random random = new Random();
@@ -170,7 +165,7 @@ public class SIPCommander implements ISIPCommander {
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();
@@ -181,81 +176,81 @@ public class SIPCommander implements ISIPCommander {
/**
* 语音广播
*
* @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;
}
/**
@@ -286,8 +281,8 @@ public class SIPCommander implements ISIPCommander {
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;
@@ -312,9 +307,7 @@ public class SIPCommander implements ISIPCommander {
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;
@@ -326,11 +319,32 @@ public class SIPCommander implements ISIPCommander {
* 查询录像信息
*
* @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;
}
/**
@@ -377,10 +391,10 @@ public class SIPCommander implements ISIPCommander {
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);
}
}

View File

@@ -2,8 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl;
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;
@@ -24,9 +26,14 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
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;
@@ -51,6 +58,9 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
@Autowired
private EventPublisher publisher;
@Autowired
private DeferredResultHolder deferredResultHolder;
/**
* 处理MESSAGE请求
*
@@ -74,21 +84,49 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
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();
}
}
/***
* 收到catalog设备目录列表请求 处理
* @param evt
*/
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");
@@ -152,52 +190,24 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
}
// 更新
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();
}
}
/***
* 收到alarm设备报警信息 处理
* @param evt
*/
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();
@@ -224,10 +234,7 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
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);
@@ -235,5 +242,68 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
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();
}
}

View File

@@ -25,10 +25,10 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
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;
@@ -48,7 +48,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
private SipConfig config;
@Autowired
private SIPCommander cmder;
private RegisterLogicHandler handler;
@Autowired
private IVideoManagerStorager storager;
@@ -149,7 +149,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
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);

View File

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