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 12 Integer sipPort;
13 13 @Value("${sip.domain}")
14 14 String sipDomain;
  15 + @Value("${sip.id}")
  16 + String sipId;
15 17 @Value("${sip.password}")
16 18 String sipPassword;
17 19 @Value("${media.ip}")
... ... @@ -77,6 +79,12 @@ public class SipConfig {
77 79 public void setSpeed(Integer speed) {
78 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 117 @Override
118 118 public void processRequest(RequestEvent evt) {
119 119 ISIPRequestProcessor processor = processorFactory.createRequestProcessor(evt);
120   - processor.process(evt, this, getServerTransaction(evt));
  120 + processor.process(evt, this);
121 121 }
122 122  
123 123 @Override
... ... @@ -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 204 Request request = evt.getRequest();
205 205 ServerTransaction serverTransaction = evt.getServerTransaction();
206 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 3 import java.util.ArrayList;
4 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 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 94 * @param device 视频设备
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -46,14 +46,15 @@ public class SIPRequestHeaderProvider {
46 46 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
47 47 ViaHeader viaHeader = layer.getHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
48 48 device.getTransport(), viaTag);
  49 + viaHeader.setRPort();
49 50 viaHeaders.add(viaHeader);
50 51 // from
51   - SipURI fromSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),
  52 + SipURI fromSipURI = layer.getAddressFactory().createSipURI(sipConfig.getSipId(),
52 53 sipConfig.getSipIp() + ":" + sipConfig.getSipPort());
53 54 Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
54 55 FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag);
55 56 // to
56   - SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
  57 + SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(), sipConfig.getSipDomain());
57 58 Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
58 59 ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress, toTag);
59 60 // callid
... ... @@ -71,6 +72,49 @@ public class SIPRequestHeaderProvider {
71 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 118 public Request createInviteRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException {
75 119 Request request = null;
76 120 Host host = device.getHost();
... ... @@ -82,11 +126,11 @@ public class SIPRequestHeaderProvider {
82 126 viaHeader.setRPort();
83 127 viaHeaders.add(viaHeader);
84 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 130 Address fromAddress = layer.getAddressFactory().createAddress(fromSipURI);
87 131 FromHeader fromHeader = layer.getHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
88 132 //to
89   - SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),host.getAddress());
  133 + SipURI toSipURI = layer.getAddressFactory().createSipURI(device.getDeviceId(),sipConfig.getSipDomain());
90 134 Address toAddress = layer.getAddressFactory().createAddress(toSipURI);
91 135 ToHeader toHeader = layer.getHeaderFactory().createToHeader(toAddress,null);
92 136  
... ... @@ -101,9 +145,14 @@ public class SIPRequestHeaderProvider {
101 145  
102 146 //Forwards
103 147 MaxForwardsHeader maxForwards = layer.getHeaderFactory().createMaxForwardsHeader(70);
  148 +
104 149 //ceq
105 150 CSeqHeader cSeqHeader = layer.getHeaderFactory().createCSeqHeader(1L, Request.INVITE);
106 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 156 ContentTypeHeader contentTypeHeader = layer.getHeaderFactory().createContentTypeHeader("Application", "SDP");
108 157 request.setContent(content, contentTypeHeader);
109 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 3 import java.text.ParseException;
4 4  
5 5 import javax.sip.ClientTransaction;
  6 +import javax.sip.Dialog;
6 7 import javax.sip.InvalidArgumentException;
7 8 import javax.sip.SipException;
  9 +import javax.sip.TransactionDoesNotExistException;
  10 +import javax.sip.header.ViaHeader;
8 11 import javax.sip.message.Request;
9 12  
10 13 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -13,10 +16,10 @@ import org.springframework.stereotype.Component;
13 16 import com.genersoft.iot.vmp.conf.SipConfig;
14 17 import com.genersoft.iot.vmp.gb28181.SipLayer;
15 18 import com.genersoft.iot.vmp.gb28181.bean.Device;
  19 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
16 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
17 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
18 22 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
19   -import com.genersoft.iot.vmp.gb28181.utils.SsrcUtil;
20 23  
21 24 /**
22 25 * @Description:设备能力接口,用于定义设备的控制、查询能力
... ... @@ -35,6 +38,9 @@ public class SIPCommander implements ISIPCommander {
35 38 @Autowired
36 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 141 public String playStreamCmd(Device device, String channelId) {
136 142 try {
137 143  
138   - String ssrc = SsrcUtil.getPlaySsrc();
  144 + String ssrc = streamSession.createPlaySsrc();
139 145 //
140 146 StringBuffer content = new StringBuffer(200);
141 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 149 content.append("s=Play\r\n");
144 150 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
145 151 content.append("t=0 0\r\n");
... ... @@ -161,7 +167,8 @@ public class SIPCommander implements ISIPCommander {
161 167  
162 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 172 return ssrc;
166 173 } catch ( SipException | ParseException | InvalidArgumentException e) {
167 174 e.printStackTrace();
... ... @@ -181,11 +188,11 @@ public class SIPCommander implements ISIPCommander {
181 188 public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) {
182 189 try {
183 190  
184   - String ssrc = SsrcUtil.getPlayBackSsrc();
  191 + String ssrc = streamSession.createPlayBackSsrc();
185 192 //
186 193 StringBuffer content = new StringBuffer(200);
187 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 196 content.append("s=Playback\r\n");
190 197 content.append("u="+channelId+":3\r\n");
191 198 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
... ... @@ -208,13 +215,50 @@ public class SIPCommander implements ISIPCommander {
208 215  
209 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 220 return ssrc;
213 221 } catch ( SipException | ParseException | InvalidArgumentException e) {
214 222 e.printStackTrace();
215 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 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 483 ClientTransaction clientTransaction = null;
440   - if(device.getTransport().equals("TCP")) {
  484 + if("TCP".equals(device.getTransport())) {
441 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 487 clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request);
445   - //sipLayer.getUdpSipProvider().sendRequest(request);
446 488 }
447 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 1 package com.genersoft.iot.vmp.gb28181.transmit.request;
2 2  
3 3 import javax.sip.RequestEvent;
4   -import javax.sip.ServerTransaction;
5 4  
6 5 import com.genersoft.iot.vmp.gb28181.SipLayer;
7 6  
... ... @@ -12,6 +11,6 @@ import com.genersoft.iot.vmp.gb28181.SipLayer;
12 11 */
13 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 31 * @param config
32 32 */
33 33 @Override
34   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  34 + public void process(RequestEvent evt, SipLayer layer) {
35 35 Request request = evt.getRequest();
36 36 Dialog dialog = evt.getDialog();
37 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 25 * @param config
26 26 */
27 27 @Override
28   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  28 + public void process(RequestEvent evt, SipLayer layer) {
29 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 25 * @param config
26 26 */
27 27 @Override
28   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  28 + public void process(RequestEvent evt, SipLayer layer) {
29 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 23 * 请求消息
24 24 */
25 25 @Override
26   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  26 + public void process(RequestEvent evt, SipLayer layer) {
27 27 // TODO Auto-generated method stub
28 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 93 * @param transaction
94 94 */
95 95 @Override
96   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  96 + public void process(RequestEvent evt, SipLayer layer) {
97 97  
98 98 this.layer = layer;
99   - this.transaction = transaction;
  99 + this.transaction = layer.getServerTransaction(evt);
100 100  
101 101 Request request = evt.getRequest();
102 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 25 * @param config
26 26 */
27 27 @Override
28   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  28 + public void process(RequestEvent evt, SipLayer layer) {
29 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 63 * 请求消息
64 64 */
65 65 @Override
66   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  66 + public void process(RequestEvent evt, SipLayer layer) {
67 67 try {
68 68 System.out.println("收到注册请求,开始处理");
69 69 Request request = evt.getRequest();
... ... @@ -141,7 +141,7 @@ public class RegisterRequestProcessor implements ISIPRequestProcessor {
141 141 device.setTransport(isTcp ? "TCP" : "UDP");
142 142 }
143 143 }
144   - transaction.sendResponse(response);
  144 + layer.getServerTransaction(evt).sendResponse(response);
145 145 // 注册成功
146 146 // 保存到redis
147 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 32 * @param config
33 33 */
34 34 @Override
35   - public void process(RequestEvent evt, SipLayer layer, ServerTransaction transaction) {
  35 + public void process(RequestEvent evt, SipLayer layer) {
36 36 Request request = evt.getRequest();
37 37  
38 38 try {
... ... @@ -43,7 +43,7 @@ public class SubscribeRequestProcessor implements ISIPRequestProcessor {
43 43 response.setExpires(expireHeader);
44 44 }
45 45 System.out.println("response : " + response.toString());
46   -
  46 + ServerTransaction transaction = layer.getServerTransaction(evt);
47 47 if (transaction != null) {
48 48 transaction.sendResponse(response);
49 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 50 //成功响应
51 51 //下发ack
52 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 78 } catch (InvalidArgumentException | SipException e) {
75 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 96 */
97 97 @Override
98 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 68 * @SuppressWarnings("unchecked") 忽略类型转换警告
69 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 14 import org.springframework.web.bind.annotation.RestController;
15 15 import org.springframework.web.context.request.async.DeferredResult;
16 16  
  17 +import com.alibaba.fastjson.JSONObject;
17 18 import com.genersoft.iot.vmp.gb28181.bean.Device;
  19 +import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
18 20 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
19 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
20 22 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
... ... @@ -34,6 +36,9 @@ public class DeviceController {
34 36 @Autowired
35 37 private DeferredResultHolder resultHolder;
36 38  
  39 + @Autowired
  40 + private DeviceOffLineDetector offLineDetector;
  41 +
37 42 @GetMapping("/devices/{deviceId}")
38 43 public ResponseEntity<Device> devices(@PathVariable String deviceId){
39 44  
... ... @@ -69,4 +74,25 @@ public class DeviceController {
69 74 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
70 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 7 import org.springframework.http.ResponseEntity;
8 8 import org.springframework.web.bind.annotation.GetMapping;
9 9 import org.springframework.web.bind.annotation.PathVariable;
  10 +import org.springframework.web.bind.annotation.PostMapping;
10 11 import org.springframework.web.bind.annotation.RequestMapping;
11 12 import org.springframework.web.bind.annotation.RestController;
12 13  
... ... @@ -47,4 +48,23 @@ public class PlayController {
47 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 26 server:
27 27 port: 8080
28 28 sip:
29   - ip: 127.0.0.1
  29 + ip: 10.200.64.63
30 30 port: 5060
31 31 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
32 32 # 后两位为行业编码,定义参照附录D.3
... ...