Commit 6ecd801c2365feb4e65f6684065aa97f11615797

Authored by songww
1 parent ca513992

增加设备删除接口,只允许删除离线设备;增加视频停止播放接口

Showing 22 changed files with 266 additions and 66 deletions
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
@@ -12,6 +12,8 @@ public class SipConfig { @@ -12,6 +12,8 @@ public class SipConfig {
12 Integer sipPort; 12 Integer sipPort;
13 @Value("${sip.domain}") 13 @Value("${sip.domain}")
14 String sipDomain; 14 String sipDomain;
  15 + @Value("${sip.id}")
  16 + String sipId;
15 @Value("${sip.password}") 17 @Value("${sip.password}")
16 String sipPassword; 18 String sipPassword;
17 @Value("${media.ip}") 19 @Value("${media.ip}")
@@ -77,6 +79,12 @@ public class SipConfig { @@ -77,6 +79,12 @@ public class SipConfig {
77 public void setSpeed(Integer speed) { 79 public void setSpeed(Integer speed) {
78 this.speed = speed; 80 this.speed = speed;
79 } 81 }
80 -  
81 - 82 +
  83 + public String getSipId() {
  84 + return sipId;
  85 + }
  86 +
  87 + public void setSipId(String sipId) {
  88 + this.sipId = sipId;
  89 + }
82 } 90 }
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -117,7 +117,7 @@ public class SipLayer implements SipListener, Runnable { @@ -117,7 +117,7 @@ public class SipLayer implements SipListener, Runnable {
117 @Override 117 @Override
118 public void processRequest(RequestEvent evt) { 118 public void processRequest(RequestEvent evt) {
119 ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt); 119 ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt);
120 - processor.process(evt, this, getServerTransaction(evt)); 120 + processor.process(evt, this);
121 } 121 }
122 122
123 @Override 123 @Override
@@ -200,7 +200,7 @@ public class SipLayer implements SipListener, Runnable { @@ -200,7 +200,7 @@ public class SipLayer implements SipListener, Runnable {
200 200
201 } 201 }
202 202
203 - private ServerTransaction getServerTransaction(RequestEvent evt) { 203 + public ServerTransaction getServerTransaction(RequestEvent evt) {
204 Request request = evt.getRequest(); 204 Request request = evt.getRequest();
205 ServerTransaction serverTransaction = evt.getServerTransaction(); 205 ServerTransaction serverTransaction = evt.getServerTransaction();
206 // 判断TCP还是UDP 206 // 判断TCP还是UDP
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SsrcUtil.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java
1 -package com.genersoft.iot.vmp.gb28181.utils; 1 +package com.genersoft.iot.vmp.gb28181.session;
2 2
3 import java.util.ArrayList; 3 import java.util.ArrayList;
4 import java.util.List; 4 import java.util.List;
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.session;
  2 +
  3 +import java.util.concurrent.ConcurrentHashMap;
  4 +
  5 +import javax.sip.ClientTransaction;
  6 +
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +/**
  10 + * @Description:视频流session管理器,管理视频预览、预览回放的通信句柄
  11 + * @author: songww
  12 + * @date: 2020年5月13日 下午4:03:02
  13 + */
  14 +@Component
  15 +public class VideoStreamSessionManager {
  16 +
  17 + private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
  18 +
  19 + public String createPlaySsrc(){
  20 + String ssrc = SsrcUtil.getPlaySsrc();
  21 + return ssrc;
  22 + }
  23 +
  24 + public String createPlayBackSsrc(){
  25 + String ssrc = SsrcUtil.getPlayBackSsrc();
  26 + return ssrc;
  27 + }
  28 +
  29 + public void put(String ssrc,ClientTransaction transaction){
  30 + sessionMap.put(ssrc, transaction);
  31 + }
  32 +
  33 + public ClientTransaction get(String ssrc){
  34 + return sessionMap.get(ssrc);
  35 + }
  36 +
  37 + public void remove(String ssrc) {
  38 + sessionMap.remove(ssrc);
  39 + SsrcUtil.releaseSsrc(ssrc);
  40 + }
  41 +}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -82,6 +82,13 @@ public interface ISIPCommander { @@ -82,6 +82,13 @@ public interface ISIPCommander {
82 public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime); 82 public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime);
83 83
84 /** 84 /**
  85 + * 视频流停止
  86 + *
  87 + * @param ssrc ssrc
  88 + */
  89 + public void streamByeCmd(String ssrc);
  90 +
  91 + /**
85 * 语音广播 92 * 语音广播
86 * 93 *
87 * @param device 视频设备 94 * @param device 视频设备
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -46,14 +46,15 @@ public class SIPRequestHeaderProvider { @@ -46,14 +46,15 @@ public class SIPRequestHeaderProvider {
46 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); 46 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
47 ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), 47 ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
48 device.getTransport(), viaTag); 48 device.getTransport(), viaTag);
  49 + viaHeader.setRPort();
49 viaHeaders.add(viaHeader); 50 viaHeaders.add(viaHeader);
50 // from 51 // from
51 - SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), 52 + SipURI fromSipURI = layer.getAddressFactory().createSipURI(sipConfig.getSipId(),
52 sipConfig.getSipIp() + ":" + sipConfig.getSipPort()); 53 sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
53 Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI); 54 Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
54 FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); 55 FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag);
55 // to 56 // to
56 - SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress()); 57 + SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain());
57 Address toAddress = layer.getAddressFactory().createAddress(toSipURI); 58 Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
58 ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress, toTag); 59 ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress, toTag);
59 // callid 60 // callid
@@ -71,6 +72,49 @@ public class SIPRequestHeaderProvider { @@ -71,6 +72,49 @@ public class SIPRequestHeaderProvider {
71 return request; 72 return request;
72 } 73 }
73 74
  75 +// public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException {
  76 +// Request request = null;
  77 +// Host host = device.getHost();
  78 +// //请求行
  79 +// SipURI requestLine = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
  80 +// //via
  81 +// ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
  82 +// ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
  83 +// viaHeader.setRPort();
  84 +// viaHeaders.add(viaHeader);
  85 +// //from
  86 +// SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipIp()+":"+sipConfig.getSipPort());
  87 +// Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
  88 +// FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
  89 +// //to
  90 +// SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),host.getAddress());
  91 +// Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
  92 +// ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null);
  93 +//
  94 +// //callid
  95 +// CallIdHeader callIdHeader = null;
  96 +// if(device.getTransport().equals("TCP")) {
  97 +// callIdHeader = layer.getTcpSipProvider().getNewCallId();
  98 +// }
  99 +// if(device.getTransport().equals("UDP")) {
  100 +// callIdHeader = layer.getUdpSipProvider().getNewCallId();
  101 +// }
  102 +//
  103 +// //Forwards
  104 +// MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70);
  105 +//
  106 +// //ceq
  107 +// CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE);
  108 +// request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  109 +//
  110 +// Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
  111 +// request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress));
  112 +//
  113 +// ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
  114 +// request.setContent(content, contentTypeHeader);
  115 +// return request;
  116 +// }
  117 +
74 public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException { 118 public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException {
75 Request request = null; 119 Request request = null;
76 Host host = device.getHost(); 120 Host host = device.getHost();
@@ -82,11 +126,11 @@ public class SIPRequestHeaderProvider { @@ -82,11 +126,11 @@ public class SIPRequestHeaderProvider {
82 viaHeader.setRPort(); 126 viaHeader.setRPort();
83 viaHeaders.add(viaHeader); 127 viaHeaders.add(viaHeader);
84 //from 128 //from
85 - SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipIp()+":"+sipConfig.getSipPort()); 129 + SipURI fromSipURI = layer.getAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain());
86 Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI); 130 Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
87 FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack 131 FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
88 //to 132 //to
89 - SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),host.getAddress()); 133 + SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipDomain());
90 Address toAddress = layer.getAddressFactory().createAddress(toSipURI); 134 Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
91 ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null); 135 ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null);
92 136
@@ -101,9 +145,14 @@ public class SIPRequestHeaderProvider { @@ -101,9 +145,14 @@ public class SIPRequestHeaderProvider {
101 145
102 //Forwards 146 //Forwards
103 MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70); 147 MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70);
  148 +
104 //ceq 149 //ceq
105 CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE); 150 CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE);
106 request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards); 151 request = layer.getMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
  152 +
  153 + Address concatAddress = layer.getAddressFactory().createAddress(layer.getAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
  154 + request.addHeader(layer.getHeaderFactory().createContactHeader(concatAddress));
  155 +
107 ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP"); 156 ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
108 request.setContent(content, contentTypeHeader); 157 request.setContent(content, contentTypeHeader);
109 return request; 158 return request;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -3,8 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; @@ -3,8 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
3 import java.text.ParseException; 3 import java.text.ParseException;
4 4
5 import javax.sip.ClientTransaction; 5 import javax.sip.ClientTransaction;
  6 +import javax.sip.Dialog;
6 import javax.sip.InvalidArgumentException; 7 import javax.sip.InvalidArgumentException;
7 import javax.sip.SipException; 8 import javax.sip.SipException;
  9 +import javax.sip.TransactionDoesNotExistException;
  10 +import javax.sip.header.ViaHeader;
8 import javax.sip.message.Request; 11 import javax.sip.message.Request;
9 12
10 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,10 +16,10 @@ import org.springframework.stereotype.Component; @@ -13,10 +16,10 @@ import org.springframework.stereotype.Component;
13 import com.genersoft.iot.vmp.conf.SipConfig; 16 import com.genersoft.iot.vmp.conf.SipConfig;
14 import com.genersoft.iot.vmp.gb28181.SipLayer; 17 import com.genersoft.iot.vmp.gb28181.SipLayer;
15 import com.genersoft.iot.vmp.gb28181.bean.Device; 18 import com.genersoft.iot.vmp.gb28181.bean.Device;
  19 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
16 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
17 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
18 import com.genersoft.iot.vmp.gb28181.utils.DateUtil; 22 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
19 -import com.genersoft.iot.vmp.gb28181.utils.SsrcUtil;  
20 23
21 /** 24 /**
22 * @Description:设备能力接口,用于定义设备的控制、查询能力 25 * @Description:设备能力接口,用于定义设备的控制、查询能力
@@ -35,6 +38,9 @@ public class SIPCommander implements ISIPCommander { @@ -35,6 +38,9 @@ public class SIPCommander implements ISIPCommander {
35 @Autowired 38 @Autowired
36 private SipLayer sipLayer; 39 private SipLayer sipLayer;
37 40
  41 + @Autowired
  42 + private VideoStreamSessionManager streamSession;
  43 +
38 /** 44 /**
39 * 云台方向放控制,使用配置文件中的默认镜头移动速度 45 * 云台方向放控制,使用配置文件中的默认镜头移动速度
40 * 46 *
@@ -135,11 +141,11 @@ public class SIPCommander implements ISIPCommander { @@ -135,11 +141,11 @@ public class SIPCommander implements ISIPCommander {
135 public String playStreamCmd(Device device, String channelId) { 141 public String playStreamCmd(Device device, String channelId) {
136 try { 142 try {
137 143
138 - String ssrc = SsrcUtil.getPlaySsrc(); 144 + String ssrc = streamSession.createPlaySsrc();
139 // 145 //
140 StringBuffer content = new StringBuffer(200); 146 StringBuffer content = new StringBuffer(200);
141 content.append("v=0\r\n"); 147 content.append("v=0\r\n");
142 - content.append("o="+channelId+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n"); 148 + content.append("o="+channelId+" 0 0 IN IP4 "+sipConfig.getMediaIp()+"\r\n");
143 content.append("s=Play\r\n"); 149 content.append("s=Play\r\n");
144 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n"); 150 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
145 content.append("t=0 0\r\n"); 151 content.append("t=0 0\r\n");
@@ -161,7 +167,8 @@ public class SIPCommander implements ISIPCommander { @@ -161,7 +167,8 @@ public class SIPCommander implements ISIPCommander {
161 167
162 Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null); 168 Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
163 169
164 - transmitRequest(device, request); 170 + ClientTransaction transaction = transmitRequest(device, request);
  171 + streamSession.put(ssrc, transaction);
165 return ssrc; 172 return ssrc;
166 } catch ( SipException | ParseException | InvalidArgumentException e) { 173 } catch ( SipException | ParseException | InvalidArgumentException e) {
167 e.printStackTrace(); 174 e.printStackTrace();
@@ -181,11 +188,11 @@ public class SIPCommander implements ISIPCommander { @@ -181,11 +188,11 @@ public class SIPCommander implements ISIPCommander {
181 public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) { 188 public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) {
182 try { 189 try {
183 190
184 - String ssrc = SsrcUtil.getPlayBackSsrc(); 191 + String ssrc = streamSession.createPlayBackSsrc();
185 // 192 //
186 StringBuffer content = new StringBuffer(200); 193 StringBuffer content = new StringBuffer(200);
187 content.append("v=0\r\n"); 194 content.append("v=0\r\n");
188 - content.append("o="+device.getDeviceId()+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n"); 195 + content.append("o="+device.getDeviceId()+" 0 0 IN IP4 "+sipConfig.getMediaIp()+"\r\n");
189 content.append("s=Playback\r\n"); 196 content.append("s=Playback\r\n");
190 content.append("u="+channelId+":3\r\n"); 197 content.append("u="+channelId+":3\r\n");
191 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n"); 198 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
@@ -208,13 +215,50 @@ public class SIPCommander implements ISIPCommander { @@ -208,13 +215,50 @@ public class SIPCommander implements ISIPCommander {
208 215
209 Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null); 216 Request request = headerProvider.createInviteRequest(device, content.toString(), null, "live", null);
210 217
211 - transmitRequest(device, request); 218 + ClientTransaction transaction = transmitRequest(device, request);
  219 + streamSession.put(ssrc, transaction);
212 return ssrc; 220 return ssrc;
213 } catch ( SipException | ParseException | InvalidArgumentException e) { 221 } catch ( SipException | ParseException | InvalidArgumentException e) {
214 e.printStackTrace(); 222 e.printStackTrace();
215 return null; 223 return null;
216 } 224 }
217 } 225 }
  226 +
  227 + /**
  228 + * 视频流停止
  229 + *
  230 + * @param device 视频设备
  231 + * @param channelId 预览通道
  232 + */
  233 + @Override
  234 + public void streamByeCmd(String ssrc) {
  235 +
  236 + try {
  237 + ClientTransaction transaction = streamSession.get(ssrc);
  238 + if (transaction == null) {
  239 + return;
  240 + }
  241 +
  242 + Dialog dialog = transaction.getDialog();
  243 + if (dialog == null) {
  244 + return;
  245 + }
  246 + Request byeRequest = dialog.createRequest(Request.BYE);
  247 + ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
  248 + String protocol = viaHeader.getTransport();
  249 + ClientTransaction clientTransaction = null;
  250 + if("TCP".equals(protocol)) {
  251 + clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(byeRequest);
  252 + } else if("UDP".equals(protocol)) {
  253 + clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(byeRequest);
  254 + }
  255 + dialog.sendRequest(clientTransaction);
  256 + } catch (TransactionDoesNotExistException e) {
  257 + e.printStackTrace();
  258 + } catch (SipException e) {
  259 + e.printStackTrace();
  260 + }
  261 + }
218 262
219 /** 263 /**
220 * 语音广播 264 * 语音广播
@@ -435,16 +479,15 @@ public class SIPCommander implements ISIPCommander { @@ -435,16 +479,15 @@ public class SIPCommander implements ISIPCommander {
435 return false; 479 return false;
436 } 480 }
437 481
438 - private void transmitRequest(Device device, Request request) throws SipException { 482 + private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
439 ClientTransaction clientTransaction = null; 483 ClientTransaction clientTransaction = null;
440 - if(device.getTransport().equals("TCP")) { 484 + if("TCP".equals(device.getTransport())) {
441 clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(request); 485 clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(request);
442 - //sipLayer.getTcpSipProvider().sendRequest(request);  
443 - } else if(device.getTransport().equals("UDP")) { 486 + } else if("UDP".equals(device.getTransport())) {
444 clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request); 487 clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request);
445 - //sipLayer.getUdpSipProvider().sendRequest(request);  
446 } 488 }
447 clientTransaction.sendRequest(); 489 clientTransaction.sendRequest();
  490 + return clientTransaction;
448 } 491 }
449 492
450 } 493 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/ISIPRequestProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.request; 1 package com.genersoft.iot.vmp.gb28181.transmit.request;
2 2
3 import javax.sip.RequestEvent; 3 import javax.sip.RequestEvent;
4 -import javax.sip.ServerTransaction;  
5 4
6 import com.genersoft.iot.vmp.gb28181.SipLayer; 5 import com.genersoft.iot.vmp.gb28181.SipLayer;
7 6
@@ -12,6 +11,6 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; @@ -12,6 +11,6 @@ import com.genersoft.iot.vmp.gb28181.SipLayer;
12 */ 11 */
13 public interface ISIPRequestProcessor { 12 public interface ISIPRequestProcessor {
14 13
15 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction); 14 + public void process(RequestEvent evt, SipLayer layer);
16 15
17 } 16 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
@@ -31,7 +31,7 @@ public class AckRequestProcessor implements ISIPRequestProcessor { @@ -31,7 +31,7 @@ public class AckRequestProcessor implements ISIPRequestProcessor {
31 * @param config 31 * @param config
32 */ 32 */
33 @Override 33 @Override
34 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 34 + public void process(RequestEvent evt, SipLayer layer) {
35 Request request = evt.getRequest(); 35 Request request = evt.getRequest();
36 Dialog dialog = evt.getDialog(); 36 Dialog dialog = evt.getDialog();
37 try { 37 try {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
@@ -25,7 +25,7 @@ public class ByeRequestProcessor implements ISIPRequestProcessor { @@ -25,7 +25,7 @@ public class ByeRequestProcessor implements ISIPRequestProcessor {
25 * @param config 25 * @param config
26 */ 26 */
27 @Override 27 @Override
28 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 28 + public void process(RequestEvent evt, SipLayer layer) {
29 // TODO Auto-generated method stub 29 // TODO Auto-generated method stub
30 30
31 } 31 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/CancelRequestProcessor.java
@@ -25,7 +25,7 @@ public class CancelRequestProcessor implements ISIPRequestProcessor { @@ -25,7 +25,7 @@ public class CancelRequestProcessor implements ISIPRequestProcessor {
25 * @param config 25 * @param config
26 */ 26 */
27 @Override 27 @Override
28 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 28 + public void process(RequestEvent evt, SipLayer layer) {
29 // TODO Auto-generated method stub 29 // TODO Auto-generated method stub
30 30
31 } 31 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
@@ -23,7 +23,7 @@ public class InviteRequestProcessor implements ISIPRequestProcessor { @@ -23,7 +23,7 @@ public class InviteRequestProcessor implements ISIPRequestProcessor {
23 * 请求消息 23 * 请求消息
24 */ 24 */
25 @Override 25 @Override
26 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 26 + public void process(RequestEvent evt, SipLayer layer) {
27 // TODO Auto-generated method stub 27 // TODO Auto-generated method stub
28 // Request request = requestEvent.getRequest(); 28 // Request request = requestEvent.getRequest();
29 // 29 //
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -93,10 +93,10 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { @@ -93,10 +93,10 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
93 * @param transaction 93 * @param transaction
94 */ 94 */
95 @Override 95 @Override
96 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 96 + public void process(RequestEvent evt, SipLayer layer) {
97 97
98 this.layer = layer; 98 this.layer = layer;
99 - this.transaction = transaction; 99 + this.transaction = layer.getServerTransaction(evt);
100 100
101 Request request = evt.getRequest(); 101 Request request = evt.getRequest();
102 SAXReader reader = new SAXReader(); 102 SAXReader reader = new SAXReader();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/OtherRequestProcessor.java
@@ -25,7 +25,7 @@ public class OtherRequestProcessor implements ISIPRequestProcessor { @@ -25,7 +25,7 @@ public class OtherRequestProcessor implements ISIPRequestProcessor {
25 * @param config 25 * @param config
26 */ 26 */
27 @Override 27 @Override
28 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 28 + public void process(RequestEvent evt, SipLayer layer) {
29 System.out.println("no support the method! Method:" + evt.getRequest().getMethod()); 29 System.out.println("no support the method! Method:" + evt.getRequest().getMethod());
30 } 30 }
31 31
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
@@ -63,7 +63,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor { @@ -63,7 +63,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
63 * 请求消息 63 * 请求消息
64 */ 64 */
65 @Override 65 @Override
66 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 66 + public void process(RequestEvent evt, SipLayer layer) {
67 try { 67 try {
68 System.out.println("收到注册请求,开始处理"); 68 System.out.println("收到注册请求,开始处理");
69 Request request = evt.getRequest(); 69 Request request = evt.getRequest();
@@ -141,7 +141,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor { @@ -141,7 +141,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
141 device.setTransport(isTcp ? "TCP" : "UDP"); 141 device.setTransport(isTcp ? "TCP" : "UDP");
142 } 142 }
143 } 143 }
144 - transaction.sendResponse(response); 144 + layer.getServerTransaction(evt).sendResponse(response);
145 // 注册成功 145 // 注册成功
146 // 保存到redis 146 // 保存到redis
147 // 下发catelog查询目录 147 // 下发catelog查询目录
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/SubscribeRequestProcessor.java
@@ -32,7 +32,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor { @@ -32,7 +32,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor {
32 * @param config 32 * @param config
33 */ 33 */
34 @Override 34 @Override
35 - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) { 35 + public void process(RequestEvent evt, SipLayer layer) {
36 Request request = evt.getRequest(); 36 Request request = evt.getRequest();
37 37
38 try { 38 try {
@@ -43,7 +43,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor { @@ -43,7 +43,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor {
43 response.setExpires(expireHeader); 43 response.setExpires(expireHeader);
44 } 44 }
45 System.out.println("response : " + response.toString()); 45 System.out.println("response : " + response.toString());
46 - 46 + ServerTransaction transaction = layer.getServerTransaction(evt);
47 if (transaction != null) { 47 if (transaction != null) {
48 transaction.sendResponse(response); 48 transaction.sendResponse(response);
49 transaction.terminate(); 49 transaction.terminate();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
@@ -50,31 +50,33 @@ public class InviteResponseProcessor implements ISIPResponseProcessor { @@ -50,31 +50,33 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
50 //成功响应 50 //成功响应
51 //下发ack 51 //下发ack
52 if(statusCode == Response.OK){ 52 if(statusCode == Response.OK){
53 - ClientTransaction clientTransaction = evt.getClientTransaction();  
54 - if(clientTransaction == null){  
55 - logger.error("回复ACK时,clientTransaction为null >>> {}",response);  
56 - return;  
57 - }  
58 - Dialog clientDialog = clientTransaction.getDialog();  
59 -  
60 - CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);  
61 - long cseqId = clientCSeqHeader.getSeqNumber();  
62 - /*  
63 - createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。  
64 - 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流  
65 - 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。  
66 - */  
67 - Request ackRequest = clientDialog.createAck(cseqId);  
68 - SipURI requestURI = (SipURI) ackRequest.getRequestURI();  
69 - ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);  
70 - requestURI.setHost(viaHeader.getHost());  
71 - requestURI.setPort(viaHeader.getPort());  
72 - clientDialog.sendAck(ackRequest); 53 +// ClientTransaction clientTransaction = evt.getClientTransaction();
  54 +// if(clientTransaction == null){
  55 +// logger.error("回复ACK时,clientTransaction为null >>> {}",response);
  56 +// return;
  57 +// }
  58 +// Dialog clientDialog = clientTransaction.getDialog();
  59 +//
  60 +// CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
  61 +// long cseqId = clientCSeqHeader.getSeqNumber();
  62 +// /*
  63 +// createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
  64 +// 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
  65 +// 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。
  66 +// */
  67 +// Request ackRequest = clientDialog.createAck(cseqId);
  68 +// SipURI requestURI = (SipURI) ackRequest.getRequestURI();
  69 +// ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
  70 +// requestURI.setHost(viaHeader.getHost());
  71 +// requestURI.setPort(viaHeader.getPort());
  72 +// clientDialog.sendAck(ackRequest);
  73 +
  74 + Dialog dialog = evt.getDialog();
  75 + Request reqAck =dialog.createAck(1L);
  76 + dialog.sendAck(reqAck);
73 } 77 }
74 } catch (InvalidArgumentException | SipException e) { 78 } catch (InvalidArgumentException | SipException e) {
75 e.printStackTrace(); 79 e.printStackTrace();
76 - } catch (ParseException e) {  
77 - e.printStackTrace();  
78 } 80 }
79 } 81 }
80 82
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
@@ -96,8 +96,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { @@ -96,8 +96,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
96 */ 96 */
97 @Override 97 @Override
98 public boolean delete(String deviceId) { 98 public boolean delete(String deviceId) {
99 - redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);  
100 - return true; 99 + return redis.del(VideoManagerConstants.CACHEKEY_PREFIX+deviceId);
101 } 100 }
102 101
103 /** 102 /**
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
@@ -68,14 +68,20 @@ public class RedisUtil { @@ -68,14 +68,20 @@ public class RedisUtil {
68 * @SuppressWarnings("unchecked") 忽略类型转换警告 68 * @SuppressWarnings("unchecked") 忽略类型转换警告
69 * @param key 键(一个或者多个) 69 * @param key 键(一个或者多个)
70 */ 70 */
71 - public void del(String... key) {  
72 - if (key != null && key.length > 0) {  
73 - if (key.length == 1) {  
74 - redisTemplate.delete(key[0]);  
75 - } else {  
76 -// 传入一个 Collection<String> 集合  
77 - redisTemplate.delete(CollectionUtils.arrayToList(key)); 71 + public boolean del(String... key) {
  72 + try {
  73 + if (key != null && key.length > 0) {
  74 + if (key.length == 1) {
  75 + redisTemplate.delete(key[0]);
  76 + } else {
  77 +// 传入一个 Collection<String> 集合
  78 + redisTemplate.delete(CollectionUtils.arrayToList(key));
  79 + }
78 } 80 }
  81 + return true;
  82 + } catch (Exception e) {
  83 + e.printStackTrace();
  84 + return false;
79 } 85 }
80 } 86 }
81 87
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
@@ -14,7 +14,9 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -14,7 +14,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
14 import org.springframework.web.bind.annotation.RestController; 14 import org.springframework.web.bind.annotation.RestController;
15 import org.springframework.web.context.request.async.DeferredResult; 15 import org.springframework.web.context.request.async.DeferredResult;
16 16
  17 +import com.alibaba.fastjson.JSONObject;
17 import com.genersoft.iot.vmp.gb28181.bean.Device; 18 import com.genersoft.iot.vmp.gb28181.bean.Device;
  19 +import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
18 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 20 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
19 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
20 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 22 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -34,6 +36,9 @@ public class DeviceController { @@ -34,6 +36,9 @@ public class DeviceController {
34 @Autowired 36 @Autowired
35 private DeferredResultHolder resultHolder; 37 private DeferredResultHolder resultHolder;
36 38
  39 + @Autowired
  40 + private DeviceOffLineDetector offLineDetector;
  41 +
37 @GetMapping("/devices/{deviceId}") 42 @GetMapping("/devices/{deviceId}")
38 public ResponseEntity<Device> devices(@PathVariable String deviceId){ 43 public ResponseEntity<Device> devices(@PathVariable String deviceId){
39 44
@@ -69,4 +74,25 @@ public class DeviceController { @@ -69,4 +74,25 @@ public class DeviceController {
69 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result); 74 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
70 return result; 75 return result;
71 } 76 }
  77 +
  78 + @PostMapping("/devices/{deviceId}/delete")
  79 + public ResponseEntity<String> delete(@PathVariable String deviceId){
  80 +
  81 + if (logger.isDebugEnabled()) {
  82 + logger.debug("设备信息删除API调用,deviceId:" + deviceId);
  83 + }
  84 +
  85 + if (offLineDetector.isOnline(deviceId)) {
  86 + return new ResponseEntity<String>("不允许删除在线设备!", HttpStatus.NOT_ACCEPTABLE);
  87 + }
  88 + boolean isSuccess = storager.delete(deviceId);
  89 + if (isSuccess) {
  90 + JSONObject json = new JSONObject();
  91 + json.put("deviceId", deviceId);
  92 + return new ResponseEntity<>(json.toString(),HttpStatus.OK);
  93 + } else {
  94 + logger.warn("设备预览API调用失败!");
  95 + return new ResponseEntity<String>("设备预览API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
  96 + }
  97 + }
72 } 98 }
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -7,6 +7,7 @@ import org.springframework.http.HttpStatus; @@ -7,6 +7,7 @@ import org.springframework.http.HttpStatus;
7 import org.springframework.http.ResponseEntity; 7 import org.springframework.http.ResponseEntity;
8 import org.springframework.web.bind.annotation.GetMapping; 8 import org.springframework.web.bind.annotation.GetMapping;
9 import org.springframework.web.bind.annotation.PathVariable; 9 import org.springframework.web.bind.annotation.PathVariable;
  10 +import org.springframework.web.bind.annotation.PostMapping;
10 import org.springframework.web.bind.annotation.RequestMapping; 11 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.RestController; 12 import org.springframework.web.bind.annotation.RestController;
12 13
@@ -47,4 +48,23 @@ public class PlayController { @@ -47,4 +48,23 @@ public class PlayController {
47 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); 48 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
48 } 49 }
49 } 50 }
  51 +
  52 + @PostMapping("/play/{ssrc}/stop")
  53 + public ResponseEntity<String> playStop(@PathVariable String ssrc){
  54 +
  55 + cmder.streamByeCmd(ssrc);
  56 +
  57 + if (logger.isDebugEnabled()) {
  58 + logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc));
  59 + }
  60 +
  61 + if(ssrc!=null) {
  62 + JSONObject json = new JSONObject();
  63 + json.put("ssrc", ssrc);
  64 + return new ResponseEntity<String>(json.toString(),HttpStatus.OK);
  65 + } else {
  66 + logger.warn("设备预览停止API调用失败!");
  67 + return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
  68 + }
  69 + }
50 } 70 }
src/main/resources/application.yml
@@ -26,7 +26,7 @@ spring: @@ -26,7 +26,7 @@ spring:
26 server: 26 server:
27 port: 8080 27 port: 8080
28 sip: 28 sip:
29 - ip: 127.0.0.1 29 + ip: 10.200.64.63
30 port: 5060 30 port: 5060
31 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) 31 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
32 # 后两位为行业编码,定义参照附录D.3 32 # 后两位为行业编码,定义参照附录D.3