Commit ca5139929b8b5853229ca3d63e2bca1ce82fa0ab

Authored by songww
1 parent d072017b

尝试修复catalog获取失败。服务重启后设备未注册仍上报keeplive处理

src/main/java/com/genersoft/iot/vmp/gb28181/event/DeviceOffLineDetector.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.event;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.stereotype.Component;
  5 +
  6 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
  7 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
  8 +
  9 +/**
  10 + * @Description:设备离在线状态检测器,用于检测设备状态
  11 + * @author: songww
  12 + * @date: 2020年5月13日 下午2:40:29
  13 + */
  14 +@Component
  15 +public class DeviceOffLineDetector {
  16 +
  17 + @Autowired
  18 + private RedisUtil redis;
  19 +
  20 + public boolean isOnline(String deviceId) {
  21 + String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + deviceId;
  22 + return redis.hasKey(key);
  23 + }
  24 +}
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
@@ -4,8 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -4,8 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.context.ApplicationEventPublisher; 4 import org.springframework.context.ApplicationEventPublisher;
5 import org.springframework.stereotype.Component; 5 import org.springframework.stereotype.Component;
6 6
  7 +import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent;
7 import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent; 8 import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;
8 -import com.genersoft.iot.vmp.gb28181.event.outline.OutlineEvent;  
9 9
10 /** 10 /**
11 * @Description:Event事件通知推送器,支持推送在线事件、离线事件 11 * @Description:Event事件通知推送器,支持推送在线事件、离线事件
@@ -26,7 +26,7 @@ public class EventPublisher { @@ -26,7 +26,7 @@ public class EventPublisher {
26 } 26 }
27 27
28 public void outlineEventPublish(String deviceId, String from){ 28 public void outlineEventPublish(String deviceId, String from){
29 - OutlineEvent outEvent = new OutlineEvent(this); 29 + OfflineEvent outEvent = new OfflineEvent(this);
30 outEvent.setDeviceId(deviceId); 30 outEvent.setDeviceId(deviceId);
31 outEvent.setFrom(from); 31 outEvent.setFrom(from);
32 applicationEventPublisher.publishEvent(outEvent); 32 applicationEventPublisher.publishEvent(outEvent);
src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/KeepliveTimeoutListener.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java
1 -package com.genersoft.iot.vmp.gb28181.event.outline; 1 +package com.genersoft.iot.vmp.gb28181.event.offline;
2 2
3 import org.springframework.beans.factory.annotation.Autowired; 3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.data.redis.connection.Message; 4 import org.springframework.data.redis.connection.Message;
src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/OutlineEvent.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java
1 -package com.genersoft.iot.vmp.gb28181.event.outline; 1 +package com.genersoft.iot.vmp.gb28181.event.offline;
2 2
3 import org.springframework.context.ApplicationEvent; 3 import org.springframework.context.ApplicationEvent;
4 4
@@ -7,7 +7,7 @@ import org.springframework.context.ApplicationEvent; @@ -7,7 +7,7 @@ import org.springframework.context.ApplicationEvent;
7 * @author: songww 7 * @author: songww
8 * @date: 2020年5月6日 上午11:33:13 8 * @date: 2020年5月6日 上午11:33:13
9 */ 9 */
10 -public class OutlineEvent extends ApplicationEvent { 10 +public class OfflineEvent extends ApplicationEvent {
11 11
12 /** 12 /**
13 * @Title: OutlineEvent 13 * @Title: OutlineEvent
@@ -15,7 +15,7 @@ public class OutlineEvent extends ApplicationEvent { @@ -15,7 +15,7 @@ public class OutlineEvent extends ApplicationEvent {
15 * @param: @param source 15 * @param: @param source
16 * @throws 16 * @throws
17 */ 17 */
18 - public OutlineEvent(Object source) { 18 + public OfflineEvent(Object source) {
19 super(source); 19 super(source);
20 } 20 }
21 21
src/main/java/com/genersoft/iot/vmp/gb28181/event/outline/OutlineEventListener.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java
1 -package com.genersoft.iot.vmp.gb28181.event.outline; 1 +package com.genersoft.iot.vmp.gb28181.event.offline;
2 2
3 import org.slf4j.Logger; 3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory; 4 import org.slf4j.LoggerFactory;
@@ -13,14 +13,14 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -13,14 +13,14 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
13 /** 13 /**
14 * @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源: 14 * @Description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源:
15 * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor} 15 * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.request.impl.RegisterRequestProcessor}
16 - * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.outline.OutlineEventListener} 16 + * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}
17 * @author: songww 17 * @author: songww
18 * @date: 2020年5月6日 下午1:51:23 18 * @date: 2020年5月6日 下午1:51:23
19 */ 19 */
20 @Component 20 @Component
21 -public class OutlineEventListener implements ApplicationListener<OutlineEvent> { 21 +public class OfflineEventListener implements ApplicationListener<OfflineEvent> {
22 22
23 - private final static Logger logger = LoggerFactory.getLogger(OutlineEventListener.class); 23 + private final static Logger logger = LoggerFactory.getLogger(OfflineEventListener.class);
24 24
25 @Autowired 25 @Autowired
26 private IVideoManagerStorager storager; 26 private IVideoManagerStorager storager;
@@ -29,7 +29,7 @@ public class OutlineEventListener implements ApplicationListener&lt;OutlineEvent&gt; { @@ -29,7 +29,7 @@ public class OutlineEventListener implements ApplicationListener&lt;OutlineEvent&gt; {
29 private RedisUtil redis; 29 private RedisUtil redis;
30 30
31 @Override 31 @Override
32 - public void onApplicationEvent(OutlineEvent event) { 32 + public void onApplicationEvent(OfflineEvent event) {
33 33
34 if (logger.isDebugEnabled()) { 34 if (logger.isDebugEnabled()) {
35 logger.debug("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom()); 35 logger.debug("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -79,7 +79,7 @@ public interface ISIPCommander { @@ -79,7 +79,7 @@ public interface ISIPCommander {
79 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss 79 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
80 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 80 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
81 */ 81 */
82 - public String playbackStreamCmd(Device device,String channelId, String recordId, String startTime, String endTime); 82 + public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime);
83 83
84 /** 84 /**
85 * 语音广播 85 * 语音广播
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2
3 import java.text.ParseException; 3 import java.text.ParseException;
4 -import java.util.Random;  
5 4
  5 +import javax.sip.ClientTransaction;
6 import javax.sip.InvalidArgumentException; 6 import javax.sip.InvalidArgumentException;
7 import javax.sip.SipException; 7 import javax.sip.SipException;
8 import javax.sip.message.Request; 8 import javax.sip.message.Request;
9 9
10 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.beans.factory.annotation.Autowired;
11 -import org.springframework.context.ApplicationEventPublisher;  
12 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
13 12
14 import com.genersoft.iot.vmp.conf.SipConfig; 13 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -19,8 +18,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; @@ -19,8 +18,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
19 import com.genersoft.iot.vmp.gb28181.utils.DateUtil; 18 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
20 import com.genersoft.iot.vmp.gb28181.utils.SsrcUtil; 19 import com.genersoft.iot.vmp.gb28181.utils.SsrcUtil;
21 20
22 -import tk.mybatis.mapper.util.StringUtil;  
23 -  
24 /** 21 /**
25 * @Description:设备能力接口,用于定义设备的控制、查询能力 22 * @Description:设备能力接口,用于定义设备的控制、查询能力
26 * @author: songww 23 * @author: songww
@@ -181,16 +178,16 @@ public class SIPCommander implements ISIPCommander { @@ -181,16 +178,16 @@ public class SIPCommander implements ISIPCommander {
181 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 178 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
182 */ 179 */
183 @Override 180 @Override
184 - public String playbackStreamCmd(Device device, String channelId, String recordId, String startTime, String endTime) { 181 + public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) {
185 try { 182 try {
186 183
187 String ssrc = SsrcUtil.getPlayBackSsrc(); 184 String ssrc = SsrcUtil.getPlayBackSsrc();
188 // 185 //
189 StringBuffer content = new StringBuffer(200); 186 StringBuffer content = new StringBuffer(200);
190 content.append("v=0\r\n"); 187 content.append("v=0\r\n");
191 - content.append("o="+channelId+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n"); 188 + content.append("o="+device.getDeviceId()+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n");
192 content.append("s=Playback\r\n"); 189 content.append("s=Playback\r\n");
193 - content.append("u="+recordId+":3\r\n"); 190 + content.append("u="+channelId+":3\r\n");
194 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n"); 191 content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
195 content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); 192 content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
196 if(device.getTransport().equals("TCP")) { 193 if(device.getTransport().equals("TCP")) {
@@ -439,11 +436,15 @@ public class SIPCommander implements ISIPCommander { @@ -439,11 +436,15 @@ public class SIPCommander implements ISIPCommander {
439 } 436 }
440 437
441 private void transmitRequest(Device device, Request request) throws SipException { 438 private void transmitRequest(Device device, Request request) throws SipException {
  439 + ClientTransaction clientTransaction = null;
442 if(device.getTransport().equals("TCP")) { 440 if(device.getTransport().equals("TCP")) {
443 - sipLayer.getTcpSipProvider().sendRequest(request); 441 + clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(request);
  442 + //sipLayer.getTcpSipProvider().sendRequest(request);
444 } else if(device.getTransport().equals("UDP")) { 443 } else if(device.getTransport().equals("UDP")) {
445 - sipLayer.getUdpSipProvider().sendRequest(request); 444 + clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request);
  445 + //sipLayer.getUdpSipProvider().sendRequest(request);
446 } 446 }
  447 + clientTransaction.sendRequest();
447 } 448 }
448 449
449 } 450 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -30,6 +30,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -30,6 +30,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
30 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 30 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
31 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; 31 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
32 import com.genersoft.iot.vmp.gb28181.bean.RecordItem; 32 import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
  33 +import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
33 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 34 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
34 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 35 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
35 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 36 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
@@ -69,8 +70,21 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { @@ -69,8 +70,21 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
69 @Autowired 70 @Autowired
70 private DeferredResultHolder deferredResultHolder; 71 private DeferredResultHolder deferredResultHolder;
71 72
  73 + @Autowired
  74 + private DeviceOffLineDetector offLineDetector;
  75 +
72 private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_"; 76 private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
73 77
  78 + private static final String MESSAGE_CATALOG = "Catalog";
  79 + private static final String MESSAGE_DEVICE_INFO = "DeviceInfo";
  80 + private static final String MESSAGE_KEEP_ALIVE = "Keepalive";
  81 + private static final String MESSAGE_ALARM = "Alarm";
  82 + private static final String MESSAGE_RECORD_INFO = "RecordInfo";
  83 +// private static final String MESSAGE_BROADCAST = "Broadcast";
  84 +// private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
  85 +// private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
  86 +// private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";
  87 +
74 /** 88 /**
75 * 处理MESSAGE请求 89 * 处理MESSAGE请求
76 * 90 *
@@ -85,22 +99,31 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { @@ -85,22 +99,31 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
85 this.transaction = transaction; 99 this.transaction = transaction;
86 100
87 Request request = evt.getRequest(); 101 Request request = evt.getRequest();
88 -  
89 - if (new String(request.getRawContent()).contains("<CmdType>Keepalive</CmdType>")) {  
90 - logger.info("接收到KeepAlive消息");  
91 - processMessageKeepAlive(evt);  
92 - } else if (new String(request.getRawContent()).contains("<CmdType>Catalog</CmdType>")) {  
93 - logger.info("接收到Catalog消息");  
94 - processMessageCatalogList(evt);  
95 - } else if (new String(request.getRawContent()).contains("<CmdType>DeviceInfo</CmdType>")) {  
96 - logger.info("接收到DeviceInfo消息");  
97 - processMessageDeviceInfo(evt);  
98 - } else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) {  
99 - logger.info("接收到Alarm消息");  
100 - processMessageAlarm(evt);  
101 - } else if (new String(request.getRawContent()).contains("<CmdType>RecordInfo</CmdType>")) {  
102 - logger.info("接收到RecordInfo消息");  
103 - processMessageRecordInfo(evt); 102 + SAXReader reader = new SAXReader();
  103 + Document xml;
  104 + try {
  105 + xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
  106 + Element rootElement = xml.getRootElement();
  107 + String cmd = rootElement.element("CmdType").getStringValue();
  108 +
  109 + if (MESSAGE_KEEP_ALIVE.equals(cmd)) {
  110 + logger.info("接收到KeepAlive消息");
  111 + processMessageKeepAlive(evt);
  112 + } else if (MESSAGE_CATALOG.equals(cmd)) {
  113 + logger.info("接收到Catalog消息");
  114 + processMessageCatalogList(evt);
  115 + } else if (MESSAGE_DEVICE_INFO.equals(cmd)) {
  116 + logger.info("接收到DeviceInfo消息");
  117 + processMessageDeviceInfo(evt);
  118 + } else if (MESSAGE_ALARM.equals(cmd)) {
  119 + logger.info("接收到Alarm消息");
  120 + processMessageAlarm(evt);
  121 + } else if (MESSAGE_RECORD_INFO.equals(cmd)) {
  122 + logger.info("接收到RecordInfo消息");
  123 + processMessageRecordInfo(evt);
  124 + }
  125 + } catch (DocumentException e) {
  126 + e.printStackTrace();
104 } 127 }
105 128
106 } 129 }
@@ -247,12 +270,17 @@ public class MessageRequestProcessor implements ISIPRequestProcessor { @@ -247,12 +270,17 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
247 */ 270 */
248 private void processMessageKeepAlive(RequestEvent evt){ 271 private void processMessageKeepAlive(RequestEvent evt){
249 try { 272 try {
250 - Request request = evt.getRequest();  
251 - Response response = layer.getMessageFactory().createResponse(Response.OK,request);  
252 Element rootElement = getRootElement(evt); 273 Element rootElement = getRootElement(evt);
253 - Element deviceIdElement = rootElement.element("DeviceID"); 274 + String deviceId = XmlUtil.getText(rootElement,"DeviceID");
  275 + Request request = evt.getRequest();
  276 + Response response = null;
  277 + if (offLineDetector.isOnline(deviceId)) {
  278 + response = layer.getMessageFactory().createResponse(Response.OK,request);
  279 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  280 + } else {
  281 + response = layer.getMessageFactory().createResponse(Response.BAD_REQUEST,request);
  282 + }
254 transaction.sendResponse(response); 283 transaction.sendResponse(response);
255 - publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);  
256 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { 284 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
257 e.printStackTrace(); 285 e.printStackTrace();
258 } 286 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.response.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
2 2
  3 +import java.text.ParseException;
  4 +
  5 +import javax.sip.ClientTransaction;
3 import javax.sip.Dialog; 6 import javax.sip.Dialog;
4 import javax.sip.InvalidArgumentException; 7 import javax.sip.InvalidArgumentException;
5 import javax.sip.ResponseEvent; 8 import javax.sip.ResponseEvent;
6 import javax.sip.SipException; 9 import javax.sip.SipException;
  10 +import javax.sip.address.SipURI;
  11 +import javax.sip.header.CSeqHeader;
  12 +import javax.sip.header.ViaHeader;
7 import javax.sip.message.Request; 13 import javax.sip.message.Request;
  14 +import javax.sip.message.Response;
8 15
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
9 import org.springframework.stereotype.Component; 18 import org.springframework.stereotype.Component;
10 19
11 import com.genersoft.iot.vmp.conf.SipConfig; 20 import com.genersoft.iot.vmp.conf.SipConfig;
12 import com.genersoft.iot.vmp.gb28181.SipLayer; 21 import com.genersoft.iot.vmp.gb28181.SipLayer;
  22 +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
13 import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; 23 import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
14 24
15 /** 25 /**
@@ -20,20 +30,51 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor; @@ -20,20 +30,51 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
20 @Component 30 @Component
21 public class InviteResponseProcessor implements ISIPResponseProcessor { 31 public class InviteResponseProcessor implements ISIPResponseProcessor {
22 32
  33 + private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
  34 +
23 /** 35 /**
24 * 处理invite响应 36 * 处理invite响应
25 * 37 *
26 - * @param request 38 + * @param evt
27 * 响应消息 39 * 响应消息
28 */ 40 */
29 @Override 41 @Override
30 public void process(ResponseEvent evt, SipLayer layer, SipConfig config) { 42 public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
31 try { 43 try {
32 - Dialog dialog = evt.getDialog();  
33 - Request reqAck =dialog.createAck(1L);  
34 - dialog.sendAck(reqAck); 44 + Response response = evt.getResponse();
  45 + int statusCode = response.getStatusCode();
  46 + //trying不会回复
  47 + if(statusCode == Response.TRYING){
  48 +
  49 + }
  50 + //成功响应
  51 + //下发ack
  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);
  73 + }
35 } catch (InvalidArgumentException | SipException e) { 74 } catch (InvalidArgumentException | SipException e) {
36 e.printStackTrace(); 75 e.printStackTrace();
  76 + } catch (ParseException e) {
  77 + e.printStackTrace();
37 } 78 }
38 } 79 }
39 80
src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java
@@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.PathVariable; @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.PathVariable;
10 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.RestController; 11 import org.springframework.web.bind.annotation.RestController;
12 12
  13 +import com.alibaba.fastjson.JSONObject;
13 import com.genersoft.iot.vmp.gb28181.bean.Device; 14 import com.genersoft.iot.vmp.gb28181.bean.Device;
14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
15 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -30,7 +31,7 @@ public class PlaybackController { @@ -30,7 +31,7 @@ public class PlaybackController {
30 public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){ 31 public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){
31 32
32 Device device = storager.queryVideoDevice(deviceId); 33 Device device = storager.queryVideoDevice(deviceId);
33 - String ssrc = cmder.playStreamCmd(device, channelId); 34 + String ssrc = cmder.playbackStreamCmd(device, channelId, startTime, endTime);
34 35
35 if (logger.isDebugEnabled()) { 36 if (logger.isDebugEnabled()) {
36 logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId)); 37 logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId));
@@ -38,7 +39,9 @@ public class PlaybackController { @@ -38,7 +39,9 @@ public class PlaybackController {
38 } 39 }
39 40
40 if(ssrc!=null) { 41 if(ssrc!=null) {
41 - return new ResponseEntity<String>(ssrc,HttpStatus.OK); 42 + JSONObject json = new JSONObject();
  43 + json.put("ssrc", ssrc);
  44 + return new ResponseEntity<String>(json.toString(),HttpStatus.OK);
42 } else { 45 } else {
43 logger.warn("设备预览API调用失败!"); 46 logger.warn("设备预览API调用失败!");
44 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); 47 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
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: 10.200.64.63 29 + ip: 127.0.0.1
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