Commit f2279859b367fda6108a5ea22c572d38d89d338d

Authored by panlinlin
1 parent 17f4fe25

增加对水星IPC的兼容

增加对SIP错误的订阅,刷新通道或点播或回放出现sip错误时及时返回给页面
优化UI,增加按钮loading
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
... ... @@ -8,8 +8,10 @@ import java.util.concurrent.ThreadPoolExecutor;
8 8 import java.util.concurrent.TimeUnit;
9 9  
10 10 import javax.sip.*;
  11 +import javax.sip.header.CallIdHeader;
11 12 import javax.sip.message.Response;
12 13  
  14 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
13 15 import org.slf4j.Logger;
14 16 import org.slf4j.LoggerFactory;
15 17 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -34,6 +36,9 @@ public class SipLayer implements SipListener {
34 36 @Autowired
35 37 private SIPProcessorFactory processorFactory;
36 38  
  39 + @Autowired
  40 + private SipSubscribe sipSubscribe;
  41 +
37 42 private SipStack sipStack;
38 43  
39 44 private SipFactory sipFactory;
... ... @@ -139,11 +144,19 @@ public class SipLayer implements SipListener {
139 144 // 增加其它无需回复的响应,如101、180等
140 145 } else {
141 146 logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
  147 + if (evt.getResponse() != null && sipSubscribe.getSize() > 0 ) {
  148 + CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
  149 + if (callIdHeader != null) {
  150 + SipSubscribe.Event subscribe = sipSubscribe.getSubscribe(callIdHeader.getCallId());
  151 + if (subscribe != null) {
  152 + subscribe.response(evt);
  153 + }
  154 + }
  155 + }
142 156 }
143   - // trying不会回复
144   - // if (status == Response.TRYING) {
145 157  
146   - // }
  158 +
  159 +
147 160 }
148 161  
149 162 /**
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
... ... @@ -21,6 +21,6 @@ public class RegisterLogicHandler {
21 21 // TODO 后续处理,只有第一次注册时调用查询设备信息,如需更新调用更新API接口
22 22 cmder.deviceInfoQuery(device);
23 23  
24   - cmder.catalogQuery(device);
  24 + cmder.catalogQuery(device, null);
25 25 }
26 26 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.event;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import javax.sip.ResponseEvent;
  10 +import javax.sip.message.Request;
  11 +import java.util.EventObject;
  12 +import java.util.Map;
  13 +import java.util.concurrent.ConcurrentHashMap;
  14 +
  15 +@Component
  16 +public class SipSubscribe {
  17 +
  18 + private final static Logger logger = LoggerFactory.getLogger(SipSubscribe.class);
  19 +
  20 + private Map<String, SipSubscribe.Event> allSubscribes = new ConcurrentHashMap<>();
  21 +
  22 + public interface Event {
  23 + void response(ResponseEvent event);
  24 + }
  25 +
  26 + public void addSubscribe(String key, SipSubscribe.Event event) {
  27 + allSubscribes.put(key, event);
  28 + }
  29 +
  30 + public SipSubscribe.Event getSubscribe(String key) {
  31 + return allSubscribes.get(key);
  32 + }
  33 +
  34 + public int getSize(){
  35 + return allSubscribes.size();
  36 + }
  37 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
... ... @@ -4,10 +4,13 @@ import javax.sip.RequestEvent;
4 4 import javax.sip.ResponseEvent;
5 5 import javax.sip.SipProvider;
6 6 import javax.sip.header.CSeqHeader;
  7 +import javax.sip.header.CallIdHeader;
  8 +import javax.sip.header.Header;
7 9 import javax.sip.message.Request;
8 10 import javax.sip.message.Response;
9 11  
10 12 import com.alibaba.fastjson.JSON;
  13 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
11 14 import org.slf4j.Logger;
12 15 import org.slf4j.LoggerFactory;
13 16 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -83,7 +86,8 @@ public class SIPProcessorFactory {
83 86  
84 87 @Autowired
85 88 private OtherResponseProcessor otherResponseProcessor;
86   -
  89 +
  90 +
87 91 // 注:这里使用注解会导致循环依赖注入,暂用springBean
88 92 private SipProvider tcpSipProvider;
89 93  
... ... @@ -94,6 +98,7 @@ public class SIPProcessorFactory {
94 98 Request request = evt.getRequest();
95 99 String method = request.getMethod();
96 100 // logger.info("接收到消息:"+request.getMethod());
  101 +// sipSubscribe.getSubscribe(evt.getServerTransaction().getBranchId()).response(evt);
97 102 if (Request.INVITE.equals(method)) {
98 103 InviteRequestProcessor processor = new InviteRequestProcessor();
99 104 processor.setRequestEvent(evt);
... ... @@ -145,6 +150,7 @@ public class SIPProcessorFactory {
145 150 }
146 151  
147 152 public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) {
  153 +
148 154 Response response = evt.getResponse();
149 155 CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
150 156 String method = cseqHeader.getMethod();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
6 7  
7 8 /**
... ... @@ -83,7 +84,7 @@ public interface ISIPCommander {
83 84 * @param device 视频设备
84 85 * @param channelId 预览通道
85 86 */
86   - void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event);
  87 + void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
87 88  
88 89 /**
89 90 * 请求回放视频流
... ... @@ -93,7 +94,7 @@ public interface ISIPCommander {
93 94 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
94 95 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
95 96 */
96   - void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event);
  97 + void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
97 98  
98 99 /**
99 100 * 视频流停止
... ... @@ -175,7 +176,7 @@ public interface ISIPCommander {
175 176 *
176 177 * @param device 视频设备
177 178 */
178   - boolean catalogQuery(Device device);
  179 + boolean catalogQuery(Device device, SipSubscribe.Event errorEvent);
179 180  
180 181 /**
181 182 * 查询录像信息
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -4,22 +4,22 @@ import java.text.ParseException;
4 4 import java.util.regex.Matcher;
5 5 import java.util.regex.Pattern;
6 6  
7   -import javax.sip.ClientTransaction;
8   -import javax.sip.Dialog;
9   -import javax.sip.InvalidArgumentException;
10   -import javax.sip.SipException;
11   -import javax.sip.SipProvider;
12   -import javax.sip.TransactionDoesNotExistException;
  7 +import javax.sip.*;
13 8 import javax.sip.address.SipURI;
  9 +import javax.sip.header.CallIdHeader;
  10 +import javax.sip.header.Header;
14 11 import javax.sip.header.ViaHeader;
15 12 import javax.sip.message.Request;
16 13  
17 14 import com.alibaba.fastjson.JSONObject;
18 15 import com.genersoft.iot.vmp.conf.MediaServerConfig;
19 16 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  17 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
20 18 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
21 19 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
22 20 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  21 +import org.slf4j.Logger;
  22 +import org.slf4j.LoggerFactory;
23 23 import org.springframework.beans.factory.annotation.Autowired;
24 24 import org.springframework.beans.factory.annotation.Qualifier;
25 25 import org.springframework.beans.factory.annotation.Value;
... ... @@ -39,6 +39,8 @@ import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
39 39 */
40 40 @Component
41 41 public class SIPCommander implements ISIPCommander {
  42 +
  43 + private final Logger logger = LoggerFactory.getLogger(SIPCommander.class);
42 44  
43 45 @Autowired
44 46 private SipConfig sipConfig;
... ... @@ -69,6 +71,9 @@ public class SIPCommander implements ISIPCommander {
69 71 @Autowired
70 72 private ZLMHttpHookSubscribe subscribe;
71 73  
  74 + @Autowired
  75 + private SipSubscribe sipSubscribe;
  76 +
72 77  
73 78  
74 79 /**
... ... @@ -221,7 +226,7 @@ public class SIPCommander implements ISIPCommander {
221 226  
222 227 Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
223 228  
224   - transmitRequest(device, request);
  229 + transmitRequest(device, request, null);
225 230 return true;
226 231 } catch (SipException | ParseException | InvalidArgumentException e) {
227 232 e.printStackTrace();
... ... @@ -256,22 +261,23 @@ public class SIPCommander implements ISIPCommander {
256 261 ptzXml.append("</Control>\r\n");
257 262  
258 263 Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
259   -
260   - transmitRequest(device, request);
  264 + transmitRequest(device, request, null);
261 265 return true;
262 266 } catch (SipException | ParseException | InvalidArgumentException e) {
263 267 e.printStackTrace();
264 268 }
265 269 return false;
266 270 }
  271 +
267 272 /**
268   - * 请求预览视频流
269   - *
  273 + * 请求预览视频流
270 274 * @param device 视频设备
271 275 * @param channelId 预览通道
  276 + * @param event hook订阅
  277 + * @param errorEvent sip错误订阅
272 278 */
273 279 @Override
274   - public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event) {
  280 + public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
275 281 try {
276 282  
277 283 String ssrc = streamSession.createPlaySsrc();
... ... @@ -300,7 +306,8 @@ public class SIPCommander implements ISIPCommander {
300 306 //
301 307 StringBuffer content = new StringBuffer(200);
302 308 content.append("v=0\r\n");
303   - content.append("o="+channelId+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
  309 +// content.append("o="+channelId+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
  310 + content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
304 311 content.append("s=Play\r\n");
305 312 content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
306 313 content.append("t=0 0\r\n");
... ... @@ -332,7 +339,7 @@ public class SIPCommander implements ISIPCommander {
332 339  
333 340 Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "live", null, ssrc);
334 341  
335   - ClientTransaction transaction = transmitRequest(device, request);
  342 + ClientTransaction transaction = transmitRequest(device, request, errorEvent);
336 343 streamSession.put(streamId, transaction);
337 344 DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId);
338 345 if (deviceChannel != null) {
... ... @@ -357,7 +364,8 @@ public class SIPCommander implements ISIPCommander {
357 364 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
358 365 */
359 366 @Override
360   - public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event) {
  367 + public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
  368 + , SipSubscribe.Event errorEvent) {
361 369 try {
362 370 MediaServerConfig mediaInfo = storager.getMediaInfo();
363 371 String ssrc = streamSession.createPlayBackSsrc();
... ... @@ -413,8 +421,8 @@ public class SIPCommander implements ISIPCommander {
413 421 content.append("y="+ssrc+"\r\n");//ssrc
414 422  
415 423 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "playback", null);
416   -
417   - ClientTransaction transaction = transmitRequest(device, request);
  424 +
  425 + ClientTransaction transaction = transmitRequest(device, request, errorEvent);
418 426 streamSession.put(streamId, transaction);
419 427  
420 428 } catch ( SipException | ParseException | InvalidArgumentException e) {
... ... @@ -575,7 +583,8 @@ public class SIPCommander implements ISIPCommander {
575 583 catalogXml.append("</Query>\r\n");
576 584  
577 585 Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag");
578   - transmitRequest(device, request);
  586 +
  587 + transmitRequest(device, request, null);
579 588  
580 589 } catch (SipException | ParseException | InvalidArgumentException e) {
581 590 e.printStackTrace();
... ... @@ -590,7 +599,7 @@ public class SIPCommander implements ISIPCommander {
590 599 * @param device 视频设备
591 600 */
592 601 @Override
593   - public boolean catalogQuery(Device device) {
  602 + public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) {
594 603 // 清空通道
595 604 storager.cleanChannelsForDevice(device.getDeviceId());
596 605 try {
... ... @@ -602,8 +611,9 @@ public class SIPCommander implements ISIPCommander {
602 611 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
603 612 catalogXml.append("</Query>\r\n");
604 613  
605   - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag");
606   - transmitRequest(device, request);
  614 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", null);
  615 +
  616 + transmitRequest(device, request, errorEvent);
607 617 } catch (SipException | ParseException | InvalidArgumentException e) {
608 618 e.printStackTrace();
609 619 return false;
... ... @@ -636,7 +646,9 @@ public class SIPCommander implements ISIPCommander {
636 646 recordInfoXml.append("</Query>\r\n");
637 647  
638 648 Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", "ToRecordInfoTag");
639   - transmitRequest(device, request);
  649 +
  650 +
  651 + transmitRequest(device, request, null);
640 652 } catch (SipException | ParseException | InvalidArgumentException e) {
641 653 e.printStackTrace();
642 654 return false;
... ... @@ -688,13 +700,20 @@ public class SIPCommander implements ISIPCommander {
688 700 return false;
689 701 }
690 702  
691   - private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
  703 + private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent) throws SipException {
692 704 ClientTransaction clientTransaction = null;
693 705 if("TCP".equals(device.getTransport())) {
694 706 clientTransaction = tcpSipProvider.getNewClientTransaction(request);
695 707 } else if("UDP".equals(device.getTransport())) {
696 708 clientTransaction = udpSipProvider.getNewClientTransaction(request);
697 709 }
  710 +
  711 + // 添加订阅
  712 + if (errorEvent != null) {
  713 + CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
  714 + sipSubscribe.addSubscribe(callIdHeader.getCallId(), errorEvent);
  715 + }
  716 +
698 717 clientTransaction.sendRequest();
699 718 return clientTransaction;
700 719 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
... ... @@ -294,7 +294,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
294 294 device.setStreamMode("UDP");
295 295 }
296 296 storager.updateDevice(device);
297   - cmder.catalogQuery(device);
  297 + cmder.catalogQuery(device, null);
298 298 // 回复200 OK
299 299 responseAck(evt);
300 300 if (offLineDetector.isOnline(deviceId)) {
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -323,7 +323,7 @@ public class ZLMHttpHookListener {
323 323 cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
324 324 logger.info("收到订阅消息: " + response.toJSONString());
325 325 playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
326   - });
  326 + }, null);
327 327 }
328 328  
329 329 }
... ...
src/main/java/com/genersoft/iot/vmp/utils/SpringBeanFactory.java
... ... @@ -34,6 +34,7 @@ public class SpringBeanFactory implements ApplicationContextAware {
34 34 * 获取对象 这里重写了bean方法,起主要作用
35 35 */
36 36 public static Object getBean(String beanId) throws BeansException {
  37 + if (applicationContext == null) return null;
37 38 return applicationContext.getBean(beanId);
38 39 }
39 40  
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/device/DeviceController.java
... ... @@ -4,6 +4,7 @@ import java.util.List;
4 4  
5 5 import com.genersoft.iot.vmp.common.PageResult;
6 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  7 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
7 8 import org.slf4j.Logger;
8 9 import org.slf4j.LoggerFactory;
9 10 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -19,6 +20,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
19 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
20 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
21 22  
  23 +import javax.sip.message.Response;
  24 +
22 25 @CrossOrigin
23 26 @RestController
24 27 @RequestMapping("/api")
... ... @@ -86,11 +89,25 @@ public class DeviceController {
86 89  
87 90 if (logger.isDebugEnabled()) {
88 91 }
89   - logger.debug("设备信息同步API调用,deviceId:" + deviceId);
  92 + logger.debug("设备通道信息同步API调用,deviceId:" + deviceId);
90 93  
91 94 Device device = storager.queryVideoDevice(deviceId);
92   - cmder.catalogQuery(device);
93   - DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>();
  95 + cmder.catalogQuery(device, event -> {
  96 + Response response = event.getResponse();
  97 + RequestMessage msg = new RequestMessage();
  98 + msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
  99 + msg.setData(String.format("同步通道失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  100 + resultHolder.invokeResult(msg);
  101 + });
  102 + DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(2*1000L);
  103 + result.onTimeout(()->{
  104 + logger.warn(String.format("设备通道信息同步超时"));
  105 + // 释放rtpserver
  106 + RequestMessage msg = new RequestMessage();
  107 + msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
  108 + msg.setData("Timeout");
  109 + resultHolder.invokeResult(msg);
  110 + });
94 111 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
95 112 return result;
96 113 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
... ... @@ -28,6 +28,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
28 28 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
29 29 import org.springframework.web.context.request.async.DeferredResult;
30 30  
  31 +import javax.sip.message.Response;
31 32 import java.text.DecimalFormat;
32 33 import java.util.UUID;
33 34  
... ... @@ -72,6 +73,12 @@ public class PlayController {
72 73 cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
73 74 logger.info("收到订阅消息: " + response.toJSONString());
74 75 playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
  76 + }, event -> {
  77 + RequestMessage msg = new RequestMessage();
  78 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  79 + Response response = event.getResponse();
  80 + msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  81 + resultHolder.invokeResult(msg);
75 82 });
76 83 } else {
77 84 String streamId = streamInfo.getStreamId();
... ... @@ -86,6 +93,12 @@ public class PlayController {
86 93 cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
87 94 logger.info("收到订阅消息: " + response.toJSONString());
88 95 playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
  96 + }, event -> {
  97 + RequestMessage msg = new RequestMessage();
  98 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  99 + Response response = event.getResponse();
  100 + msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  101 + resultHolder.invokeResult(msg);
89 102 });
90 103 }
91 104 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java
... ... @@ -27,6 +27,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
27 27 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
28 28 import org.springframework.web.context.request.async.DeferredResult;
29 29  
  30 +import javax.sip.message.Response;
30 31 import java.util.UUID;
31 32  
32 33 @CrossOrigin
... ... @@ -78,6 +79,12 @@ public class PlaybackController {
78 79 cmder.playbackStreamCmd(device, channelId, startTime, endTime, (JSONObject response) -> {
79 80 logger.info("收到订阅消息: " + response.toJSONString());
80 81 playService.onPublishHandlerForPlayBack(response, deviceId, channelId, uuid.toString());
  82 + }, event -> {
  83 + Response response = event.getResponse();
  84 + RequestMessage msg = new RequestMessage();
  85 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  86 + msg.setData(String.format("回放失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  87 + resultHolder.invokeResult(msg);
81 88 });
82 89  
83 90 return result;
... ...
web_src/src/components/videoList.vue
... ... @@ -8,7 +8,7 @@
8 8 <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9 9 <span style="font-size: 1rem; font-weight: bold;">设备列表</span>
10 10 <div style="position: absolute; right: 1rem; top: 0.3rem;">
11   - <el-button icon="el-icon-refresh-right" circle size="mini" @click="getDeviceList()"></el-button>
  11 + <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>
12 12 </div>
13 13 </div>
14 14 <devicePlayer ref="devicePlayer"></devicePlayer>
... ... @@ -51,7 +51,7 @@
51 51  
52 52 <el-table-column label="操作" width="240" align="center" fixed="right">
53 53 <template slot-scope="scope">
54   - <el-button size="mini" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button>
  54 + <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button>
55 55 <el-button size="mini" icon="el-icon-s-open" type="primary" @click="showChannelList(scope.row)">查看通道</el-button>
56 56 </template>
57 57 </el-table-column>
... ... @@ -90,7 +90,8 @@
90 90 winHeight: window.innerHeight - 200,
91 91 currentPage:1,
92 92 count:15,
93   - total:0
  93 + total:0,
  94 + getDeviceListLoading: false
94 95 };
95 96 },
96 97 computed: {
... ... @@ -130,7 +131,7 @@
130 131 },
131 132 getDeviceList: function() {
132 133 let that = this;
133   -
  134 + this.getDeviceListLoading = true;
134 135 this.$axios.get(`/api/devices`,{
135 136 params: {
136 137 page: that.currentPage - 1,
... ... @@ -141,9 +142,11 @@
141 142 console.log(res);
142 143 that.total = res.data.total;
143 144 that.deviceList = res.data.data;
  145 + that.getDeviceListLoading = false;
144 146 })
145 147 .catch(function (error) {
146 148 console.log(error);
  149 + that.getDeviceListLoading = false;
147 150 });
148 151  
149 152 },
... ... @@ -158,17 +161,30 @@
158 161 refDevice: function(itemData) {
159 162 ///api/devices/{deviceId}/sync
160 163 console.log("刷新对应设备:" + itemData.deviceId);
  164 + var that = this;
  165 + that.$refs[itemData.deviceId + 'refbtn' ].loading = true;
161 166 this.$axios({
162 167 method: 'post',
163 168 url: '/api/devices/' + itemData.deviceId + '/sync'
164 169 }).then(function(res) {
165   - // console.log("刷新设备结果:"+JSON.stringify(res));
  170 + console.log("刷新设备结果:"+JSON.stringify(res));
  171 + if (!res.data.deviceId) {
  172 + that.$message({
  173 + showClose: true,
  174 + message: res.data,
  175 + type: 'error'
  176 + });
  177 + }else{
  178 + that.$message({
  179 + showClose: true,
  180 + message: '请求成功',
  181 + type: 'success'
  182 + });
  183 + }
  184 + that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
166 185 }).catch(function(e) {
167   - that.$message({
168   - showClose: true,
169   - message: '请求成功',
170   - type: 'success'
171   - });
  186 + console.error(e)
  187 + that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
172 188 });;
173 189 },
174 190 //通知设备上传媒体流
... ...