forked from Thirdparty/wvp
增加设备删除接口,只允许删除离线设备;增加视频停止播放接口
parent
ca5139929b
commit
6ecd801c23
|
@ -12,6 +12,8 @@ public class SipConfig {
|
||||||
Integer sipPort;
|
Integer sipPort;
|
||||||
@Value("${sip.domain}")
|
@Value("${sip.domain}")
|
||||||
String sipDomain;
|
String sipDomain;
|
||||||
|
@Value("${sip.id}")
|
||||||
|
String sipId;
|
||||||
@Value("${sip.password}")
|
@Value("${sip.password}")
|
||||||
String sipPassword;
|
String sipPassword;
|
||||||
@Value("${media.ip}")
|
@Value("${media.ip}")
|
||||||
|
@ -77,6 +79,12 @@ public class SipConfig {
|
||||||
public void setSpeed(Integer speed) {
|
public void setSpeed(Integer speed) {
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSipId() {
|
||||||
|
return sipId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSipId(String sipId) {
|
||||||
|
this.sipId = sipId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class SipLayer implements SipListener, Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void processRequest(RequestEvent evt) {
|
public void processRequest(RequestEvent evt) {
|
||||||
ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt);
|
ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt);
|
||||||
processor.process(evt, this, getServerTransaction(evt));
|
processor.process(evt, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -200,7 +200,7 @@ public class SipLayer implements SipListener, Runnable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerTransaction getServerTransaction(RequestEvent evt) {
|
public ServerTransaction getServerTransaction(RequestEvent evt) {
|
||||||
Request request = evt.getRequest();
|
Request request = evt.getRequest();
|
||||||
ServerTransaction serverTransaction = evt.getServerTransaction();
|
ServerTransaction serverTransaction = evt.getServerTransaction();
|
||||||
// 判断TCP还是UDP
|
// 判断TCP还是UDP
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.utils;
|
package com.genersoft.iot.vmp.gb28181.session;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.session;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.sip.ClientTransaction;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
||||||
|
* @author: songww
|
||||||
|
* @date: 2020年5月13日 下午4:03:02
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class VideoStreamSessionManager {
|
||||||
|
|
||||||
|
private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public String createPlaySsrc(){
|
||||||
|
String ssrc = SsrcUtil.getPlaySsrc();
|
||||||
|
return ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String createPlayBackSsrc(){
|
||||||
|
String ssrc = SsrcUtil.getPlayBackSsrc();
|
||||||
|
return ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String ssrc,ClientTransaction transaction){
|
||||||
|
sessionMap.put(ssrc, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientTransaction get(String ssrc){
|
||||||
|
return sessionMap.get(ssrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String ssrc) {
|
||||||
|
sessionMap.remove(ssrc);
|
||||||
|
SsrcUtil.releaseSsrc(ssrc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,6 +81,13 @@ public interface ISIPCommander {
|
||||||
*/
|
*/
|
||||||
public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime);
|
public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频流停止
|
||||||
|
*
|
||||||
|
* @param ssrc ssrc
|
||||||
|
*/
|
||||||
|
public void streamByeCmd(String ssrc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 语音广播
|
* 语音广播
|
||||||
*
|
*
|
||||||
|
|
|
@ -46,14 +46,15 @@ public class SIPRequestHeaderProvider {
|
||||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
|
ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
|
||||||
device.getTransport(), viaTag);
|
device.getTransport(), viaTag);
|
||||||
|
viaHeader.setRPort();
|
||||||
viaHeaders.add(viaHeader);
|
viaHeaders.add(viaHeader);
|
||||||
// from
|
// from
|
||||||
SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),
|
SipURI fromSipURI = layer.getAddressFactory().createSipURI(sipConfig.getSipId(),
|
||||||
sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
|
sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
|
||||||
Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
|
Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
|
||||||
FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag);
|
FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag);
|
||||||
// to
|
// to
|
||||||
SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
|
SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain());
|
||||||
Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
|
Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress, toTag);
|
ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress, toTag);
|
||||||
// callid
|
// callid
|
||||||
|
@ -71,6 +72,49 @@ public class SIPRequestHeaderProvider {
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException {
|
||||||
|
// Request request = null;
|
||||||
|
// Host host = device.getHost();
|
||||||
|
// //请求行
|
||||||
|
// SipURI requestLine = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
|
||||||
|
// //via
|
||||||
|
// ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
|
// ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
|
||||||
|
// viaHeader.setRPort();
|
||||||
|
// viaHeaders.add(viaHeader);
|
||||||
|
// //from
|
||||||
|
// SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipIp()+":"+sipConfig.getSipPort());
|
||||||
|
// Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
|
||||||
|
// FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||||
|
// //to
|
||||||
|
// SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),host.getAddress());
|
||||||
|
// Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
|
||||||
|
// ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null);
|
||||||
|
//
|
||||||
|
// //callid
|
||||||
|
// CallIdHeader callIdHeader = null;
|
||||||
|
// if(device.getTransport().equals("TCP")) {
|
||||||
|
// callIdHeader = layer.getTcpSipProvider().getNewCallId();
|
||||||
|
// }
|
||||||
|
// if(device.getTransport().equals("UDP")) {
|
||||||
|
// callIdHeader = layer.getUdpSipProvider().getNewCallId();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //Forwards
|
||||||
|
// MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70);
|
||||||
|
//
|
||||||
|
// //ceq
|
||||||
|
// CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE);
|
||||||
|
// request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||||
|
//
|
||||||
|
// Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
|
||||||
|
// request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress));
|
||||||
|
//
|
||||||
|
// ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
|
||||||
|
// request.setContent(content, contentTypeHeader);
|
||||||
|
// return request;
|
||||||
|
// }
|
||||||
|
|
||||||
public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException {
|
public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
Host host = device.getHost();
|
Host host = device.getHost();
|
||||||
|
@ -82,11 +126,11 @@ public class SIPRequestHeaderProvider {
|
||||||
viaHeader.setRPort();
|
viaHeader.setRPort();
|
||||||
viaHeaders.add(viaHeader);
|
viaHeaders.add(viaHeader);
|
||||||
//from
|
//from
|
||||||
SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipIp()+":"+sipConfig.getSipPort());
|
SipURI fromSipURI = layer.getAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain());
|
||||||
Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
|
Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
|
||||||
FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||||
//to
|
//to
|
||||||
SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),host.getAddress());
|
SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipDomain());
|
||||||
Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
|
Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null);
|
ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null);
|
||||||
|
|
||||||
|
@ -101,9 +145,14 @@ public class SIPRequestHeaderProvider {
|
||||||
|
|
||||||
//Forwards
|
//Forwards
|
||||||
MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70);
|
MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70);
|
||||||
|
|
||||||
//ceq
|
//ceq
|
||||||
CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE);
|
CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE);
|
||||||
request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||||
|
|
||||||
|
Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
|
||||||
|
request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress));
|
||||||
|
|
||||||
ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
|
ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
|
||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
|
|
|
@ -3,8 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
import javax.sip.ClientTransaction;
|
import javax.sip.ClientTransaction;
|
||||||
|
import javax.sip.Dialog;
|
||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.TransactionDoesNotExistException;
|
||||||
|
import javax.sip.header.ViaHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -13,10 +16,10 @@ import org.springframework.stereotype.Component;
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.SsrcUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
|
@ -35,6 +38,9 @@ public class SIPCommander implements ISIPCommander {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipLayer sipLayer;
|
private SipLayer sipLayer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VideoStreamSessionManager streamSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
||||||
*
|
*
|
||||||
|
@ -135,11 +141,11 @@ public class SIPCommander implements ISIPCommander {
|
||||||
public String playStreamCmd(Device device, String channelId) {
|
public String playStreamCmd(Device device, String channelId) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String ssrc = SsrcUtil.getPlaySsrc();
|
String ssrc = streamSession.createPlaySsrc();
|
||||||
//
|
//
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+channelId+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n");
|
content.append("o="+channelId+" 0 0 IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
||||||
content.append("s=Play\r\n");
|
content.append("s=Play\r\n");
|
||||||
content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
||||||
content.append("t=0 0\r\n");
|
content.append("t=0 0\r\n");
|
||||||
|
@ -161,7 +167,8 @@ public class SIPCommander implements ISIPCommander {
|
||||||
|
|
||||||
Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
|
Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
|
||||||
|
|
||||||
transmitRequest(device, request);
|
ClientTransaction transaction = transmitRequest(device, request);
|
||||||
|
streamSession.put(ssrc, transaction);
|
||||||
return ssrc;
|
return ssrc;
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -181,11 +188,11 @@ public class SIPCommander implements ISIPCommander {
|
||||||
public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) {
|
public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String ssrc = SsrcUtil.getPlayBackSsrc();
|
String ssrc = streamSession.createPlayBackSsrc();
|
||||||
//
|
//
|
||||||
StringBuffer content = new StringBuffer(200);
|
StringBuffer content = new StringBuffer(200);
|
||||||
content.append("v=0\r\n");
|
content.append("v=0\r\n");
|
||||||
content.append("o="+device.getDeviceId()+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n");
|
content.append("o="+device.getDeviceId()+" 0 0 IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
||||||
content.append("s=Playback\r\n");
|
content.append("s=Playback\r\n");
|
||||||
content.append("u="+channelId+":3\r\n");
|
content.append("u="+channelId+":3\r\n");
|
||||||
content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
||||||
|
@ -208,13 +215,50 @@ public class SIPCommander implements ISIPCommander {
|
||||||
|
|
||||||
Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
|
Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
|
||||||
|
|
||||||
transmitRequest(device, request);
|
ClientTransaction transaction = transmitRequest(device, request);
|
||||||
|
streamSession.put(ssrc, transaction);
|
||||||
return ssrc;
|
return ssrc;
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频流停止
|
||||||
|
*
|
||||||
|
* @param device 视频设备
|
||||||
|
* @param channelId 预览通道
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void streamByeCmd(String ssrc) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ClientTransaction transaction = streamSession.get(ssrc);
|
||||||
|
if (transaction == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog dialog = transaction.getDialog();
|
||||||
|
if (dialog == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Request byeRequest = dialog.createRequest(Request.BYE);
|
||||||
|
ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
|
||||||
|
String protocol = viaHeader.getTransport();
|
||||||
|
ClientTransaction clientTransaction = null;
|
||||||
|
if("TCP".equals(protocol)) {
|
||||||
|
clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(byeRequest);
|
||||||
|
} else if("UDP".equals(protocol)) {
|
||||||
|
clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(byeRequest);
|
||||||
|
}
|
||||||
|
dialog.sendRequest(clientTransaction);
|
||||||
|
} catch (TransactionDoesNotExistException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SipException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 语音广播
|
* 语音广播
|
||||||
|
@ -435,16 +479,15 @@ public class SIPCommander implements ISIPCommander {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transmitRequest(Device device, Request request) throws SipException {
|
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
||||||
ClientTransaction clientTransaction = null;
|
ClientTransaction clientTransaction = null;
|
||||||
if(device.getTransport().equals("TCP")) {
|
if("TCP".equals(device.getTransport())) {
|
||||||
clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(request);
|
clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(request);
|
||||||
//sipLayer.getTcpSipProvider().sendRequest(request);
|
} else if("UDP".equals(device.getTransport())) {
|
||||||
} else if(device.getTransport().equals("UDP")) {
|
|
||||||
clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request);
|
clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request);
|
||||||
//sipLayer.getUdpSipProvider().sendRequest(request);
|
|
||||||
}
|
}
|
||||||
clientTransaction.sendRequest();
|
clientTransaction.sendRequest();
|
||||||
|
return clientTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.transmit.request;
|
package com.genersoft.iot.vmp.gb28181.transmit.request;
|
||||||
|
|
||||||
import javax.sip.RequestEvent;
|
import javax.sip.RequestEvent;
|
||||||
import javax.sip.ServerTransaction;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
|
|
||||||
|
@ -12,6 +11,6 @@ import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
*/
|
*/
|
||||||
public interface ISIPRequestProcessor {
|
public interface ISIPRequestProcessor {
|
||||||
|
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction);
|
public void process(RequestEvent evt, SipLayer layer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class AckRequestProcessor implements ISIPRequestProcessor {
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
Request request = evt.getRequest();
|
Request request = evt.getRequest();
|
||||||
Dialog dialog = evt.getDialog();
|
Dialog dialog = evt.getDialog();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class ByeRequestProcessor implements ISIPRequestProcessor {
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class CancelRequestProcessor implements ISIPRequestProcessor {
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class InviteRequestProcessor implements ISIPRequestProcessor {
|
||||||
* 请求消息
|
* 请求消息
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
// Request request = requestEvent.getRequest();
|
// Request request = requestEvent.getRequest();
|
||||||
//
|
//
|
||||||
|
|
|
@ -93,10 +93,10 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
|
||||||
* @param transaction
|
* @param transaction
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
|
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this.transaction = transaction;
|
this.transaction = layer.getServerTransaction(evt);
|
||||||
|
|
||||||
Request request = evt.getRequest();
|
Request request = evt.getRequest();
|
||||||
SAXReader reader = new SAXReader();
|
SAXReader reader = new SAXReader();
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class OtherRequestProcessor implements ISIPRequestProcessor {
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
System.out.println("no support the method! Method:" + evt.getRequest().getMethod());
|
System.out.println("no support the method! Method:" + evt.getRequest().getMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
|
||||||
* 请求消息
|
* 请求消息
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
try {
|
try {
|
||||||
System.out.println("收到注册请求,开始处理");
|
System.out.println("收到注册请求,开始处理");
|
||||||
Request request = evt.getRequest();
|
Request request = evt.getRequest();
|
||||||
|
@ -141,7 +141,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
|
||||||
device.setTransport(isTcp ? "TCP" : "UDP");
|
device.setTransport(isTcp ? "TCP" : "UDP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transaction.sendResponse(response);
|
layer.getServerTransaction(evt).sendResponse(response);
|
||||||
// 注册成功
|
// 注册成功
|
||||||
// 保存到redis
|
// 保存到redis
|
||||||
// 下发catelog查询目录
|
// 下发catelog查询目录
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor {
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
|
public void process(RequestEvent evt, SipLayer layer) {
|
||||||
Request request = evt.getRequest();
|
Request request = evt.getRequest();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -43,7 +43,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor {
|
||||||
response.setExpires(expireHeader);
|
response.setExpires(expireHeader);
|
||||||
}
|
}
|
||||||
System.out.println("response : " + response.toString());
|
System.out.println("response : " + response.toString());
|
||||||
|
ServerTransaction transaction = layer.getServerTransaction(evt);
|
||||||
if (transaction != null) {
|
if (transaction != null) {
|
||||||
transaction.sendResponse(response);
|
transaction.sendResponse(response);
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
|
|
|
@ -50,31 +50,33 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
||||||
//成功响应
|
//成功响应
|
||||||
//下发ack
|
//下发ack
|
||||||
if(statusCode == Response.OK){
|
if(statusCode == Response.OK){
|
||||||
ClientTransaction clientTransaction = evt.getClientTransaction();
|
// ClientTransaction clientTransaction = evt.getClientTransaction();
|
||||||
if(clientTransaction == null){
|
// if(clientTransaction == null){
|
||||||
logger.error("回复ACK时,clientTransaction为null >>> {}",response);
|
// logger.error("回复ACK时,clientTransaction为null >>> {}",response);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
Dialog clientDialog = clientTransaction.getDialog();
|
// Dialog clientDialog = clientTransaction.getDialog();
|
||||||
|
//
|
||||||
CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
// CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||||
long cseqId = clientCSeqHeader.getSeqNumber();
|
// long cseqId = clientCSeqHeader.getSeqNumber();
|
||||||
/*
|
// /*
|
||||||
createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
|
// createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
|
||||||
有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
|
// 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
|
||||||
所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。
|
// 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。
|
||||||
*/
|
// */
|
||||||
Request ackRequest = clientDialog.createAck(cseqId);
|
// Request ackRequest = clientDialog.createAck(cseqId);
|
||||||
SipURI requestURI = (SipURI) ackRequest.getRequestURI();
|
// SipURI requestURI = (SipURI) ackRequest.getRequestURI();
|
||||||
ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
|
// ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
|
||||||
requestURI.setHost(viaHeader.getHost());
|
// requestURI.setHost(viaHeader.getHost());
|
||||||
requestURI.setPort(viaHeader.getPort());
|
// requestURI.setPort(viaHeader.getPort());
|
||||||
clientDialog.sendAck(ackRequest);
|
// clientDialog.sendAck(ackRequest);
|
||||||
|
|
||||||
|
Dialog dialog = evt.getDialog();
|
||||||
|
Request reqAck =dialog.createAck(1L);
|
||||||
|
dialog.sendAck(reqAck);
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException | SipException e) {
|
} catch (InvalidArgumentException | SipException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean delete(String deviceId) {
|
public boolean delete(String deviceId) {
|
||||||
redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
|
return redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -68,14 +68,20 @@ public class RedisUtil {
|
||||||
* @SuppressWarnings("unchecked") 忽略类型转换警告
|
* @SuppressWarnings("unchecked") 忽略类型转换警告
|
||||||
* @param key 键(一个或者多个)
|
* @param key 键(一个或者多个)
|
||||||
*/
|
*/
|
||||||
public void del(String... key) {
|
public boolean del(String... key) {
|
||||||
if (key != null && key.length > 0) {
|
try {
|
||||||
if (key.length == 1) {
|
if (key != null && key.length > 0) {
|
||||||
redisTemplate.delete(key[0]);
|
if (key.length == 1) {
|
||||||
} else {
|
redisTemplate.delete(key[0]);
|
||||||
// 传入一个 Collection<String> 集合
|
} else {
|
||||||
redisTemplate.delete(CollectionUtils.arrayToList(key));
|
// 传入一个 Collection<String> 集合
|
||||||
|
redisTemplate.delete(CollectionUtils.arrayToList(key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
@ -34,6 +36,9 @@ public class DeviceController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOffLineDetector offLineDetector;
|
||||||
|
|
||||||
@GetMapping("/devices/{deviceId}")
|
@GetMapping("/devices/{deviceId}")
|
||||||
public ResponseEntity<Device> devices(@PathVariable String deviceId){
|
public ResponseEntity<Device> devices(@PathVariable String deviceId){
|
||||||
|
|
||||||
|
@ -69,4 +74,25 @@ public class DeviceController {
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/devices/{deviceId}/delete")
|
||||||
|
public ResponseEntity<String> delete(@PathVariable String deviceId){
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("设备信息删除API调用,deviceId:" + deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
|
return new ResponseEntity<String>("不允许删除在线设备!", HttpStatus.NOT_ACCEPTABLE);
|
||||||
|
}
|
||||||
|
boolean isSuccess = storager.delete(deviceId);
|
||||||
|
if (isSuccess) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("deviceId", deviceId);
|
||||||
|
return new ResponseEntity<>(json.toString(),HttpStatus.OK);
|
||||||
|
} else {
|
||||||
|
logger.warn("设备预览API调用失败!");
|
||||||
|
return new ResponseEntity<String>("设备预览API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@ -47,4 +48,23 @@ public class PlayController {
|
||||||
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
|
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/play/{ssrc}/stop")
|
||||||
|
public ResponseEntity<String> playStop(@PathVariable String ssrc){
|
||||||
|
|
||||||
|
cmder.streamByeCmd(ssrc);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ssrc!=null) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("ssrc", ssrc);
|
||||||
|
return new ResponseEntity<String>(json.toString(),HttpStatus.OK);
|
||||||
|
} else {
|
||||||
|
logger.warn("设备预览停止API调用失败!");
|
||||||
|
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ spring:
|
||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8080
|
||||||
sip:
|
sip:
|
||||||
ip: 127.0.0.1
|
ip: 10.200.64.63
|
||||||
port: 5060
|
port: 5060
|
||||||
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
||||||
# 后两位为行业编码,定义参照附录D.3
|
# 后两位为行业编码,定义参照附录D.3
|
||||||
|
|
Loading…
Reference in New Issue