From 335916f1f15eb9d0b34dea38cacee2300eac0606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=98=B2?= Date: Mon, 7 Mar 2022 14:20:27 +0800 Subject: [PATCH 01/96] =?UTF-8?q?InviteRequestProcessor=E7=B1=BB=E4=B8=AD?= =?UTF-8?q?=EF=BC=8Cchannelid=E4=BB=8Einvite=E6=B6=88=E6=81=AF=E7=9A=84hea?= =?UTF-8?q?der=20subject=E8=8E=B7=E5=8F=96=EF=BC=8C=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E4=BB=8E=E7=AC=AC=E4=B8=80=E8=A1=8Crequest=20line=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E3=80=82=E5=8E=9F=E5=9B=A0=E6=98=AF=E5=92=8C=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E5=B9=B3=E5=8F=B0=E5=AF=B9=E6=8E=A5=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E9=80=81=E7=9A=84invite=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E7=AC=AC=E4=B8=80=E8=A1=8C=E4=B8=BA=E5=9B=BD=E6=A0=87=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E7=BC=96=E7=A0=81=E8=80=8C=E4=B8=8D=E6=98=AF=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E9=80=9A=E9=81=93=E7=BC=96=E7=A0=81=EF=BC=8C=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=8A=A5=E9=94=99=E9=80=9A=E9=81=93=E4=B8=8D=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=EF=BC=8C=E8=BF=94=E5=9B=9E404=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/request/impl/InviteRequestProcessor.java | 6 +++++- .../com/genersoft/iot/vmp/gb28181/utils/SipUtils.java | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index f861da41..9cf0d1bf 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -26,6 +26,7 @@ import gov.nist.javax.sdp.TimeDescriptionImpl; import gov.nist.javax.sdp.fields.TimeField; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; +import gov.nist.javax.sip.header.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -40,6 +41,7 @@ import javax.sip.SipException; import javax.sip.address.SipURI; import javax.sip.header.CallIdHeader; import javax.sip.header.FromHeader; +import javax.sip.header.Header; import javax.sip.message.Request; import javax.sip.message.Response; import java.text.ParseException; @@ -105,7 +107,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements try { Request request = evt.getRequest(); SipURI sipURI = (SipURI) request.getRequestURI(); - String channelId = sipURI.getUser(); + //从subject读取channelId,不再从request-line读取。 有些平台request-line是平台国标编码,不是设备国标编码。 + //String channelId = sipURI.getUser(); + String channelId = SipUtils.getChannelIdFromHeader(request); String requesterId = SipUtils.getUserIdFromFromHeader(request); CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME); if (requesterId == null || channelId == null) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java index 9dd02715..80258188 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java @@ -2,8 +2,10 @@ package com.genersoft.iot.vmp.gb28181.utils; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; +import gov.nist.javax.sip.header.Subject; import javax.sip.header.FromHeader; +import javax.sip.header.Header; import javax.sip.message.Request; /** @@ -18,6 +20,13 @@ public class SipUtils { FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); return getUserIdFromFromHeader(fromHeader); } + /** + * 从subject读取channelId + * */ + public static String getChannelIdFromHeader(Request request) { + Header subject = request.getHeader("subject"); + return ((Subject) subject).getSubject().split(":")[0]; + } public static String getUserIdFromFromHeader(FromHeader fromHeader) { AddressImpl address = (AddressImpl)fromHeader.getAddress(); From 70ada79c7a3f7c0c2e47cde5619ba94d5d57708b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E4=BF=8A=E6=9D=B0?= <502612493@qq.com> Date: Tue, 15 Mar 2022 16:31:06 +0800 Subject: [PATCH 02/96] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddevice=5Fchannel?= =?UTF-8?q?=E7=9A=84Id=E6=94=B9=E5=8F=98=E5=B8=A6=E6=9D=A5=E7=9A=84tree?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/genersoft/iot/vmp/utils/node/BaseNode.java | 14 +++----------- .../genersoft/iot/vmp/utils/node/ForestNode.java | 4 ++-- .../iot/vmp/utils/node/ForestNodeManager.java | 10 +++++----- .../iot/vmp/utils/node/ForestNodeMerger.java | 6 +++--- .../com/genersoft/iot/vmp/utils/node/INode.java | 2 +- 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java index 7835feba..89e35a54 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java @@ -16,7 +16,7 @@ public class BaseNode implements INode { /** * 主键ID */ - protected int id; + protected String channelId; /** * 父节点ID @@ -50,12 +50,8 @@ public class BaseNode implements INode { } @Override - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; + public String getChannelId() { + return channelId; } @Override @@ -63,10 +59,6 @@ public class BaseNode implements INode { return parentId; } - public void setParentId(String parentId) { - this.parentId = parentId; - } - @Override public List getChildren() { return children; diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java index 21a48df3..d983c56b 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java @@ -15,8 +15,8 @@ public class ForestNode extends BaseNode { */ private Object content; - public ForestNode(int id, String parentId, Object content) { - this.id = id; + public ForestNode(String id, String parentId, Object content) { + this.channelId = id; this.parentId = parentId; this.content = content; } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java index 895e6de0..affce9d1 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java @@ -17,15 +17,15 @@ public class ForestNodeManager> { /** * 森林的所有节点 */ - private final ImmutableMap nodeMap; + private final ImmutableMap nodeMap; /** * 森林的父节点ID */ - private final Map parentIdMap = Maps.newHashMap(); + private final Map parentIdMap = Maps.newHashMap(); public ForestNodeManager(List nodes) { - nodeMap = Maps.uniqueIndex(nodes, INode::getId); + nodeMap = Maps.uniqueIndex(nodes, INode::getChannelId); } /** @@ -46,7 +46,7 @@ public class ForestNodeManager> { * * @param parentId 父节点ID */ - public void addParentId(int parentId) { + public void addParentId(String parentId) { parentIdMap.put(parentId, ""); } @@ -58,7 +58,7 @@ public class ForestNodeManager> { public List getRoot() { List roots = new ArrayList<>(); nodeMap.forEach((key, node) -> { - if (node.getParentId() == null || parentIdMap.containsKey(node.getId())) { + if (node.getParentId() == null || parentIdMap.containsKey(node.getChannelId())) { roots.add(node); } }); diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java index 062d4cd9..8df6f503 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java @@ -25,7 +25,7 @@ public class ForestNodeMerger { if (node != null) { node.getChildren().add(forestNode); } else { - forestNodeManager.addParentId(forestNode.getId()); + forestNodeManager.addParentId(forestNode.getChannelId()); } } }); @@ -37,8 +37,8 @@ public class ForestNodeMerger { items.forEach(forestNode -> { if (forestNode.getParentId() != null) { INode node = forestNodeManager.getTreeNodeAt(forestNode.getParentId()); - if (CollectionUtil.contains(parentIds, forestNode.getId())){ - forestNodeManager.addParentId(forestNode.getId()); + if (CollectionUtil.contains(parentIds, forestNode.getChannelId())){ + forestNodeManager.addParentId(forestNode.getChannelId()); } else { if (node != null){ node.getChildren().add(forestNode); diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java index c82d6f76..27727470 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java @@ -14,7 +14,7 @@ public interface INode extends Serializable { * * @return String */ - int getId(); + String getChannelId(); /** * 父主键 From 66aac4526b8fc63912e0015ff2fdfeabcec015ce Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 15 Mar 2022 17:45:55 +0800 Subject: [PATCH 03/96] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=A8=E6=B5=81?= =?UTF-8?q?=E5=85=B3=E8=81=94=E5=B9=B3=E5=8F=B0=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/media/zlm/ZLMMediaListManager.java | 18 +++++++++++++++--- .../impl/VideoManagerStoragerImpl.java | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java index c8844959..a4f7815e 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -128,15 +128,27 @@ public class ZLMMediaListManager { if (gbStreams.size() > 0) { for (GbStream gbStream : gbStreams) { // 出现使用相同国标Id的视频流时,使用新流替换旧流, - gbStreamMapper.del(gbStream.getApp(), gbStream.getStream()); - if (!gbStream.isStatus()) { - streamPushMapper.del(gbStream.getApp(), gbStream.getStream()); + if (queryKey != null) { + Matcher matcherForStream = pattern.matcher(gbStream.getStream()); + String queryKeyForStream = null; + if (matcherForStream.find()) { //此处find()每次被调用后,会偏移到下一个匹配 + queryKeyForStream = matcherForStream.group(); + } + if (queryKeyForStream == null || !queryKeyForStream.equals(queryKey)) { + // 此时不是同一个流 + gbStreamMapper.del(gbStream.getApp(), gbStream.getStream()); + if (!gbStream.isStatus()) { + streamPushMapper.del(gbStream.getApp(), gbStream.getStream()); + } + } } } } StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(transform.getApp(), transform.getStream()); if (streamProxyItem != null) { transform.setGbStreamId(streamProxyItem.getGbStreamId()); + transform.setPlatformId(streamProxyItem.getPlatformId()); + transform.setCatalogId(streamProxyItem.getCatalogId()); gbStreamMapper.update(transform); }else { transform.setCreateStamp(System.currentTimeMillis()); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index 0ba0ab4a..e1ccf9a2 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -885,9 +885,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { List parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream(); if (parentPlatforms.size() > 0) { for (ParentPlatform parentPlatform : parentPlatforms) { - StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(streamPushItem.getApp(), streamPushItem.getStream(), + StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(streamPushItem.getApp(), streamPushItem.getStream(), parentPlatform.getServerGBId()); - if (streamProxyItems == null) { + if (streamProxyItem == null) { streamPushItem.setCatalogId(parentPlatform.getCatalogId()); streamPushItem.setPlatformId(parentPlatform.getServerGBId()); platformGbStreamMapper.add(streamPushItem); From e752dbd1a7fdfbb2063c59470b41a8e5dd546c3d Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 16 Mar 2022 10:12:31 +0800 Subject: [PATCH 04/96] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=A8=E6=B5=81?= =?UTF-8?q?=E5=85=B3=E8=81=94=E5=B9=B3=E5=8F=B0=E7=9A=84bug=20again?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/bean/SubscribeHolder.java | 5 +++++ .../iot/vmp/media/zlm/ZLMMediaListManager.java | 15 +++++++++------ .../iot/vmp/storager/dao/GbStreamMapper.java | 13 +++++++++++++ .../storager/impl/VideoManagerStoragerImpl.java | 2 +- .../gb28181/platform/PlatformController.java | 3 ++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java index 287c2a0a..62a45d5a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java @@ -46,4 +46,9 @@ public class SubscribeHolder { } return platforms; } + + public void removeAllSubscribe(String platformId) { + mobilePositionMap.remove(platformId); + catalogMap.remove(platformId); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java index a4f7815e..fa4aa35f 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -128,7 +128,7 @@ public class ZLMMediaListManager { if (gbStreams.size() > 0) { for (GbStream gbStream : gbStreams) { // 出现使用相同国标Id的视频流时,使用新流替换旧流, - if (queryKey != null) { + if (queryKey != null && gbStream.getApp().equals(mediaItem.getApp())) { Matcher matcherForStream = pattern.matcher(gbStream.getStream()); String queryKeyForStream = null; if (matcherForStream.find()) { //此处find()每次被调用后,会偏移到下一个匹配 @@ -144,12 +144,15 @@ public class ZLMMediaListManager { } } } - StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(transform.getApp(), transform.getStream()); - if (streamProxyItem != null) { - transform.setGbStreamId(streamProxyItem.getGbStreamId()); - transform.setPlatformId(streamProxyItem.getPlatformId()); - transform.setCatalogId(streamProxyItem.getCatalogId()); + // StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(transform.getApp(), transform.getStream()); + List gbStreamList = gbStreamMapper.selectByGBId(transform.getGbId()); + if (gbStreamList != null && gbStreamList.size() == 1) { + transform.setGbStreamId(gbStreamList.get(0).getGbStreamId()); + transform.setPlatformId(gbStreamList.get(0).getPlatformId()); + transform.setCatalogId(gbStreamList.get(0).getCatalogId()); + transform.setGbId(gbStreamList.get(0).getGbId()); gbStreamMapper.update(transform); + streamPushMapper.del(gbStreamList.get(0).getApp(), gbStreamList.get(0).getStream()); }else { transform.setCreateStamp(System.currentTimeMillis()); gbStreamMapper.add(transform); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java index b430ebb0..4ed0a0c2 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java @@ -33,6 +33,19 @@ public interface GbStreamMapper { "mediaServerId=#{mediaServerId}," + "status=${status} " + "WHERE app=#{app} AND stream=#{stream}") + int updateByallAndStream(GbStream gbStream); + + @Update("UPDATE gb_stream " + + "SET app=#{app}," + + "stream=#{stream}," + + "gbId=#{gbId}," + + "name=#{name}," + + "streamType=#{streamType}," + + "longitude=#{longitude}, " + + "latitude=#{latitude}," + + "mediaServerId=#{mediaServerId}," + + "status=${status} " + + "WHERE gbStreamId=#{gbStreamId}") int update(GbStream gbStream); @Delete("DELETE FROM gb_stream WHERE app=#{app} AND stream=#{stream}") diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index e1ccf9a2..158a163e 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -772,7 +772,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { try { if (streamProxyMapper.update(streamProxyItem) > 0) { if (!StringUtils.isEmpty(streamProxyItem.getGbId())) { - if (gbStreamMapper.update(streamProxyItem) > 0) { + if (gbStreamMapper.updateByallAndStream(streamProxyItem) > 0) { //事务回滚 dataSourceTransactionManager.rollback(transactionStatus); return false; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java index c3435fd1..878e77c5 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java @@ -305,6 +305,8 @@ public class PlatformController { // 停止发送位置订阅定时任务 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_MobilePosition_" + parentPlatform.getServerGBId(); dynamicTask.stop(key); + // 删除缓存的订阅信息 + subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); if (deleteResult) { return new ResponseEntity<>("success", HttpStatus.OK); } else { @@ -341,7 +343,6 @@ public class PlatformController { * @param platformId 上级平台ID * @param query 查询内容 * @param online 是否在线 - * @param choosed 是否已选中 * @param channelType 通道类型 * @return */ From b1c479b938295834be787a4a724e95bd21ddbddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E4=BF=8A=E6=9D=B0?= <502612493@qq.com> Date: Wed, 16 Mar 2022 11:18:09 +0800 Subject: [PATCH 05/96] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dinfo=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=A4=B4=E4=B8=AD=E7=9A=84cseq=E5=BA=8F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index 1c368bf6..78056791 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -255,9 +255,8 @@ public class SIPRequestHeaderProvider { // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - if (cseq == null) { - cseq = redisCatchStorage.getCSEQ(Request.INFO); - } + + cseq = redisCatchStorage.getCSEQ(Request.INVITE); // ceq CSeqHeader cSeqHeader = sipFactory.createHeaderFactory() .createCSeqHeader(cseq, Request.INFO); From ba3c38d7d352800ccda6c68bb015b071d0794b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E4=BF=8A=E6=9D=B0?= <502612493@qq.com> Date: Wed, 16 Mar 2022 11:21:39 +0800 Subject: [PATCH 06/96] =?UTF-8?q?=E5=8E=BB=E6=8E=89createinfo=E4=B8=AD?= =?UTF-8?q?=E7=9A=84cseq=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gb28181/transmit/cmd/SIPRequestHeaderProvider.java | 4 ++-- .../iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index 78056791..6c24b208 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -225,7 +225,7 @@ public class SIPRequestHeaderProvider { return request; } - public Request createInfoRequest(Device device, StreamInfo streamInfo, String content, Long cseq) + public Request createInfoRequest(Device device, StreamInfo streamInfo, String content) throws PeerUnavailableException, ParseException, InvalidArgumentException { Request request = null; if (streamInfo == null) return null; @@ -255,7 +255,7 @@ public class SIPRequestHeaderProvider { // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - + cseq = redisCatchStorage.getCSEQ(Request.INVITE); // ceq CSeqHeader cSeqHeader = sipFactory.createHeaderFactory() diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 5df6314e..5e20c47c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -1620,7 +1620,7 @@ public class SIPCommander implements ISIPCommander { content.append("PAUSE RTSP/1.0\r\n"); content.append("CSeq: " + cseq + "\r\n"); content.append("PauseTime: now\r\n"); - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq); + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString()); if (request == null) { return; } @@ -1651,7 +1651,7 @@ public class SIPCommander implements ISIPCommander { content.append("PLAY RTSP/1.0\r\n"); content.append("CSeq: " + cseq + "\r\n"); content.append("Range: npt=now-\r\n"); - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq); + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString()); if (request == null) return; logger.info(request.toString()); ClientTransaction clientTransaction = null; @@ -1680,7 +1680,7 @@ public class SIPCommander implements ISIPCommander { content.append("CSeq: " + cseq + "\r\n"); content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n"); - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq); + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString()); if (request == null) return; logger.info(request.toString()); ClientTransaction clientTransaction = null; @@ -1708,7 +1708,7 @@ public class SIPCommander implements ISIPCommander { content.append("PLAY RTSP/1.0\r\n"); content.append("CSeq: " + cseq + "\r\n"); content.append("Scale: " + String.format("%.1f",speed) + "\r\n"); - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq); + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString()); if (request == null) return; logger.info(request.toString()); ClientTransaction clientTransaction = null; From 57e6cdefdf339cc162594bccef9f513b65562789 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 16 Mar 2022 16:46:18 +0800 Subject: [PATCH 07/96] #401 --- .../iot/vmp/gb28181/event/record/RecordEndEventListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java index 95ffbfa0..b2eb7ead 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java @@ -33,7 +33,7 @@ public class RecordEndEventListener implements ApplicationListener 0) { for (RecordEndEventHandler recordEndEventHandler : handlerMap.values()) { From 4a0fd9ead3aaac3b923a9039c08e4de6b345321b Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 16 Mar 2022 16:55:04 +0800 Subject: [PATCH 08/96] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=88=E5=B9=B6pr?= =?UTF-8?q?=E5=B8=A6=E6=9D=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index 6c24b208..cb208a32 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -256,7 +256,7 @@ public class SIPRequestHeaderProvider { // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); - cseq = redisCatchStorage.getCSEQ(Request.INVITE); + Long cseq = redisCatchStorage.getCSEQ(Request.INVITE); // ceq CSeqHeader cSeqHeader = sipFactory.createHeaderFactory() .createCSeqHeader(cseq, Request.INFO); From c8f9f19c38832f030c5bde5c79ccd8485590d309 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 16 Mar 2022 17:46:24 +0800 Subject: [PATCH 09/96] #393 --- .../iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java | 1 + .../java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java | 2 +- .../iot/vmp/storager/impl/VideoManagerStoragerImpl.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index cb208a32..5d5deae1 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -230,6 +230,7 @@ public class SIPRequestHeaderProvider { Request request = null; if (streamInfo == null) return null; Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream()); + if (dialog == null) return null; SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java index 4ed0a0c2..9ac90bbe 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java @@ -33,7 +33,7 @@ public interface GbStreamMapper { "mediaServerId=#{mediaServerId}," + "status=${status} " + "WHERE app=#{app} AND stream=#{stream}") - int updateByallAndStream(GbStream gbStream); + int updateByAppAndStream(GbStream gbStream); @Update("UPDATE gb_stream " + "SET app=#{app}," + diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index 158a163e..687b10ad 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -772,7 +772,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { try { if (streamProxyMapper.update(streamProxyItem) > 0) { if (!StringUtils.isEmpty(streamProxyItem.getGbId())) { - if (gbStreamMapper.updateByallAndStream(streamProxyItem) > 0) { + if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) { //事务回滚 dataSourceTransactionManager.rollback(transactionStatus); return false; From 59ef6e67d3a1357c19039527dac47747e2ac20fe Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 17 Mar 2022 10:29:49 +0800 Subject: [PATCH 10/96] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=9B=BD=E6=A0=87?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E4=B8=8E=E7=BA=A7=E8=81=94=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E9=9B=86=E7=9A=84=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/bean/Device.java | 2 +- .../cmd/SIPRequestHeaderPlarformProvider.java | 56 +------------------ .../transmit/cmd/impl/SIPCommander.java | 24 +++++--- .../cmd/impl/SIPCommanderFroPlatform.java | 39 ++++++------- .../impl/RegisterRequestProcessor.java | 2 +- .../impl/VideoManagerStoragerImpl.java | 1 + .../gb28181/platform/PlatformController.java | 2 + web_src/src/components/ParentPlatformList.vue | 16 +++--- 8 files changed, 46 insertions(+), 96 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 761437fc..01d340c1 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -105,7 +105,7 @@ public class Device { private boolean firsRegister; /** - * 字符集, 支持 utf-8 与 gb2312 + * 字符集, 支持 UTF-8 与 GB2312 */ private String charset ; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java index 43e26909..7d67e821 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java @@ -223,7 +223,7 @@ public class SIPRequestHeaderPlarformProvider { CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.MESSAGE), Request.MESSAGE); MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); // 设置编码, 防止中文乱码 - messageFactory.setDefaultContentEncodingCharset("gb2312"); + messageFactory.setDefaultContentEncodingCharset(parentPlatform.getCharacterSet()); request = messageFactory.createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); List agentParam = new ArrayList<>(); @@ -235,58 +235,4 @@ public class SIPRequestHeaderPlarformProvider { request.setContent(content, contentTypeHeader); return request; } - -// public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, String fromTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { -// Request request = null; -// // sipuri -// SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); -// // via -// ArrayList viaHeaders = new ArrayList(); -// ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), -// parentPlatform.getTransport(), viaTag); -// viaHeader.setRPort(); -// viaHeaders.add(viaHeader); -// // from -// SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), -// parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); -// Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); -// FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); -// // to -// SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); -// Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); -// ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag()); -// -// // Forwards -// MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); -// // ceq -// CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.NOTIFY), Request.NOTIFY); -// MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); -// // 设置编码, 防止中文乱码 -// messageFactory.setDefaultContentEncodingCharset("gb2312"); -// request = messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, -// toHeader, viaHeaders, maxForwards); -// List agentParam = new ArrayList<>(); -// agentParam.add("wvp-pro"); -// UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); -// request.addHeader(userAgentHeader); -// -// EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); -// if (subscribeInfo.getEventId() != null) { -// event.setEventId(subscribeInfo.getEventId()); -// } -// -// request.addHeader(event); -// -// SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active"); -// request.setHeader(active); -// -// String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort(); -// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() -// .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); -// request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); -// -// ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); -// request.setContent(content, contentTypeHeader); -// return request; -// } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 7a385f50..48bffd77 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -1120,8 +1120,9 @@ public class SIPCommander implements ISIPCommander { @Override public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) { try { + String charset = device.getCharset(); StringBuffer catalogXml = new StringBuffer(200); - catalogXml.append("\r\n"); + catalogXml.append("\r\n"); catalogXml.append("\r\n"); catalogXml.append("DeviceStatus\r\n"); catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -1153,7 +1154,8 @@ public class SIPCommander implements ISIPCommander { public boolean deviceInfoQuery(Device device) { try { StringBuffer catalogXml = new StringBuffer(200); - catalogXml.append("\r\n"); + String charset = device.getCharset(); + catalogXml.append("\r\n"); catalogXml.append("\r\n"); catalogXml.append("DeviceInfo\r\n"); catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -1185,7 +1187,8 @@ public class SIPCommander implements ISIPCommander { public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) { try { StringBuffer catalogXml = new StringBuffer(200); - catalogXml.append("\r\n"); + String charset = device.getCharset(); + catalogXml.append("\r\n"); catalogXml.append("\r\n"); catalogXml.append("Catalog\r\n"); catalogXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -1224,7 +1227,8 @@ public class SIPCommander implements ISIPCommander { } try { StringBuffer recordInfoXml = new StringBuffer(200); - recordInfoXml.append("\r\n"); + String charset = device.getCharset(); + recordInfoXml.append("\r\n"); recordInfoXml.append("\r\n"); recordInfoXml.append("RecordInfo\r\n"); recordInfoXml.append("" + sn + "\r\n"); @@ -1396,7 +1400,8 @@ public class SIPCommander implements ISIPCommander { public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) { try { StringBuffer mobilePostitionXml = new StringBuffer(200); - mobilePostitionXml.append("\r\n"); + String charset = device.getCharset(); + mobilePostitionXml.append("\r\n"); mobilePostitionXml.append("\r\n"); mobilePostitionXml.append("MobilePosition\r\n"); mobilePostitionXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -1431,7 +1436,8 @@ public class SIPCommander implements ISIPCommander { public boolean mobilePositionSubscribe(Device device, int expires, int interval) { try { StringBuffer subscribePostitionXml = new StringBuffer(200); - subscribePostitionXml.append("\r\n"); + String charset = device.getCharset(); + subscribePostitionXml.append("\r\n"); subscribePostitionXml.append("\r\n"); subscribePostitionXml.append("MobilePosition\r\n"); subscribePostitionXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -1473,7 +1479,8 @@ public class SIPCommander implements ISIPCommander { public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) { try { StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); + String charset = device.getCharset(); + cmdXml.append("\r\n"); cmdXml.append("\r\n"); cmdXml.append("Alarm\r\n"); cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -1518,7 +1525,8 @@ public class SIPCommander implements ISIPCommander { public boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { try { StringBuffer cmdXml = new StringBuffer(200); - cmdXml.append("\r\n"); + String charset = device.getCharset(); + cmdXml.append("\r\n"); cmdXml.append("\r\n"); cmdXml.append("Catalog\r\n"); cmdXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java index 6f1d031b..a67bbbd4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java @@ -215,8 +215,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return false; } try { + String characterSet = parentPlatform.getCharacterSet(); StringBuffer catalogXml = new StringBuffer(600); - catalogXml.append("\r\n"); + catalogXml.append("\r\n"); catalogXml.append("\r\n"); catalogXml.append("Catalog\r\n"); catalogXml.append("" +sn + "\r\n"); @@ -280,8 +281,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return false; } try { + String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceInfoXml = new StringBuffer(600); - deviceInfoXml.append("\r\n"); + deviceInfoXml.append("\r\n"); deviceInfoXml.append("\r\n"); deviceInfoXml.append("DeviceInfo\r\n"); deviceInfoXml.append("" +sn + "\r\n"); @@ -319,8 +321,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return false; } try { + String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600); - deviceStatusXml.append("\r\n"); + deviceStatusXml.append("\r\n"); deviceStatusXml.append("\r\n"); deviceStatusXml.append("DeviceStatus\r\n"); deviceStatusXml.append("" +sn + "\r\n"); @@ -350,8 +353,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { } try { + String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600); - deviceStatusXml.append("\r\n"); + deviceStatusXml.append("\r\n"); deviceStatusXml.append("\r\n"); deviceStatusXml.append("MobilePosition\r\n"); deviceStatusXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); @@ -418,8 +422,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) throws NoSuchFieldException, IllegalAccessException, SipException, ParseException { MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); + String characterSet = parentPlatform.getCharacterSet(); // 设置编码, 防止中文乱码 - messageFactory.setDefaultContentEncodingCharset("gb2312"); + messageFactory.setDefaultContentEncodingCharset(characterSet); Dialog dialog = subscribeInfo.getDialog(); if (dialog == null) return; SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY); @@ -462,27 +467,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { } -// private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type, -// SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException, -// PeerUnavailableException, NoSuchFieldException, IllegalAccessException { -// String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo); -// -// CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() -// : udpSipProvider.getNewCallId(); -// callIdHeader.setCallId(subscribeInfo.getCallId()); -// String tm = Long.toString(System.currentTimeMillis()); -// -// Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, -// callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""),"FromRegister" + tm, subscribeInfo); -// return request; -// } - private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) { StringBuffer catalogXml = new StringBuffer(600); if (parentPlatform.getServerGBId().equals(channel.getParentId())) { channel.setParentId(parentPlatform.getDeviceGBId()); } - catalogXml.append("\r\n"); + String characterSet = parentPlatform.getCharacterSet(); + catalogXml.append("\r\n"); catalogXml.append("\r\n"); catalogXml.append("Catalog\r\n"); catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); @@ -554,8 +545,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { if (parentPlatform.getServerGBId().equals(channel.getParentId())) { channel.setParentId(parentPlatform.getDeviceGBId()); } + String characterSet = parentPlatform.getCharacterSet(); StringBuffer catalogXml = new StringBuffer(600); - catalogXml.append("\r\n"); + catalogXml.append("\r\n"); catalogXml.append("\r\n"); catalogXml.append("Catalog\r\n"); catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); @@ -576,8 +568,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return false; } try { + String characterSet = parentPlatform.getCharacterSet(); StringBuffer recordXml = new StringBuffer(600); - recordXml.append("\r\n"); + recordXml.append("\r\n"); recordXml.append("\r\n"); recordXml.append("RecordInfo\r\n"); recordXml.append("" +recordInfo.getSn() + "\r\n"); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index cfc61c40..cb8b723a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -155,7 +155,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen if (device == null) { device = new Device(); device.setStreamMode("UDP"); - device.setCharset("gb2312"); + device.setCharset("GB2312"); device.setDeviceId(deviceId); device.setFirsRegister(true); }else { diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index 687b10ad..0ac8745d 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -141,6 +141,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { String now = this.format.format(System.currentTimeMillis()); device.setUpdateTime(now); Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); + device.setCharset(device.getCharset().toUpperCase()); if (deviceByDeviceId == null) { device.setCreateTime(now); redisCatchStorage.updateDevice(device); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java index 878e77c5..b26ae76f 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java @@ -29,6 +29,7 @@ import org.springframework.web.bind.annotation.*; import com.genersoft.iot.vmp.conf.SipConfig; import java.util.List; +import java.util.Locale; /** * 级联平台管理 @@ -230,6 +231,7 @@ public class PlatformController { wvpResult.setMsg("missing parameters"); return new ResponseEntity<>(wvpResult, HttpStatus.BAD_REQUEST); } + parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase()); ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId()); boolean updateResult = storager.updateParentPlatform(parentPlatform); diff --git a/web_src/src/components/ParentPlatformList.vue b/web_src/src/components/ParentPlatformList.vue index ff3de485..c001071e 100644 --- a/web_src/src/components/ParentPlatformList.vue +++ b/web_src/src/components/ParentPlatformList.vue @@ -43,12 +43,12 @@ @@ -182,10 +182,10 @@ export default { From 7af3cb03ec6b0541ea85db976218c53fae09b943 Mon Sep 17 00:00:00 2001 From: brewswang Date: Thu, 17 Mar 2022 12:39:59 +0800 Subject: [PATCH 11/96] =?UTF-8?q?=E6=89=A7=E6=B3=95=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E4=BB=AA=E5=9C=A8=E6=9B=B4=E6=96=B0=E7=9B=AE=E5=BD=95=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=9A=84=E6=97=B6=E5=80=99=E9=9C=80=E8=A6=81=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=BD=8D=E7=BD=AE=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cmd/CatalogResponseMessageHandler.java | 85 ++++++++++++++++++- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java index 62ec5e9b..47ef6faa 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java @@ -2,9 +2,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.conf.UserSetup; +import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch; @@ -15,7 +14,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.utils.GpsUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import org.dom4j.DocumentException; import org.dom4j.Element; @@ -24,6 +25,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; @@ -67,6 +69,13 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @Autowired private EventPublisher publisher; + //by brewswang + @Autowired + private UserSetup userSetup; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + @Override public void afterPropertiesSet() throws Exception { responseMessageHandler.addHandler(cmdType, this); @@ -108,6 +117,11 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp if (channelDeviceElement == null) { continue; } + //by brewswang + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息,就更新一下位置 + processNotifyMobilePosition(evt, itemDevice); + } + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice); deviceChannel.setDeviceId(device.getDeviceId()); logger.debug("收到来自设备【{}】的通道: {}【{}】", device.getDeviceId(), deviceChannel.getName(), deviceChannel.getChannelId()); @@ -154,4 +168,69 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { } + + /** + * 处理设备位置的更新 + * + * @param evt, itemDevice + */ + private void processNotifyMobilePosition(RequestEvent evt, Element itemDevice) { + try { + // 回复 200 OK + Element rootElement = getRootElement(evt); + MobilePosition mobilePosition = new MobilePosition(); + Element deviceIdElement = rootElement.element("DeviceID"); + String deviceId = deviceIdElement.getTextTrim().toString(); + Device device = redisCatchStorage.getDevice(deviceId); + if (device != null) { + if (!StringUtils.isEmpty(device.getName())) { + mobilePosition.setDeviceName(device.getName()); + } + } + mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID")); + + String time = XmlUtil.getText(itemDevice, "Time"); + if(time==null){ + time = XmlUtil.getText(itemDevice, "EndTime"); + } + mobilePosition.setTime(time); + String longitude = XmlUtil.getText(itemDevice, "Longitude"); + if(longitude!=null) { + mobilePosition.setLongitude(Double.parseDouble(longitude)); + } + String latitude = XmlUtil.getText(itemDevice, "Latitude"); + if(latitude!=null) { + mobilePosition.setLatitude(Double.parseDouble(latitude)); + } + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Speed"))) { + mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(itemDevice, "Speed"))); + } else { + mobilePosition.setSpeed(0.0); + } + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Direction"))) { + mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(itemDevice, "Direction"))); + } else { + mobilePosition.setDirection(0.0); + } + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Altitude"))) { + mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Altitude"))); + } else { + mobilePosition.setAltitude(0.0); + } + mobilePosition.setReportSource("Mobile Position"); + BaiduPoint bp = new BaiduPoint(); + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); + logger.info("百度坐标:" + bp.getBdLng() + ", " + bp.getBdLat()); + mobilePosition.setGeodeticSystem("BD-09"); + mobilePosition.setCnLng(bp.getBdLng()); + mobilePosition.setCnLat(bp.getBdLat()); + if (!userSetup.getSavePositionHistory()) { + storager.clearMobilePositionsByDeviceId(deviceId); + } + storager.insertMobilePosition(mobilePosition); + responseAck(evt, Response.OK); + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } } From bc1b8098a2d042bd94038128f3e83c604b0418c9 Mon Sep 17 00:00:00 2001 From: 648540858 <456panlinlin> Date: Mon, 21 Mar 2022 16:58:42 +0800 Subject: [PATCH 12/96] =?UTF-8?q?=E4=BF=AE=E8=BA=AB=E9=A2=A0=E7=B0=B8?= =?UTF-8?q?=E4=B8=8E=E5=BD=95=E5=83=8F=E5=9B=9E=E6=94=BEredis=E5=89=8D?= =?UTF-8?q?=E7=BC=80=E9=87=8D=E5=A4=8D=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java index ac77f7b9..dbedcb65 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java @@ -35,7 +35,7 @@ public class DeferredResultHolder { public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY"; - public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAY"; + public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK"; public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD"; From a77ba194ad305feb66a3697f8696a918a3860193 Mon Sep 17 00:00:00 2001 From: 648540858 <456panlinlin> Date: Thu, 24 Mar 2022 15:59:38 +0800 Subject: [PATCH 13/96] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E6=8E=A8=E9=80=81CivilCode=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/message/notify/cmd/CatalogNotifyMessageHandler.java | 4 ++-- .../impl/message/query/cmd/CatalogQueryMessageHandler.java | 4 ++-- .../genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java | 2 +- .../iot/vmp/storager/impl/VideoManagerStoragerImpl.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java index 21f36b3a..f21dfc0a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java @@ -86,7 +86,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple deviceChannel.setParental(1); deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); + deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setSecrecy("0"); @@ -125,7 +125,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setParentId(gbStream.getCatalogId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); + deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setParental(0); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java index 925a21e5..d8c72506 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java @@ -89,7 +89,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem deviceChannel.setParental(1); deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); + deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setSecrecy("0"); @@ -128,7 +128,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setParentId(gbStream.getCatalogId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); + deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setParental(0); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java index 32a1305d..3f8c4931 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java @@ -103,7 +103,7 @@ public class GbStreamServiceImpl implements IGbStreamService { deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(sipConfig.getDomain().substring(0, sipConfig.getDomain().length() - 2)); + deviceChannel.setCivilCode(deviceGBId.substring(0, 6)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setParental(0); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index 0ac8745d..54e2b7f1 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -1083,7 +1083,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setRegisterWay(1); // 行政区划应该是Domain的前八位 - deviceChannel.setCivilCode(sipConfig.getDomain().substring(0, sipConfig.getDomain().length() - 2)); + deviceChannel.setCivilCode(parentPlatByServerGBId.getDeviceGBId().substring(0,6)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setSecrecy("0"); From 7d9cc96ef54399795deb5b7fc7682e6323dc1202 Mon Sep 17 00:00:00 2001 From: 648540858 <456panlinlin> Date: Fri, 25 Mar 2022 16:05:14 +0800 Subject: [PATCH 14/96] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=BD=E6=A0=87?= =?UTF-8?q?=E5=BD=95=E5=83=8F=E4=B8=8B=E8=BD=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=9D=A1=E4=BB=A5=E5=8F=8A=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD=EF=BC=8C?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E7=BB=93=E5=90=88=E6=96=B0=E7=89=88assist?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E4=BD=BF=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/common/StreamInfo.java | 28 +++ .../iot/vmp/gb28181/bean/SsrcTransaction.java | 11 + .../subscribe/catalog/CatalogEventLister.java | 2 - .../session/VideoStreamSessionManager.java | 9 +- .../gb28181/transmit/cmd/ISIPCommander.java | 4 +- .../transmit/cmd/impl/SIPCommander.java | 24 ++- .../cmd/CatalogNotifyMessageHandler.java | 1 + .../cmd/MediaStatusNotifyMessageHandler.java | 7 +- .../query/cmd/CatalogQueryMessageHandler.java | 1 + .../iot/vmp/media/zlm/AssistRESTfulUtils.java | 139 ++++++++++++ .../vmp/media/zlm/ZLMHttpHookListener.java | 11 +- .../vmp/media/zlm/ZLMHttpHookSubscribe.java | 1 + .../iot/vmp/service/IPlayService.java | 6 + .../iot/vmp/service/impl/PlayServiceImpl.java | 142 ++++++++++++- .../service/impl/StreamProxyServiceImpl.java | 2 +- .../iot/vmp/storager/IRedisCatchStorage.java | 2 + .../storager/impl/RedisCatchStorageImpl.java | 38 +++- .../gb28181/playback/DownloadController.java | 150 ------------- .../gb28181/record/GBRecordController.java | 121 +++++++++++ web_src/build/webpack.dev.conf.js | 1 + web_src/config/index.js | 4 +- web_src/package-lock.json | 6 +- .../src/components/dialog/devicePlayer.vue | 53 +++-- .../src/components/dialog/recordDownload.vue | 195 +++++++++++++++++ web_src/src/components/test.vue | 198 ------------------ web_src/src/components/test2.vue | 190 ----------------- web_src/src/router/index.js | 6 - 27 files changed, 761 insertions(+), 591 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java create mode 100644 web_src/src/components/dialog/recordDownload.vue delete mode 100644 web_src/src/components/test.vue delete mode 100644 web_src/src/components/test2.vue diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java index 06263840..4e4ba15e 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -31,6 +31,9 @@ public class StreamInfo { private String rtc; private String mediaServerId; private Object tracks; + private String startTime; + private String endTime; + private double progress; public static class TransactionInfo{ public String callId; @@ -264,4 +267,29 @@ public class StreamInfo { public void setHttps_ts(String https_ts) { this.https_ts = https_ts; } + + + public String getStartTime() { + return startTime; + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public double getProgress() { + return progress; + } + + public void setProgress(double progress) { + this.progress = progress; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java index c2dedec1..87d26359 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java @@ -1,5 +1,7 @@ package com.genersoft.iot.vmp.gb28181.bean; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; + public class SsrcTransaction { private String deviceId; @@ -10,6 +12,7 @@ public class SsrcTransaction { private byte[] dialog; private String mediaServerId; private String ssrc; + private VideoStreamSessionManager.SessionType type; public String getDeviceId() { return deviceId; @@ -74,4 +77,12 @@ public class SsrcTransaction { public void setSsrc(String ssrc) { this.ssrc = ssrc; } + + public VideoStreamSessionManager.SessionType getType() { + return type; + } + + public void setType(VideoStreamSessionManager.SessionType type) { + this.type = type; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java index d511f421..50957f6d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java @@ -156,8 +156,6 @@ public class CatalogEventLister implements ApplicationListener { List parentPlatforms = parentPlatformMap.get(gbId); if (parentPlatforms != null && parentPlatforms.size() > 0) { for (ParentPlatform platform : parentPlatforms) { -// String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId(); -// SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key); SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(event.getPlatformId()); if (subscribeInfo == null) continue; logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java index ba8f24c1..6eed17eb 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -30,6 +30,12 @@ public class VideoStreamSessionManager { @Autowired private UserSetup userSetup; + public enum SessionType { + play, + playback, + download + } + /** * 添加一个点播/回放的事务信息 * 后续可以通过流Id/callID @@ -40,7 +46,7 @@ public class VideoStreamSessionManager { * @param mediaServerId 所使用的流媒体ID * @param transaction 事务 */ - public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){ + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction, SessionType type){ SsrcTransaction ssrcTransaction = new SsrcTransaction(); ssrcTransaction.setDeviceId(deviceId); ssrcTransaction.setChannelId(channelId); @@ -50,6 +56,7 @@ public class VideoStreamSessionManager { ssrcTransaction.setCallId(callId); ssrcTransaction.setSsrc(ssrc); ssrcTransaction.setMediaServerId(mediaServerId); + ssrcTransaction.setType(type); redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index 409eedbf..9cd89e0e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -115,7 +115,9 @@ public interface ISIPCommander { * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss * @param downloadSpeed 下载倍速参数 */ - void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, InviteStreamCallback event, SipSubscribe.Event errorEvent); + void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, + SipSubscribe.Event errorEvent); /** * 视频流停止 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 48bffd77..0f2242cc 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -428,7 +428,7 @@ public class SIPCommander implements ISIPCommander { errorEvent.response(e); }), e ->{ // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 - streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction()); + streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play); streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog); }); @@ -537,7 +537,7 @@ public class SIPCommander implements ISIPCommander { transmitRequest(device, request, errorEvent, okEvent -> { ResponseEvent responseEvent = (ResponseEvent) okEvent.event; - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction()); + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback); streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog); }); if (inviteStreamCallback != null) { @@ -558,8 +558,9 @@ public class SIPCommander implements ISIPCommander { * @param downloadSpeed 下载倍速参数 */ @Override - public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, InviteStreamCallback event - , SipSubscribe.Event errorEvent) { + public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, + SipSubscribe.Event errorEvent) { try { logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); @@ -572,8 +573,6 @@ public class SIPCommander implements ISIPCommander { content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" " +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); - - String streamMode = device.getStreamMode().toUpperCase(); if (userSetup.isSeniorSdp()) { @@ -639,15 +638,20 @@ public class SIPCommander implements ISIPCommander { logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, (MediaServerItem mediaServerItemInUse, JSONObject json)->{ - event.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); + hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); }); Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); + if (inviteStreamCallback != null) { + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); + } + transmitRequest(device, request, errorEvent, okEvent->{ + ResponseEvent responseEvent = (ResponseEvent) okEvent.event; + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.download); + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog); + }); - ClientTransaction transaction = transmitRequest(device, request, errorEvent); - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction); - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction); } catch ( SipException | ParseException | InvalidArgumentException e) { e.printStackTrace(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java index f21dfc0a..9550266b 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java @@ -104,6 +104,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); deviceChannel.setParental(0); deviceChannel.setParentId(channelReduce.getCatalogId()); + deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6)); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 Thread.sleep(100); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java index 8235ade1..e36a705a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java @@ -62,7 +62,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i if (NotifyType.equals("121")){ logger.info("媒体播放完毕,通知关流"); String channelId =getText(rootElement, "DeviceID"); - redisCatchStorage.stopPlayback(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); +// redisCatchStorage.stopPlayback(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); +// redisCatchStorage.stopDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); + StreamInfo streamInfo = redisCatchStorage.queryDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); + // 设置进度100% + streamInfo.setProgress(1); + redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId()); cmder.streamByeCmd(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); // TODO 如果级联播放,需要给上级发送此通知 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java index d8c72506..959432ce 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java @@ -107,6 +107,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); deviceChannel.setParental(0); deviceChannel.setParentId(channelReduce.getCatalogId()); + deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6)); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 Thread.sleep(100); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java new file mode 100644 index 00000000..249ec03c --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java @@ -0,0 +1,139 @@ +package com.genersoft.iot.vmp.media.zlm; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import okhttp3.*; +import okhttp3.logging.HttpLoggingInterceptor; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.ConnectException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@Component +public class AssistRESTfulUtils { + + private final static Logger logger = LoggerFactory.getLogger(AssistRESTfulUtils.class); + + public interface RequestCallback{ + void run(JSONObject response); + } + + private OkHttpClient getClient(){ + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); + if (logger.isDebugEnabled()) { + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> { + logger.debug("http请求参数:" + message); + }); + logging.setLevel(HttpLoggingInterceptor.Level.BASIC); + // OkHttp進行添加攔截器loggingInterceptor + httpClientBuilder.addInterceptor(logging); + } + return httpClientBuilder.build(); + } + + + public JSONObject sendGet(MediaServerItem mediaServerItem, String api, Map param, RequestCallback callback) { + OkHttpClient client = getClient(); + + if (mediaServerItem == null) { + return null; + } + if (StringUtils.isEmpty(mediaServerItem.getRecordAssistPort())) { + logger.warn("未启用Assist服务"); + return null; + } + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(String.format("http://%s:%s/%s", mediaServerItem.getIp(), mediaServerItem.getRecordAssistPort(), api)); + JSONObject responseJSON = null; + + if (param != null && param.keySet().size() > 0) { + stringBuffer.append("?"); + int index = 1; + for (String key : param.keySet()){ + if (param.get(key) != null) { + stringBuffer.append(key + "=" + param.get(key)); + if (index < param.size()) { + stringBuffer.append("&"); + } + } + index++; + } + } + + String url = stringBuffer.toString(); + Request request = new Request.Builder() + .get() + .url(url) + .build(); + if (callback == null) { + try { + Response response = client.newCall(request).execute(); + if (response.isSuccessful()) { + ResponseBody responseBody = response.body(); + if (responseBody != null) { + String responseStr = responseBody.string(); + responseJSON = JSON.parseObject(responseStr); + } + }else { + response.close(); + Objects.requireNonNull(response.body()).close(); + } + } catch (ConnectException e) { + logger.error(String.format("连接Assist失败: %s, %s", e.getCause().getMessage(), e.getMessage())); + logger.info("请检查media配置并确认Assist已启动..."); + }catch (IOException e) { + logger.error(String.format("[ %s ]请求失败: %s", url, e.getMessage())); + } + }else { + client.newCall(request).enqueue(new Callback(){ + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response){ + if (response.isSuccessful()) { + try { + String responseStr = Objects.requireNonNull(response.body()).string(); + callback.run(JSON.parseObject(responseStr)); + } catch (IOException e) { + logger.error(String.format("[ %s ]请求失败: %s", url, e.getMessage())); + } + + }else { + response.close(); + Objects.requireNonNull(response.body()).close(); + } + } + + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + logger.error(String.format("连接Assist失败: %s, %s", e.getCause().getMessage(), e.getMessage())); + logger.info("请检查media配置并确认Assist已启动..."); + } + }); + } + + + + return responseJSON; + } + + + public JSONObject fileDuration(MediaServerItem mediaServerItem, String app, String stream, RequestCallback callback){ + Map param = new HashMap<>(); + param.put("app",app); + param.put("stream",stream); + param.put("recordIng",true); + return sendGet(mediaServerItem, "api/record/file/duration",param, callback); + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index bd39a0ce..c3c30a6a 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -215,7 +215,16 @@ public class ZLMHttpHookListener { if (deviceChannel != null) { ret.put("enable_audio", deviceChannel.isHasAudio()); } + // 如果是录像下载就设置视频间隔十秒 + if (ssrcTransactionForAll.get(0).getType() == VideoStreamSessionManager.SessionType.download) { + ret.put("mp4_max_second", 10); + ret.put("enable_mp4", true); + ret.put("enable_audio", true); + } + } + + return new ResponseEntity(ret.toString(), HttpStatus.OK); } @@ -324,7 +333,6 @@ public class ZLMHttpHookListener { if (mediaInfo != null) { subscribe.response(mediaInfo, json); } - } // 流消失移除redis play String app = item.getApp(); @@ -441,6 +449,7 @@ public class ZLMHttpHookListener { if ("rtp".equals(app)){ ret.put("close", true); StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(streamId); + SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, null, streamId); if (streamInfoForPlayCatch != null) { // 如果在给上级推流,也不停止。 if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java index 84b36e3e..35052253 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java @@ -31,6 +31,7 @@ public class ZLMHttpHookSubscribe { on_server_keepalive } + @FunctionalInterface public interface Event{ void response(MediaServerItem mediaServerItem, JSONObject response); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java index 4cff4a68..9e764931 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.service; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback; import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo; @@ -34,4 +35,9 @@ public interface IPlayService { DeferredResult> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void zlmServerOffline(String mediaServerId); + + DeferredResult> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); + DeferredResult> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); + + StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index 9ee58673..7334184f 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -12,6 +12,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; @@ -28,7 +30,6 @@ import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IPlayService; import gov.nist.javax.sip.stack.SIPDialog; -import jdk.nashorn.internal.ir.RuntimeNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -38,10 +39,8 @@ import org.springframework.stereotype.Service; import org.springframework.util.ResourceUtils; import org.springframework.web.context.request.async.DeferredResult; -import javax.sip.header.CallIdHeader; -import javax.sip.header.Header; -import javax.sip.message.Request; import java.io.FileNotFoundException; +import java.math.BigDecimal; import java.util.*; @SuppressWarnings(value = {"rawtypes", "unchecked"}) @@ -71,6 +70,9 @@ public class PlayServiceImpl implements IPlayService { @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + @Autowired + private AssistRESTfulUtils assistRESTfulUtils; + @Autowired private IMediaService mediaService; @@ -344,7 +346,7 @@ public class PlayServiceImpl implements IPlayService { return result; } - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result); RequestMessage msg = new RequestMessage(); msg.setId(uuid); msg.setKey(key); @@ -405,6 +407,136 @@ public class PlayServiceImpl implements IPlayService { return result; } + @Override + public DeferredResult> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { + Device device = storager.queryVideoDevice(deviceId); + if (device == null) return null; + MediaServerItem newMediaServerItem = getNewMediaServerItem(device); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); + + return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed,infoCallBack, hookCallBack); + } + + @Override + public DeferredResult> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { + if (mediaServerItem == null || ssrcInfo == null) return null; + String uuid = UUID.randomUUID().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; + DeferredResult> result = new DeferredResult<>(30000L); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); + return result; + } + + resultHolder.put(key, uuid, result); + RequestMessage msg = new RequestMessage(); + msg.setId(uuid); + msg.setKey(key); + WVPResult wvpResult = new WVPResult<>(); + msg.setData(wvpResult); + PlayBackResult downloadResult = new PlayBackResult<>(); + downloadResult.setData(msg); + + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId)); + wvpResult.setCode(-1); + wvpResult.setMsg("录像下载请求超时"); + downloadResult.setCode(-1); + hookCallBack.call(downloadResult); + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream()); + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 + if (dialog != null) { + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 + cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); + }else { + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); + mediaServerService.closeRTPServer(deviceId, channelId, ssrcInfo.getStream()); + streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); + } + cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); + // 回复之前所有的点播请求 + hookCallBack.call(downloadResult); + } + }, userSetup.getPlayTimeout()); + cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, + inviteStreamInfo -> { + logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); + timer.cancel(); + StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); + streamInfo.setStartTime(startTime); + streamInfo.setEndTime(endTime); + if (streamInfo == null) { + logger.warn("录像下载API调用失败!"); + wvpResult.setCode(-1); + wvpResult.setMsg("录像下载API调用失败"); + downloadResult.setCode(-1); + hookCallBack.call(downloadResult); + return ; + } + redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); + wvpResult.setCode(0); + wvpResult.setMsg("success"); + wvpResult.setData(streamInfo); + downloadResult.setCode(0); + downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); + downloadResult.setResponse(inviteStreamInfo.getResponse()); + hookCallBack.call(downloadResult); + }, event -> { + timer.cancel(); + downloadResult.setCode(-1); + wvpResult.setCode(-1); + wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); + downloadResult.setEvent(event); + hookCallBack.call(downloadResult); + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); + }); + return result; + } + + @Override + public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) { + StreamInfo streamInfo = redisCatchStorage.queryDownload(deviceId, channelId, stream, null); + if (streamInfo != null) { + if (streamInfo.getProgress() == 1) { + return streamInfo; + } + + // 获取当前已下载时长 + String mediaServerId = streamInfo.getMediaServerId(); + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + if (mediaServerItem == null) { + logger.warn("查询录像信息时发现节点已离线"); + return null; + } + if (mediaServerItem.getRecordAssistPort() != 0) { + JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + long duration = jsonObject.getLong("data"); + + if (duration == 0) { + streamInfo.setProgress(0); + }else { + String startTime = streamInfo.getStartTime(); + String endTime = streamInfo.getEndTime(); + long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); + long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); + + BigDecimal currentCount = new BigDecimal(duration/1000); + BigDecimal totalCount = new BigDecimal(end-start); + BigDecimal divide = currentCount.divide(totalCount,2, BigDecimal.ROUND_HALF_UP); + double process = divide.doubleValue(); + streamInfo.setProgress(process); + } + } + } + } + return streamInfo; + } + @Override public void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String uuid) { RequestMessage msg = new RequestMessage(); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java index 564deb55..3e82e8d8 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -91,7 +91,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { MediaServerItem mediaInfo; WVPResult wvpResult = new WVPResult<>(); wvpResult.setCode(0); - if ("auto".equals(param.getMediaServerId())){ + if (param.getMediaServerId() == null || "auto".equals(param.getMediaServerId())){ mediaInfo = mediaServerService.getMediaServerForMinimumLoad(); }else { mediaInfo = mediaServerService.getOne(param.getMediaServerId()); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index 50948533..e669ab45 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -169,6 +169,8 @@ public interface IRedisCatchStorage { StreamInfo queryDownload(String deviceId, String channelId, String stream, String callId); + boolean stopDownload(String deviceId, String channelId, String stream, String callId); + /** * 查找第三方系统留下的国标预设值 * @param queryKey diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index 6ad654e6..4840446f 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -166,8 +166,42 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public boolean startDownload(StreamInfo stream, String callId) { - return redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, - userSetup.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream); + boolean result; + if (stream.getProgress() == 1) { + result = redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, + userSetup.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream); + }else { + result = redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, + userSetup.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream, 60*60); + } + return result; + } + @Override + public boolean stopDownload(String deviceId, String channelId, String stream, String callId) { + DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); + if (deviceChannel != null) { + deviceChannel.setStreamId(null); + deviceChannel.setDeviceId(deviceId); + deviceChannelMapper.update(deviceChannel); + } + if (deviceId == null) deviceId = "*"; + if (channelId == null) channelId = "*"; + if (stream == null) stream = "*"; + if (callId == null) callId = "*"; + String key = String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, + userSetup.getServerId(), + deviceId, + channelId, + stream, + callId + ); + List scan = redis.scan(key); + if (scan.size() > 0) { + for (Object keyObj : scan) { + redis.del((String) keyObj); + } + } + return true; } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java deleted file mode 100644 index 4ffbd4b0..00000000 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.genersoft.iot.vmp.vmanager.gb28181.playback; - -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo; -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.bean.SSRCInfo; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.service.IPlayService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import org.springframework.web.context.request.async.DeferredResult; - -import javax.sip.message.Response; -import java.util.UUID; - -@Api(tags = "历史媒体下载") -@CrossOrigin -@RestController -@RequestMapping("/api/download") -public class DownloadController { - - private final static Logger logger = LoggerFactory.getLogger(DownloadController.class); - - @Autowired - private SIPCommander cmder; - - @Autowired - private IVideoManagerStorager storager; - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - // @Autowired - // private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired - private IPlayService playService; - - @Autowired - private DeferredResultHolder resultHolder; - - @Autowired - private IMediaServerService mediaServerService; - - @ApiOperation("开始历史媒体下载") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), - @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), - @ApiImplicitParam(name = "startTime", value = "开始时间", dataTypeClass = String.class), - @ApiImplicitParam(name = "endTime", value = "结束时间", dataTypeClass = String.class), - @ApiImplicitParam(name = "downloadSpeed", value = "下载倍速", dataTypeClass = String.class), - }) - @GetMapping("/start/{deviceId}/{channelId}") - public DeferredResult> play(@PathVariable String deviceId, @PathVariable String channelId, - String startTime, String endTime, String downloadSpeed) { - - if (logger.isDebugEnabled()) { - logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed)); - } - String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; - String uuid = UUID.randomUUID().toString(); - DeferredResult> result = new DeferredResult>(30000L); - // 超时处理 - result.onTimeout(()->{ - logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId)); - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("Timeout"); - resultHolder.invokeAllResult(msg); - }); - if(resultHolder.exist(key, null)) { - return result; - } - resultHolder.put(key, uuid, result); - Device device = storager.queryVideoDevice(deviceId); - - MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); - if (newMediaServerItem == null) { - logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId)); - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("Timeout"); - resultHolder.invokeAllResult(msg); - return result; - } - - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); - - cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (InviteStreamInfo inviteStreamInfo) -> { - logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); - playService.onPublishHandlerForDownload(inviteStreamInfo, deviceId, channelId, uuid); - }, event -> { - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); - resultHolder.invokeAllResult(msg); - }); - - return result; - } - - @ApiOperation("停止历史媒体下载") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), - @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), - @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), - }) - @GetMapping("/stop/{deviceId}/{channelId}/{stream}") - public ResponseEntity playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { - - cmder.streamByeCmd(deviceId, channelId, stream, null); - - if (logger.isDebugEnabled()) { - logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); - } - - if (deviceId != null && channelId != null) { - JSONObject json = new JSONObject(); - json.put("deviceId", deviceId); - json.put("channelId", channelId); - return new ResponseEntity(json.toString(), HttpStatus.OK); - } else { - logger.warn("设备历史媒体下载停止API调用失败!"); - return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); - } - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java index e5659814..d33dd2ac 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java @@ -1,6 +1,13 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record; +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.service.IPlayService; +import com.genersoft.iot.vmp.service.bean.SSRCInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -8,6 +15,7 @@ import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; @@ -41,6 +49,12 @@ public class GBRecordController { @Autowired private DeferredResultHolder resultHolder; + @Autowired + private IPlayService playService; + + @Autowired + private IMediaServerService mediaServerService; + @ApiOperation("录像查询") @ApiImplicitParams({ @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), @@ -77,4 +91,111 @@ public class GBRecordController { }); return result; } + + @ApiOperation("开始历史媒体下载") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "startTime", value = "开始时间", dataTypeClass = String.class), + @ApiImplicitParam(name = "endTime", value = "结束时间", dataTypeClass = String.class), + @ApiImplicitParam(name = "downloadSpeed", value = "下载倍速", dataTypeClass = String.class), + }) + @GetMapping("/download/start/{deviceId}/{channelId}") + public DeferredResult> download(@PathVariable String deviceId, @PathVariable String channelId, + String startTime, String endTime, String downloadSpeed) { + + if (logger.isDebugEnabled()) { + logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed)); + } +// String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; +// String uuid = UUID.randomUUID().toString(); +// DeferredResult> result = new DeferredResult>(30000L); +// // 超时处理 +// result.onTimeout(()->{ +// logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId)); +// RequestMessage msg = new RequestMessage(); +// msg.setId(uuid); +// msg.setKey(key); +// msg.setData("Timeout"); +// resultHolder.invokeAllResult(msg); +// }); +// if(resultHolder.exist(key, null)) { +// return result; +// } +// resultHolder.put(key, uuid, result); +// Device device = storager.queryVideoDevice(deviceId); +// +// MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); +// if (newMediaServerItem == null) { +// logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId)); +// RequestMessage msg = new RequestMessage(); +// msg.setId(uuid); +// msg.setKey(key); +// msg.setData("Timeout"); +// resultHolder.invokeAllResult(msg); +// return result; +// } +// +// SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); +// +// cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (InviteStreamInfo inviteStreamInfo) -> { +// logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); +// playService.onPublishHandlerForDownload(inviteStreamInfo, deviceId, channelId, uuid); +// }, event -> { +// RequestMessage msg = new RequestMessage(); +// msg.setId(uuid); +// msg.setKey(key); +// msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); +// resultHolder.invokeAllResult(msg); +// }); + + if (logger.isDebugEnabled()) { + logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); + } + + DeferredResult> result = playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, hookCallBack->{ + resultHolder.invokeResult(hookCallBack.getData()); + }); + + return result; + } + + @ApiOperation("停止历史媒体下载") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), + }) + @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}") + public ResponseEntity playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { + + cmder.streamByeCmd(deviceId, channelId, stream, null); + + if (logger.isDebugEnabled()) { + logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); + } + + if (deviceId != null && channelId != null) { + JSONObject json = new JSONObject(); + json.put("deviceId", deviceId); + json.put("channelId", channelId); + return new ResponseEntity(json.toString(), HttpStatus.OK); + } else { + logger.warn("设备历史媒体下载停止API调用失败!"); + return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @ApiOperation("获取历史媒体下载进度") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), + }) + @GetMapping("/download/progress/{deviceId}/{channelId}/{stream}") + public ResponseEntity getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { + + StreamInfo streamInfo = playService.getDownLoadInfo(deviceId, channelId, stream); + return new ResponseEntity<>(streamInfo, HttpStatus.OK); + } } diff --git a/web_src/build/webpack.dev.conf.js b/web_src/build/webpack.dev.conf.js index 070ae221..55efd304 100755 --- a/web_src/build/webpack.dev.conf.js +++ b/web_src/build/webpack.dev.conf.js @@ -32,6 +32,7 @@ const devWebpackConfig = merge(baseWebpackConfig, { contentBase: false, // since we use CopyWebpackPlugin. compress: true, host: HOST || config.dev.host, + // host:'127.0.0.1', port: PORT || config.dev.port, open: config.dev.autoOpenBrowser, overlay: config.dev.errorOverlay diff --git a/web_src/config/index.js b/web_src/config/index.js index cec91b87..b1e1cbe1 100644 --- a/web_src/config/index.js +++ b/web_src/config/index.js @@ -29,11 +29,13 @@ module.exports = { }, // Various Dev Server settings - host: 'localhost', // can be overwritten by process.env.HOST + host:"127.0.0.1", + useLocalIp: false, // can be overwritten by process.env.HOST port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: false, errorOverlay: true, notifyOnErrors: true, + hot: true,//自动保存 poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- diff --git a/web_src/package-lock.json b/web_src/package-lock.json index 356bbccb..b1da39e2 100644 --- a/web_src/package-lock.json +++ b/web_src/package-lock.json @@ -57,7 +57,7 @@ "vue-template-compiler": "^2.5.2", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", - "webpack-dev-server": "^2.9.1", + "webpack-dev-server": "^2.11.5", "webpack-merge": "^4.1.0" }, "engines": { @@ -13382,7 +13382,7 @@ }, "node_modules/webpack-dev-server": { "version": "2.11.5", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz", + "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz", "integrity": "sha512-7TdOKKt7G3sWEhPKV0zP+nD0c4V9YKUJ3wDdBwQsZNo58oZIRoVIu66pg7PYkBW8A74msP9C2kLwmxGHndz/pw==", "dev": true, "dependencies": { @@ -25569,7 +25569,7 @@ }, "webpack-dev-server": { "version": "2.11.5", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz", + "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz", "integrity": "sha512-7TdOKKt7G3sWEhPKV0zP+nD0c4V9YKUJ3wDdBwQsZNo58oZIRoVIu66pg7PYkBW8A74msP9C2kLwmxGHndz/pw==", "dev": true, "requires": { diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 5a080060..effd389d 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -175,6 +175,7 @@ + @@ -183,15 +184,15 @@ // import LivePlayer from '@liveqing/liveplayer' // import player from '../dialog/easyPlayer.vue' import player from '../dialog/jessibuca.vue' +import recordDownload from '../dialog/recordDownload.vue' export default { name: 'devicePlayer', props: {}, components: { - player, + player,recordDownload, }, computed: { getPlayerShared: function () { - return { sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl), sharedIframe: '', @@ -250,7 +251,7 @@ export default { that.tracks = []; that.tracksLoading = true; that.tracksNotLoaded = false; - if (tab.name == "codec") { + if (tab.name === "codec") { this.$axios({ method: 'get', url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId @@ -340,7 +341,7 @@ export default { this.$refs.videoPlayer.pause() that.$axios({ method: 'post', - url: '/api/play/convert/' + that.streamId + url: '/api/gb_record/convert/' + that.streamId }).then(function (res) { if (res.data.code == 0) { that.convertKey = res.data.key; @@ -474,8 +475,8 @@ export default { console.log(this.seekTime) if (that.streamId != "") { that.stopPlayRecord(function () { - that.streamId = "", - that.playRecord(row); + that.streamId = ""; + that.playRecord(row); }) } else { this.$axios({ @@ -506,22 +507,36 @@ export default { downloadRecord: function (row) { let that = this; if (that.streamId != "") { - that.stopDownloadRecord(function () { - that.streamId = "", - that.downloadRecord(row); + that.stopDownloadRecord(function (res) { + if (res.code == 0) { + that.streamId = ""; + that.downloadRecord(row); + }else { + this.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } + }) } else { this.$axios({ method: 'get', - url: '/api/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + + url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + row.endTime + '&downloadSpeed=4' }).then(function (res) { - var streamInfo = res.data; - that.app = streamInfo.app; - that.streamId = streamInfo.stream; - that.mediaServerId = streamInfo.mediaServerId; - that.videoUrl = that.getUrlByStreamInfo(streamInfo); - that.recordPlay = true; + if (res.data.code == 0) { + let streamInfo = res.data.data; + that.recordPlay = false; + that.$refs.recordDownload.openDialog(that.deviceId, that.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId); + }else { + that.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } }); } }, @@ -530,9 +545,9 @@ export default { this.videoUrl = ''; this.$axios({ method: 'get', - url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId - }).then(function (res) { - if (callback) callback() + url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId + }).then((res)=> { + if (callback) callback(res) }); }, ptzCamera: function (command) { diff --git a/web_src/src/components/dialog/recordDownload.vue b/web_src/src/components/dialog/recordDownload.vue new file mode 100644 index 00000000..6b7ca1f6 --- /dev/null +++ b/web_src/src/components/dialog/recordDownload.vue @@ -0,0 +1,195 @@ + + + + + + diff --git a/web_src/src/components/test.vue b/web_src/src/components/test.vue deleted file mode 100644 index d7801259..00000000 --- a/web_src/src/components/test.vue +++ /dev/null @@ -1,198 +0,0 @@ - - - - - diff --git a/web_src/src/components/test2.vue b/web_src/src/components/test2.vue deleted file mode 100644 index 75f182eb..00000000 --- a/web_src/src/components/test2.vue +++ /dev/null @@ -1,190 +0,0 @@ - - - - - diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js index ad573cfa..05bb1ae6 100644 --- a/web_src/src/router/index.js +++ b/web_src/src/router/index.js @@ -11,7 +11,6 @@ import login from '../components/Login.vue' import parentPlatformList from '../components/ParentPlatformList.vue' import cloudRecord from '../components/CloudRecord.vue' import mediaServerManger from '../components/MediaServerManger.vue' -import test from '../components/test.vue' import web from '../components/setting/Web.vue' import sip from '../components/setting/Sip.vue' import media from '../components/setting/Media.vue' @@ -96,11 +95,6 @@ export default new VueRouter({ name: 'media', component: media, }, - { - path: '/test', - name: 'test', - component: test, - }, { path: '/play/wasm/:url', name: 'wasmPlayer', From daab2586ca1ed278ca19d3f0283fbca192cef1be Mon Sep 17 00:00:00 2001 From: 648540858 <456panlinlin> Date: Fri, 25 Mar 2022 17:22:17 +0800 Subject: [PATCH 15/96] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=BD=E6=A0=87?= =?UTF-8?q?=E7=BA=A7=E8=81=94=E4=B8=8A=E7=BA=A7=E8=A6=81=E6=B1=82tcp?= =?UTF-8?q?=E6=8E=A8=E6=B5=81=E6=97=B6=E7=9A=84=E5=9B=9E=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/request/impl/InviteRequestProcessor.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index 46551a66..b1c7a31c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -225,6 +225,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements mediaTransmissionTCP = true; if ("active".equals(setup)) { tcpActive = true; + // 不支持tcp主动 + responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 目录不支持点播 + return; } else if ("passive".equals(setup)) { tcpActive = false; } @@ -428,6 +431,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); content.append("a=sendonly\r\n"); content.append("a=rtpmap:96 PS/90000\r\n"); + if (sendRtpItem.isTcp()) { + content.append("a=connection:new\r\n"); + if (!sendRtpItem.isTcpActive()) { + content.append("a=setup:active\r\n"); + }else { + content.append("a=setup:passive\r\n"); + } + } content.append("y="+ ssrc + "\r\n"); content.append("f=\r\n"); From 9aee7d42e3f7f1c28bddf765b1078048d982ae30 Mon Sep 17 00:00:00 2001 From: 648540858 <456panlinlin> Date: Fri, 25 Mar 2022 18:05:05 +0800 Subject: [PATCH 16/96] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=B5=B7=E5=BA=B7=20?= =?UTF-8?q?=E5=AA=92=E4=BD=93=E9=80=9A=E7=9F=A5=20=E6=B6=88=E6=81=AFfrom?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=B8=8D=E6=98=AF=E8=AE=BE=E5=A4=87ID?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/impl/message/MessageRequestProcessor.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java index e126fba4..a0c1a38f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java @@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; @@ -49,6 +51,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private VideoStreamSessionManager sessionManager; + @Override public void afterPropertiesSet() throws Exception { // 添加消息处理的订阅 @@ -64,6 +69,11 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement logger.debug("接收到消息:" + evt.getRequest()); String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); + // 先从会话内查找 + SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, null, callIdHeader.getCallId()); + if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 + deviceId = ssrcTransaction.getDeviceId(); + } // 查询设备是否存在 CSeqHeader cseqHeader = (CSeqHeader) evt.getRequest().getHeader(CSeqHeader.NAME); String method = cseqHeader.getMethod(); From a1b6e56427fa7279e65afc880b7124c6cf289177 Mon Sep 17 00:00:00 2001 From: mk1990 <153958232@qq.com> Date: Mon, 28 Mar 2022 10:11:13 +0800 Subject: [PATCH 17/96] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9control.vue=20?= =?UTF-8?q?=E6=8A=A5Invalid=20prop:=20type=20check=20failed=20for=20prop?= =?UTF-8?q?=20"column".=20Expected=20Number=20with=20value=201,=20got=20St?= =?UTF-8?q?ring=20with=20value=20"1".=202.=20=E4=BF=AE=E6=94=B9control.vue?= =?UTF-8?q?=20Error:=20[vue-clipboards]=20Invalid=20value.=20Please=20use?= =?UTF-8?q?=20a=20valid=20value.=203.=20=E4=BF=AE=E6=94=B9DeviceList.vue?= =?UTF-8?q?=20=E5=88=B7=E6=96=B0=E6=97=B6=E6=8A=A5=20[Vue=20warn]:=20Avoid?= =?UTF-8?q?=20mutating=20a=20prop=20directly=20since=20the=20value=20will?= =?UTF-8?q?=20be=20overwritten=20whenever=20the=20parent=20component=20re-?= =?UTF-8?q?renders.=20Instead,=20use=20a=20data=20or=20computed=20property?= =?UTF-8?q?=20based=20on=20the=20prop's=20value.=20Prop=20being=20mutated:?= =?UTF-8?q?=20"loading"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/src/components/DeviceList.vue | 8 ++++---- web_src/src/components/control.vue | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/web_src/src/components/DeviceList.vue b/web_src/src/components/DeviceList.vue index 7922a934..74e3fbc2 100644 --- a/web_src/src/components/DeviceList.vue +++ b/web_src/src/components/DeviceList.vue @@ -57,7 +57,7 @@