Commit f2279859b367fda6108a5ea22c572d38d89d338d
1 parent
17f4fe25
增加对水星IPC的兼容
增加对SIP错误的订阅,刷新通道或点播或回放出现sip错误时及时返回给页面 优化UI,增加按钮loading
Showing
13 changed files
with
176 additions
and
46 deletions
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
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 | //通知设备上传媒体流 | ... | ... |