From 12571e0db1b5014e707010e4ab2514ad22ee6fc1 Mon Sep 17 00:00:00 2001 From: wenyanjun <997745354@qq.com> Date: Wed, 14 Sep 2022 14:32:22 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=BD=95=E5=83=8F=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/src/components/dialog/recordDownload.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web_src/src/components/dialog/recordDownload.vue b/web_src/src/components/dialog/recordDownload.vue index b718a8bd4..df3880c44 100644 --- a/web_src/src/components/dialog/recordDownload.vue +++ b/web_src/src/components/dialog/recordDownload.vue @@ -89,7 +89,7 @@ export default { if (parseFloat(res.data.progress) == 1) { this.percentage = 100; }else { - this.percentage = (res.data.progress*100).toFixed(1); + this.percentage = (res.data.data.progress*100).toFixed(1); } if (callback)callback(); } @@ -175,6 +175,10 @@ export default { }).then((res) => { console.log(res) if (res.data.code === 0) { + if (res.data.data.length === 0){ + this.percentage = 0 + return + } this.percentage = parseFloat(res.data.data.percentage)*100 if (res.data.data[0].percentage === '1') { this.getProgressForFileRun = false; From 692f7167883a246067dfa0dc7f7f16d6ef309d9b Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 16 Sep 2022 18:02:56 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=82=B9=E6=92=AD?= =?UTF-8?q?=E6=97=B6RtpServer=E4=B8=BA=E6=AD=A3=E5=B8=B8=E5=85=B3=E9=97=AD?= =?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 --- .../vmp/gb28181/transmit/SIPProcessorObserver.java | 4 ++-- .../event/request/impl/AckRequestProcessor.java | 2 +- .../iot/vmp/media/zlm/ZLMRTPServerFactory.java | 13 ++++++++++++- .../com/genersoft/iot/vmp/media/zlm/ZLMRunner.java | 2 +- .../vmp/media/zlm/event/ZLMStatusEventListener.java | 4 ++-- .../iot/vmp/service/impl/PlayServiceImpl.java | 6 +++--- web_src/src/components/dialog/devicePlayer.vue | 3 +++ 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java index b94daf7a3..c10973aa4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java @@ -69,7 +69,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { * @param requestEvent RequestEvent事件 */ @Override - @Async + @Async("taskExecutor") public void processRequest(RequestEvent requestEvent) { String method = requestEvent.getRequest().getMethod(); if ("NOTIFY".equalsIgnoreCase(requestEvent.getRequest().getMethod())) { @@ -89,7 +89,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { * @param responseEvent responseEvent事件 */ @Override - @Async + @Async("taskExecutor") public void processResponse(ResponseEvent responseEvent) { Response response = responseEvent.getResponse(); int status = response.getStatusCode(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index a56a83c21..5c1ba9ce4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -102,7 +102,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - logger.info("收到ACK,开始向上级推流 rtp/{}", sendRtpItem.getStreamId()); + logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); Map param = new HashMap<>(); param.put("vhost","__defaultVhost__"); param.put("app",sendRtpItem.getApp()); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index a5b5f19c9..f1f407209 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -98,7 +98,18 @@ public class ZLMRTPServerFactory { result = rtpInfo.getInteger("local_port"); if (result == 0) { // 此时说明rtpServer已经创建但是流还没有推上来 - + // 此时重新打开rtpServer + Map param = new HashMap<>(); + param.put("stream_id", streamId); + JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param); + if (jsonObject != null ) { + System.out.println(jsonObject); + if (jsonObject.getInteger("code") == 0) { + return createRTPServer(mediaServerItem, streamId, ssrc, port); + }else { + logger.warn("[开启rtpServer], 重启RtpServer错误"); + } + } } return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index da4bb76c3..3dfb16787 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -104,7 +104,7 @@ public class ZLMRunner implements CommandLineRunner { }, 60 * 1000 ); } - @Async + @Async("taskExecutor") public void connectZlmServer(MediaServerItem mediaServerItem){ String connectZlmServerTaskKey = "connect-zlm-" + mediaServerItem.getId(); ZLMServerConfig zlmServerConfigFirst = getMediaServerConfig(mediaServerItem); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java index 223ef13f2..bad8e5605 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java @@ -36,7 +36,7 @@ public class ZLMStatusEventListener { @Autowired private IPlayService playService; - @Async + @Async("taskExecutor") @EventListener public void onApplicationEvent(ZLMOnlineEvent event) { logger.info("[ZLM] 上线 ID:" + event.getMediaServerId()); @@ -45,7 +45,7 @@ public class ZLMStatusEventListener { playService.zlmServerOnline(event.getMediaServerId()); } - @Async + @Async("taskExecutor") @EventListener public void onApplicationEvent(ZLMOfflineEvent event) { 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 320b16830..c0b9e95bf 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 @@ -253,7 +253,7 @@ public class PlayServiceImpl implements IPlayService { if (ssrcInfo == null) { ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); } - logger.info("[点播开始] deviceId: {}, channelId: {}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getSsrc() ); + logger.info("[点播开始] deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck() ); // 超时处理 String timeOutTaskKey = UUID.randomUUID().toString(); SSRCInfo finalSsrcInfo = ssrcInfo; @@ -262,12 +262,12 @@ public class PlayServiceImpl implements IPlayService { SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); if (dialog != null) { - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); timeoutCallback.run(1, "收流超时"); // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null); }else { - logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); timeoutCallback.run(0, "点播超时"); mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 71530cec6..e44770fa4 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -394,6 +394,9 @@ export default { console.log(this.videoUrl) }, openDialog: function (tab, deviceId, channelId, param) { + if (this.showVideoDialog) { + return; + } this.tabActiveName = tab; this.channelId = channelId; this.deviceId = deviceId; From 710600db6f3bd6f72a83ef75cca30953fd0f375f Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 21 Sep 2022 18:18:37 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=BC=98=E5=8C=96sip=E6=B6=88=E6=81=AF?= =?UTF-8?q?=EF=BC=8C=E5=8E=BB=E9=99=A4=E8=87=AA=E5=8A=A8dialog=E5=88=9B?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/conf/MediaConfig.java | 4 +- .../genersoft/iot/vmp/gb28181/SipLayer.java | 39 +--- .../iot/vmp/gb28181/bean/Device.java | 1 + .../iot/vmp/gb28181/bean/SendRtpItem.java | 51 +++-- .../iot/vmp/gb28181/bean/SubscribeHolder.java | 14 +- .../iot/vmp/gb28181/bean/SubscribeInfo.java | 64 +++--- .../vmp/gb28181/conf/DefaultProperties.java | 46 ++++ .../iot/vmp/gb28181/event/SipSubscribe.java | 16 +- .../iot/vmp/gb28181/task/ISubscribeTask.java | 2 - .../task/impl/CatalogSubscribeTask.java | 67 +++--- .../MobilePositionSubscribeHandlerTask.java | 62 +----- .../impl/MobilePositionSubscribeTask.java | 73 ++++--- .../transmit/SIPProcessorObserver.java | 9 +- .../gb28181/transmit/cmd/ISIPCommander.java | 5 +- .../cmd/ISIPCommanderForPlatform.java | 1 + .../cmd/SIPRequestHeaderPlarformProvider.java | 117 ++++++++++- .../cmd/SIPRequestHeaderProvider.java | 11 +- .../transmit/cmd/impl/SIPCommander.java | 128 ++---------- .../cmd/impl/SIPCommanderFroPlatform.java | 196 +++++++----------- .../request/SIPRequestProcessorParent.java | 146 +++++++------ .../request/impl/AckRequestProcessor.java | 85 ++++---- .../request/impl/ByeRequestProcessor.java | 112 +++++----- .../request/impl/InviteRequestProcessor.java | 170 ++++++++------- .../request/impl/NotifyRequestProcessor.java | 4 +- .../impl/SubscribeRequestProcessor.java | 93 ++++----- .../impl/info/InfoRequestProcessor.java | 14 +- .../impl/message/MessageRequestProcessor.java | 12 +- .../cmd/DeviceControlQueryMessageHandler.java | 8 +- .../notify/cmd/AlarmNotifyMessageHandler.java | 6 +- .../cmd/KeepaliveNotifyMessageHandler.java | 2 +- .../cmd/MediaStatusNotifyMessageHandler.java | 2 +- .../MobilePositionNotifyMessageHandler.java | 4 +- .../query/cmd/AlarmQueryMessageHandler.java | 2 +- .../query/cmd/CatalogQueryMessageHandler.java | 2 +- .../cmd/DeviceInfoQueryMessageHandler.java | 2 +- .../cmd/DeviceStatusQueryMessageHandler.java | 2 +- .../cmd/RecordInfoQueryMessageHandler.java | 11 +- .../cmd/BroadcastResponseMessageHandler.java | 4 +- .../cmd/CatalogResponseMessageHandler.java | 6 +- .../ConfigDownloadResponseMessageHandler.java | 2 +- .../DeviceControlResponseMessageHandler.java | 2 +- .../cmd/DeviceInfoResponseMessageHandler.java | 6 +- .../DeviceStatusResponseMessageHandler.java | 2 +- .../MobilePositionResponseMessageHandler.java | 7 +- .../PresetQueryResponseMessageHandler.java | 10 +- .../cmd/RecordInfoResponseMessageHandler.java | 2 +- .../impl/InviteResponseProcessor.java | 4 +- .../vmp/media/zlm/ZLMHttpHookListener.java | 16 +- .../vmp/media/zlm/ZLMMediaListManager.java | 13 +- .../vmp/media/zlm/ZLMRTPServerFactory.java | 6 +- .../vmp/media/zlm/ZlmHttpHookSubscribe.java | 3 - .../vmp/media/zlm/dto/ChannelOnlineEvent.java | 4 +- .../iot/vmp/service/IPlatformService.java | 11 + .../impl/PlatformChannelServiceImpl.java | 6 +- .../vmp/service/impl/PlatformServiceImpl.java | 40 +++- .../service/impl/RedisGbPlayMsgListener.java | 9 +- .../storager/impl/RedisCatchStorageImpl.java | 4 +- .../vmanager/gb28181/device/DeviceQuery.java | 14 +- .../src/components/dialog/recordDownload.vue | 3 +- 59 files changed, 892 insertions(+), 865 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index 3438893fd..03498fd08 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -64,8 +64,8 @@ public class MediaConfig{ @Value("${media.secret}") private String secret; - @Value("${media.stream-none-reader-delay-ms:10000}") - private int streamNoneReaderDelayMS = 10000; + @Value("${media.stream-none-reader-delay-ms:15000}") + private int streamNoneReaderDelayMS = 15000; @Value("${media.rtp.enable}") private boolean rtpEnable; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 9b570972a..cd8b5d762 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.gb28181; import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties; import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; @@ -41,43 +42,7 @@ public class SipLayer{ @Bean("sipStack") @DependsOn({"sipFactory"}) SipStack createSipStack() throws PeerUnavailableException { - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); - properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp()); - /** - * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码 - * gov/nist/javax/sip/SipStackImpl.class - * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法 - */ - -// * gov/nist/javax/sip/SipStackImpl.class - if (logger.isDebugEnabled()) { - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); - } - // 接收所有notify请求,即使没有订阅 - properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); - properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false"); - // 为_NULL _对话框传递_终止的_事件 - properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); - // 会话清理策略 - properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal"); - // 处理由该服务器处理的基于底层TCP的保持生存超时 - properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60"); - // 获取实际内容长度,不使用header中的长度信息 - properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true"); - - /** - * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE - */ - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); -// properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", "com.genersoft.iot.vmp.gb28181.session.SipMessagePreprocessing"); -// if (logger.isDebugEnabled()) { -// properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); -// } - - sipStack = (SipStackImpl) sipFactory.createSipStack(properties); - + sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false)); return sipStack; } 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 b26dc68a4..4137fe463 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 @@ -380,4 +380,5 @@ public class Device { public void setTreeType(String treeType) { this.treeType = treeType; } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java index 41e1af780..8f61bc969 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java @@ -1,5 +1,7 @@ package com.genersoft.iot.vmp.gb28181.bean; +import gov.nist.javax.sip.message.SIPRequest; + public class SendRtpItem { /** @@ -77,10 +79,20 @@ public class SendRtpItem { private String serverId; /** - * invite的callId + * invite 的 callId */ private String CallId; + /** + * invite 的 fromTag + */ + private String fromTag; + + /** + * invite 的 toTag + */ + private String toTag; + /** * 发送时,rtp的pt(uint8_t),不传时默认为96 */ @@ -96,15 +108,12 @@ public class SendRtpItem { */ private boolean onlyAudio = false; + /** * 播放类型 */ private InviteStreamType playType; - private byte[] transaction; - - private byte[] dialog; - public String getIp() { return ip; } @@ -225,22 +234,6 @@ public class SendRtpItem { this.playType = playType; } - public byte[] getTransaction() { - return transaction; - } - - public void setTransaction(byte[] transaction) { - this.transaction = transaction; - } - - public byte[] getDialog() { - return dialog; - } - - public void setDialog(byte[] dialog) { - this.dialog = dialog; - } - public int getPt() { return pt; } @@ -272,4 +265,20 @@ public class SendRtpItem { public void setServerId(String serverId) { this.serverId = serverId; } + + public String getFromTag() { + return fromTag; + } + + public void setFromTag(String fromTag) { + this.fromTag = fromTag; + } + + public String getToTag() { + return toTag; + } + + public void setToTag(String toTag) { + this.toTag = toTag; + } } 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 441dff3fd..ba905b50b 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 @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.service.IPlatformService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import org.springframework.beans.factory.annotation.Autowired; @@ -23,15 +24,6 @@ public class SubscribeHolder { @Autowired private DynamicTask dynamicTask; - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired - private ISIPCommanderForPlatform sipCommanderForPlatform; - - @Autowired - private IVideoManagerStorage storager; - private final String taskOverduePrefix = "subscribe_overdue_"; private static ConcurrentHashMap catalogMap = new ConcurrentHashMap<>(); @@ -62,15 +54,13 @@ public class SubscribeHolder { } // 添加任务处理订阅过期 dynamicTask.stop(taskOverdueKey); - } public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { mobilePositionMap.put(platformId, subscribeInfo); String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId; // 添加任务处理GPS定时推送 - dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, - storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask), + dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId), subscribeInfo.getGpsInterval() * 1000); String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; // 添加任务处理订阅过期 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java index 1958b449c..2c80c62b6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java @@ -1,7 +1,10 @@ package com.genersoft.iot.vmp.gb28181.bean; import com.genersoft.iot.vmp.utils.SerializeUtils; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.message.SIPResponse; +import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.RequestEvent; import javax.sip.ServerTransaction; @@ -11,30 +14,24 @@ import javax.sip.message.Request; public class SubscribeInfo { - public SubscribeInfo(RequestEvent evt, String id) { + public SubscribeInfo(ServerTransaction serverTransaction, String id) { this.id = id; - Request request = evt.getRequest(); - ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME); - this.expires = expiresHeader.getExpires(); + SIPRequest request = (SIPRequest)serverTransaction.getRequest(); + this.request = request; + this.expires = request.getExpires().getExpires(); EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME); this.eventId = eventHeader.getEventId(); this.eventType = eventHeader.getEventType(); - this.transaction = evt.getServerTransaction(); - this.dialog = evt.getDialog(); - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); - this.callId = callIdHeader.getCallId(); - } - public SubscribeInfo() { } private String id; + + private SIPRequest request; private int expires; - private String callId; private String eventId; private String eventType; - private ServerTransaction transaction; - private Dialog dialog; + private SIPResponse response; /** * 以下为可选字段 @@ -43,29 +40,28 @@ public class SubscribeInfo { private String sn; private int gpsInterval; - public String getId() { return id; } - public int getExpires() { - return expires; - } - - public String getCallId() { - return callId; - } - public void setId(String id) { this.id = id; } - public void setExpires(int expires) { - this.expires = expires; + public SIPRequest getRequest() { + return request; } - public void setCallId(String callId) { - this.callId = callId; + public void setRequest(SIPRequest request) { + this.request = request; + } + + public int getExpires() { + return expires; + } + + public void setExpires(int expires) { + this.expires = expires; } public String getEventId() { @@ -84,20 +80,12 @@ public class SubscribeInfo { this.eventType = eventType; } - public ServerTransaction getTransaction() { - return transaction; + public SIPResponse getResponse() { + return response; } - public void setTransaction(ServerTransaction transaction) { - this.transaction = transaction; - } - - public Dialog getDialog() { - return dialog; - } - - public void setDialog(Dialog dialog) { - this.dialog = dialog; + public void setResponse(SIPResponse response) { + this.response = response; } public String getSn() { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java new file mode 100644 index 000000000..e0691e5da --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java @@ -0,0 +1,46 @@ +package com.genersoft.iot.vmp.gb28181.conf; + +import java.util.Properties; + +/** + * 获取sip默认配置 + * @author lin + */ +public class DefaultProperties { + + public static Properties getProperties(String ip, boolean isDebug) { + Properties properties = new Properties(); + properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); + properties.setProperty("javax.sip.IP_ADDRESS", ip); + properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); + /** + * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码 + * gov/nist/javax/sip/SipStackImpl.class + * sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法 + */ + +// * gov/nist/javax/sip/SipStackImpl.class + if (isDebug) { + properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); + } + // 接收所有notify请求,即使没有订阅 + properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); + properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); + properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false"); + // 为_NULL _对话框传递_终止的_事件 + properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); + // 会话清理策略 + properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal"); + // 处理由该服务器处理的基于底层TCP的保持生存超时 + properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60"); + // 获取实际内容长度,不使用header中的长度信息 + properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true"); + + /** + * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE + */ + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); + + return properties; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java index b3fd82e8d..69529b061 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.gb28181.event; import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; +import gov.nist.javax.sip.message.SIPRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; @@ -104,22 +105,27 @@ public class SipSubscribe { this.type = EventResultType.timeout; this.msg = "消息超时未回复"; this.statusCode = -1024; - this.dialog = timeoutEvent.getClientTransaction().getDialog(); - this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null; + if (timeoutEvent.isServerTransaction()) { + this.callId = ((SIPRequest)timeoutEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId(); + }else { + this.callId = ((SIPRequest)timeoutEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId(); + } }else if (event instanceof TransactionTerminatedEvent) { TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event; this.type = EventResultType.transactionTerminated; this.msg = "事务已结束"; this.statusCode = -1024; - this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId(); - this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog(); + if (transactionTerminatedEvent.isServerTransaction()) { + this.callId = ((SIPRequest)transactionTerminatedEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId(); + }else { + this.callId = ((SIPRequest)transactionTerminatedEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId(); + } }else if (event instanceof DialogTerminatedEvent) { DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event; this.type = EventResultType.dialogTerminated; this.msg = "会话已结束"; this.statusCode = -1024; this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); - this.dialog = dialogTerminatedEvent.getDialog(); }else if (event instanceof DeviceNotFoundEvent) { DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event; this.type = EventResultType.deviceNotFoundEvent; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java index c7a16ee57..a4e711d9e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java @@ -7,6 +7,4 @@ import javax.sip.DialogState; */ public interface ISubscribeTask extends Runnable{ void stop(); - - DialogState getDialogState(); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java index 577e72400..bfa900a9d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import gov.nist.javax.sip.message.SIPRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; @@ -12,6 +13,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.ResponseEvent; +import javax.sip.header.ToHeader; +import java.text.ParseException; import java.util.Timer; import java.util.TimerTask; @@ -23,7 +26,7 @@ public class CatalogSubscribeTask implements ISubscribeTask { private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class); private Device device; private final ISIPCommander sipCommander; - private Dialog dialog; + private SIPRequest request; private DynamicTask dynamicTask; @@ -41,24 +44,26 @@ public class CatalogSubscribeTask implements ISubscribeTask { if (dynamicTask.get(taskKey) != null) { dynamicTask.stop(taskKey); } - sipCommander.catalogSubscribe(device, dialog, eventResult -> { - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) { - dialog = eventResult.dialog; - } + SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> { ResponseEvent event = (ResponseEvent) eventResult.event; - if (event.getResponse().getRawContent() != null) { - // 成功 - logger.info("[目录订阅]成功: {}", device.getDeviceId()); - }else { - // 成功 - logger.info("[目录订阅]成功: {}", device.getDeviceId()); + // 成功 + logger.info("[目录订阅]成功: {}", device.getDeviceId()); + ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME); + try { + this.request.getToHeader().setTag(toHeader.getTag()); + } catch (ParseException e) { + logger.info("[目录订阅]成功: 但为request设置ToTag失败"); + this.request = null; } },eventResult -> { - dialog = null; + this.request = null; // 失败 logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000); }); + if (sipRequest != null) { + this.request = sipRequest; + } } @Override @@ -74,29 +79,19 @@ public class CatalogSubscribeTask implements ISubscribeTask { if (dynamicTask.get(taskKey) != null) { dynamicTask.stop(taskKey); } - if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { - device.setSubscribeCycleForCatalog(0); - sipCommander.catalogSubscribe(device, dialog, eventResult -> { - ResponseEvent event = (ResponseEvent) eventResult.event; - if (event.getResponse().getRawContent() != null) { - // 成功 - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); - }else { - // 成功 - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); - } - },eventResult -> { - // 失败 - logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); - }); - } - } - - @Override - public DialogState getDialogState() { - if (dialog == null) { - return null; - } - return dialog.getState(); + device.setSubscribeCycleForCatalog(0); + sipCommander.catalogSubscribe(device, request, eventResult -> { + ResponseEvent event = (ResponseEvent) eventResult.event; + if (event.getResponse().getRawContent() != null) { + // 成功 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); + }else { + // 成功 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); + } + },eventResult -> { + // 失败 + logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); + }); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java index 2ee103763..2e792c1c9 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java @@ -4,9 +4,11 @@ import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.service.IPlatformService; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.SpringBeanFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; @@ -20,71 +22,23 @@ import java.util.List; */ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { - private Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeHandlerTask.class); - private IRedisCatchStorage redisCatchStorage; - private IVideoManagerStorage storager; - private ISIPCommanderForPlatform sipCommanderForPlatform; - private SubscribeHolder subscribeHolder; - private ParentPlatform platform; + private IPlatformService platformService; + private String platformId; - private String sn; - private String key; - public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, - ISIPCommanderForPlatform sipCommanderForPlatform, - IVideoManagerStorage storager, - String platformId, - String sn, - String key, - SubscribeHolder subscribeInfo, - DynamicTask dynamicTask) { - this.redisCatchStorage = redisCatchStorage; - this.storager = storager; - this.platform = storager.queryParentPlatByServerGBId(platformId); - this.sn = sn; - this.key = key; - this.sipCommanderForPlatform = sipCommanderForPlatform; - this.subscribeHolder = subscribeInfo; + public MobilePositionSubscribeHandlerTask(String platformId) { + this.platformService = SpringBeanFactory.getBean("platformServiceImpl"); + this.platformId = platformId; } @Override public void run() { - - if (platform == null) { - return; - } - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()); - if (subscribe != null) { - - // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 - List gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId()); - if (gbStreams.size() == 0) { - return; - } - for (DeviceChannel deviceChannel : gbStreams) { - String gbId = deviceChannel.getChannelId(); - GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); - // 无最新位置不发送 - if (gpsMsgInfo != null) { - // 经纬度都为0不发送 - if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { - continue; - } - // 发送GPS消息 - sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe); - } - } - } + platformService.sendNotifyMobilePosition(this.platformId); } @Override public void stop() { } - - @Override - public DialogState getDialogState() { - return null; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java index e43e59b9c..5dbdbe644 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java @@ -4,6 +4,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.message.SIPResponse; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,6 +14,8 @@ import org.springframework.scheduling.annotation.Async; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.ResponseEvent; +import javax.sip.header.ToHeader; +import java.text.ParseException; import java.util.Timer; import java.util.TimerTask; @@ -21,9 +25,10 @@ import java.util.TimerTask; */ public class MobilePositionSubscribeTask implements ISubscribeTask { private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class); - private Device device; - private ISIPCommander sipCommander; - private Dialog dialog; + private Device device; + private ISIPCommander sipCommander; + + private SIPRequest request; private DynamicTask dynamicTask; private String taskKey = "mobile-position-subscribe-timeout"; @@ -38,24 +43,26 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { if (dynamicTask.get(taskKey) != null) { dynamicTask.stop(taskKey); } - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { - if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) { - dialog = eventResult.dialog; - } + SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> { + // 成功 + logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); ResponseEvent event = (ResponseEvent) eventResult.event; - if (event.getResponse().getRawContent() != null) { - // 成功 - logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); - }else { - // 成功 - logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); + ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME); + try { + this.request.getToHeader().setTag(toHeader.getTag()); + } catch (ParseException e) { + logger.info("[移动位置订阅]成功: 为request设置ToTag失败"); + this.request = null; } },eventResult -> { - dialog = null; + this.request = null; // 失败 logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000); }); + if (sipRequest != null) { + this.request = sipRequest; + } } @@ -71,29 +78,19 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { if (dynamicTask.get(taskKey) != null) { dynamicTask.stop(taskKey); } - if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) { - logger.info("取消移动订阅时dialog状态为{}", dialog.getState()); - device.setSubscribeCycleForMobilePosition(0); - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { - ResponseEvent event = (ResponseEvent) eventResult.event; - if (event.getResponse().getRawContent() != null) { - // 成功 - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); - }else { - // 成功 - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); - } - },eventResult -> { - // 失败 - logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); - }); - } - } - @Override - public DialogState getDialogState() { - if (dialog == null) { - return null; - } - return dialog.getState(); + device.setSubscribeCycleForMobilePosition(0); + sipCommander.mobilePositionSubscribe(device, request, eventResult -> { + ResponseEvent event = (ResponseEvent) eventResult.event; + if (event.getResponse().getRawContent() != null) { + // 成功 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); + }else { + // 成功 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); + } + },eventResult -> { + // 失败 + logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); + }); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java index c10973aa4..1252adb48 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java @@ -72,9 +72,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @Async("taskExecutor") public void processRequest(RequestEvent requestEvent) { String method = requestEvent.getRequest().getMethod(); - if ("NOTIFY".equalsIgnoreCase(requestEvent.getRequest().getMethod())) { - System.out.println(); - } ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); if (sipRequestProcessor == null) { logger.warn("不支持方法{}的request", method); @@ -173,6 +170,12 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @Override public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { +// if (transactionTerminatedEvent.isServerTransaction()) { +// ServerTransaction serverTransaction = transactionTerminatedEvent.getServerTransaction(); +// serverTransaction.get +// } + + // Transaction transaction = null; // System.out.println("processTransactionTerminated"); // if (transactionTerminatedEvent.isServerTransaction()) { 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 8aadf2c8a..c7f6385ee 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 @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import gov.nist.javax.sip.message.SIPRequest; import javax.sip.Dialog; @@ -313,7 +314,7 @@ public interface ISIPCommander { * @param device 视频设备 * @return true = 命令发送成功 */ - boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent); + SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent); /** * 订阅、取消订阅报警信息 @@ -333,7 +334,7 @@ public interface ISIPCommander { * @param device 视频设备 * @return true = 命令发送成功 */ - boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent); + SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent); /** * 拉框控制命令 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java index 351505f39..ab229bd59 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java @@ -117,4 +117,5 @@ public interface ISIPCommanderForPlatform { * @param callId callId */ void streamByeCmd(ParentPlatform platform, String callId); + void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem); } 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 6ee3cce20..7ecdaf0fa 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 @@ -2,10 +2,13 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.GitUtil; import gov.nist.javax.sip.message.MessageFactoryImpl; +import gov.nist.javax.sip.message.SIPRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.DigestUtils; @@ -154,8 +157,17 @@ public class SIPRequestHeaderPlarformProvider { return registerRequest; } + public Request createMessageRequest(ParentPlatform parentPlatform, String content, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException { + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); + return createMessageRequest(parentPlatform, content, sendRtpItem.getToTag(), SipUtils.getNewViaTag(), sendRtpItem.getFromTag(), callIdHeader); + } public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException { + return createMessageRequest(parentPlatform, content, fromTag, viaTag, null, callIdHeader); + } + + + public Request createMessageRequest(ParentPlatform parentPlatform, String content, String fromTag, String viaTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException { Request request = null; String serverAddress = parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort(); // sipuri @@ -174,7 +186,7 @@ public class SIPRequestHeaderPlarformProvider { // to SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), serverAddress); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, null); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); @@ -192,4 +204,107 @@ public class SIPRequestHeaderPlarformProvider { request.setContent(content, contentTypeHeader); return request; } + + public SIPRequest createNotifyRequest(ParentPlatform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { + SIPRequest 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(), SipUtils.getNewViaTag()); + 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, subscribeInfo.getResponse().getToTag()); + // to + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag()); + + // Forwards + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); + // ceq + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.NOTIFY); + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); + // 设置编码, 防止中文乱码 + messageFactory.setDefaultContentEncodingCharset("gb2312"); + + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId()); + + request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, + toHeader, viaHeaders, maxForwards); + + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil)); + + 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; + } + + public SIPRequest createByeRequest(ParentPlatform platform, SendRtpItem sendRtpItem) throws PeerUnavailableException, ParseException, InvalidArgumentException { + + if (sendRtpItem == null ) { + return null; + } + + SIPRequest request = null; + // sipuri + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+ ":" + platform.getServerPort()); + // via + ArrayList viaHeaders = new ArrayList<>(); + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(platform.getDeviceIp(), Integer.parseInt(platform.getDevicePort()), + platform.getTransport(), SipUtils.getNewViaTag()); + viaHeader.setRPort(); + viaHeaders.add(viaHeader); + // from + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(platform.getDeviceGBId(), + platform.getDeviceIp() + ":" + platform.getDevicePort()); + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag()); + // to + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerGBDomain()); + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, sendRtpItem.getFromTag()); + + // Forwards + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); + // ceq + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); + // 设置编码, 防止中文乱码 + messageFactory.setDefaultContentEncodingCharset("gb2312"); + + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); + + request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader, + toHeader, viaHeaders, maxForwards); + + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil)); + + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort(); + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() + .createSipURI(platform.getDeviceGBId(), sipAddress)); + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + + return request; + } } 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 21ab37423..34c5cbe53 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 @@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.GitUtil; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; +import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.stack.SIPDialog; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -199,24 +200,24 @@ public class SIPRequestHeaderProvider { return request; } - public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { + public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { Request request = null; // sipuri SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); // via ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), - device.getTransport(), viaTag); + device.getTransport(), SipUtils.getNewViaTag()); viaHeader.setRPort(); viaHeaders.add(viaHeader); // from SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain()); Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag()); // to SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag()); // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); @@ -238,7 +239,7 @@ public class SIPRequestHeaderProvider { // Event EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); - int random = (int)Math.random() * 1000000000; + int random = (int) Math.floor(Math.random() * 10000); eventHeader.setEventId(random + ""); request.addHeader(eventHeader); 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 135afd209..0368ee4ac 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 @@ -1424,7 +1424,7 @@ public class SIPCommander implements ISIPCommander { * @return true = 命令发送成功 */ @Override - public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) { + public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) { try { StringBuffer subscribePostitionXml = new StringBuffer(200); String charset = device.getCharset(); @@ -1434,38 +1434,27 @@ public class SIPCommander implements ISIPCommander { subscribePostitionXml.append("" + (int)((Math.random()*9+1)*100000) + "\r\n"); subscribePostitionXml.append("" + device.getDeviceId() + "\r\n"); if (device.getSubscribeCycleForMobilePosition() > 0) { - subscribePostitionXml.append("" + String.valueOf(device.getMobilePositionSubmissionInterval()) + "\r\n"); + subscribePostitionXml.append("" + device.getMobilePositionSubmissionInterval() + "\r\n"); } subscribePostitionXml.append("\r\n"); - Request request; - if (dialog != null) { - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); - request = dialog.createRequest(Request.SUBSCRIBE); - ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog()); - request.setExpires(expiresHeader); + CallIdHeader callIdHeader; - request.setRequestURI(requestURI); - - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); - request.setContent(subscribePostitionXml.toString(), contentTypeHeader); - - CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME); - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ()); - request.removeHeader(CSeqHeader.NAME); - request.addHeader(cSeqHeader); + if (requestOld != null) { + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); }else { - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); } + SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4)); + transmitRequest(device, request, errorEvent, okEvent); - return true; + return request; } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { e.printStackTrace(); - return false; + return null; } } @@ -1515,7 +1504,7 @@ public class SIPCommander implements ISIPCommander { CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, expires, "presence" , callIdHeader); + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence" , callIdHeader); transmitRequest(device, request); return true; @@ -1527,7 +1516,7 @@ public class SIPCommander implements ISIPCommander { } @Override - public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { + public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { try { StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); @@ -1538,40 +1527,24 @@ public class SIPCommander implements ISIPCommander { cmdXml.append("" + device.getDeviceId() + "\r\n"); cmdXml.append("\r\n"); + CallIdHeader callIdHeader ; - Request request; - if (dialog != null) { - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); - request = dialog.createRequest(Request.SUBSCRIBE); - ExpiresHeader expiresHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForCatalog()); - request.setExpires(expiresHeader); - - request.setRequestURI(requestURI); - - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); - request.setContent(cmdXml.toString(), contentTypeHeader); - - CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME); - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ()); - request.removeHeader(CSeqHeader.NAME); - request.addHeader(cSeqHeader); - + if (requestOld != null) { + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId()); }else { - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - - // 有效时间默认为60秒以上 - request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(), - SipUtils.getNewFromTag(), null, device.getSubscribeCycleForCatalog(), "Catalog" , - callIdHeader); - } + + // 有效时间默认为60秒以上 + SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog" , + callIdHeader); transmitRequest(device, request, errorEvent, okEvent); - return true; + return request; } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) { e.printStackTrace(); - return false; + return null; } } @@ -1847,61 +1820,4 @@ public class SIPCommander implements ISIPCommander { } return true; } - - private void sendNotify(Device device, String catalogXmlContent, - SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) - throws SipException, ParseException { - MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); - String characterSet = device.getCharset(); - // 设置编码, 防止中文乱码 - messageFactory.setDefaultContentEncodingCharset(characterSet); - Dialog dialog = subscribeInfo.getDialog(); - if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) { - return; - } - SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); - notifyRequest.setContent(catalogXmlContent, contentTypeHeader); - - SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory() - .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE); - notifyRequest.addHeader(subscriptionState); - - EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); - if (subscribeInfo.getEventId() != null) { - event.setEventId(subscribeInfo.getEventId()); - } - notifyRequest.addHeader(event); - - SipURI sipURI = (SipURI) notifyRequest.getRequestURI(); - if (subscribeInfo.getTransaction() != null) { - SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest(); - sipURI.setHost(request.getRemoteAddress().getHostAddress()); - sipURI.setPort(request.getRemotePort()); - }else { - sipURI.setHost(device.getIp()); - sipURI.setPort(device.getPort()); - } - - ClientTransaction transaction = null; - if ("TCP".equals(device.getTransport())) { - transaction = tcpSipProvider.getNewClientTransaction(notifyRequest); - } else if ("UDP".equals(device.getTransport())) { - transaction = udpSipProvider.getNewClientTransaction(notifyRequest); - } - // 添加错误订阅 - if (errorEvent != null) { - sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent); - } - // 添加订阅 - if (okEvent != null) { - sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent); - } - if (transaction == null) { - logger.error("平台{}的Transport错误:{}",device.getDeviceId(), device.getTransport()); - return; - } - dialog.sendRequest(transaction); - - } } 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 0e6d4b8cd..a15940d79 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 @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl; +import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; @@ -45,7 +46,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class); @Autowired - private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider; + private SIPRequestHeaderPlarformProvider headerProviderPlatformProvider; @Autowired private IRedisCatchStorage redisCatchStorage; @@ -72,6 +73,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @Autowired private SipFactory sipFactory; + @Autowired + private SubscribeHolder subscribeHolder; + @Override public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { return register(parentPlatform, null, null, errorEvent, okEvent, false, true); @@ -96,7 +100,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { callIdHeader = udpSipProvider.getNewCallId(); } - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader, isRegister); // 将 callid 写入缓存, 等注册成功可以更新状态 @@ -118,7 +122,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { }else { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister); + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister); } transmitRequest(parentPlatform, request, null, okEvent); @@ -152,7 +156,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest( + Request request = headerProviderPlatformProvider.createMessageRequest( parentPlatform, keepaliveXml.toString(), SipUtils.getNewFromTag(), @@ -218,7 +222,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); transmitRequest(parentPlatform, request); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -312,7 +316,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader); + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader); transmitRequest(parentPlatform, request, null, eventResult -> { int indexNext = index + parentPlatform.getCatalogGroup(); sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext); @@ -352,7 +356,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); transmitRequest(parentPlatform, request); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -390,7 +394,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); transmitRequest(parentPlatform, request); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -425,11 +429,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { deviceStatusXml.append("" + gpsMsgInfo.getAltitude() + "\r\n"); deviceStatusXml.append("\r\n"); - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - callIdHeader.setCallId(subscribeInfo.getCallId()); - - sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> { + sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> { logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg); }, null); @@ -451,8 +451,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { if (parentPlatform == null) { return false; } - logger.info("[发送 报警订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), - deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); + logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), + deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm)); try { String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600); @@ -475,7 +475,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader); + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader); transmitRequest(parentPlatform, request); } catch (SipException | ParseException e) { @@ -527,18 +527,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return true; } - private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, + private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException { MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); String characterSet = parentPlatform.getCharacterSet(); // 设置编码, 防止中文乱码 messageFactory.setDefaultContentEncodingCharset(characterSet); - Dialog dialog = subscribeInfo.getDialog(); - if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) { - return; - } - SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY); + + SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo); notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ()); @@ -558,26 +555,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { sipURI.setHost(parentPlatform.getServerIP()); sipURI.setPort(parentPlatform.getServerPort()); +// ClientTransaction transaction = subscribeInfo.getClientTransaction(); +// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) { +// if ("TCP".equals(parentPlatform.getTransport())) { +// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest); +// } else if ("UDP".equals(parentPlatform.getTransport())) { +// transaction = udpSipProvider.getNewClientTransaction(notifyRequest); +// } +// } + ClientTransaction transaction = null; if ("TCP".equals(parentPlatform.getTransport())) { transaction = tcpSipProvider.getNewClientTransaction(notifyRequest); } else if ("UDP".equals(parentPlatform.getTransport())) { transaction = udpSipProvider.getNewClientTransaction(notifyRequest); } + // 添加错误订阅 if (errorEvent != null) { - sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent); + sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent); } // 添加订阅 if (okEvent != null) { - sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent); + sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent); } - if (transaction == null) { - logger.error("平台{}的Transport错误:{}",parentPlatform.getServerGBId(), parentPlatform.getTransport()); - return; - } - dialog.sendRequest(transaction); - + transaction.sendRequest(); + return transaction; } private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List channels, int sumNum, String type, SubscribeInfo subscribeInfo) { @@ -753,7 +756,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { // callid CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); transmitRequest(parentPlatform, request); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -772,36 +775,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return false; } - byte[] dialogByteArray = sendRtpItem.getDialog(); - if (dialogByteArray == null) { - return false; - } try{ - SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray); - SipStack sipStack; - if ("TCP".equals(platform.getTransport())) { - sipStack = tcpSipProvider.getSipStack(); - } else { - sipStack = udpSipProvider.getSipStack(); - } - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog); - if (dialog != sipDialog) { - dialog = sipDialog; - } - if ("TCP".equals(platform.getTransport())) { - dialog.setSipProvider(tcpSipProvider); - } else { - dialog.setSipProvider(udpSipProvider); - } - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack"); - sipStackField.setAccessible(true); - sipStackField.set(dialog, sipStack); - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners"); - eventListenersField.setAccessible(true); - eventListenersField.set(dialog, new HashSet<>()); - - SIPRequest messageRequest = (SIPRequest)dialog.createRequest(Request.MESSAGE); String characterSet = platform.getCharacterSet(); StringBuffer mediaStatusXml = new StringBuffer(200); mediaStatusXml.append("\r\n"); @@ -811,6 +786,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { mediaStatusXml.append("" + sendRtpItem.getChannelId() + "\r\n"); mediaStatusXml.append("121\r\n"); mediaStatusXml.append("\r\n"); + + SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(), + sendRtpItem); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader); SipURI sipURI = (SipURI) messageRequest.getRequestURI(); @@ -822,17 +801,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { }else { clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest); } - dialog.sendRequest(clientTransaction); + clientTransaction.sendRequest(); } catch (SipException e) { e.printStackTrace(); return false; } catch (ParseException e) { e.printStackTrace(); return false; - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); } return true; @@ -846,61 +823,46 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { } SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platform.getServerGBId(), null, null, callId); if (sendRtpItem != null) { - String mediaServerId = sendRtpItem.getMediaServerId(); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); - if (mediaServerItem != null) { - mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); - zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId()); + streamByeCmd(platform, sendRtpItem); + } + } + + @Override + public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) { + if (sendRtpItem == null ) { + logger.info("[向上级发送BYE], sendRtpItem 为NULL"); + return; + } + if (platform == null) { + logger.info("[向上级发送BYE], platform 为NULL"); + return; + } + logger.info("[向上级发送BYE], {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId()); + String mediaServerId = sendRtpItem.getMediaServerId(); + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + if (mediaServerItem != null) { + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); + zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId()); + } + try { + + SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem); + if (byeRequest == null) { + logger.warn("[向上级发送bye]:无法创建 byeRequest"); } - byte[] dialogByteArray = sendRtpItem.getDialog(); - if (dialogByteArray != null) { - SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray); - SipStack sipStack; - if ("TCP".equals(platform.getTransport())) { - sipStack = tcpSipProvider.getSipStack(); - } else { - sipStack = udpSipProvider.getSipStack(); - } - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog); - if (dialog != sipDialog) { - dialog = sipDialog; - } - try { - if ("TCP".equals(platform.getTransport())) { - dialog.setSipProvider(tcpSipProvider); - } else { - dialog.setSipProvider(udpSipProvider); - } - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack"); - sipStackField.setAccessible(true); - sipStackField.set(dialog, sipStack); - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners"); - eventListenersField.setAccessible(true); - eventListenersField.set(dialog, new HashSet<>()); - - Request byeRequest = dialog.createRequest(Request.BYE); - - SipURI byeURI = (SipURI) byeRequest.getRequestURI(); - byeURI.setHost(platform.getServerIP()); - byeURI.setPort(platform.getServerPort()); - ClientTransaction clientTransaction; - if ("TCP".equals(platform.getTransport())) { - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); - } else { - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); - } - dialog.sendRequest(clientTransaction); - } catch (SipException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - + ClientTransaction clientTransaction; + if ("TCP".equals(platform.getTransport())) { + clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); + } else { + clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); } + clientTransaction.sendRequest(); + } catch (SipException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java index 32130654c..c12d0df9a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java @@ -1,9 +1,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.stack.SIPServerTransaction; import org.apache.commons.lang3.ArrayUtils; import org.dom4j.Document; @@ -19,10 +21,7 @@ import javax.sip.*; import javax.sip.address.Address; import javax.sip.address.AddressFactory; import javax.sip.address.SipURI; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.ExpiresHeader; -import javax.sip.header.HeaderFactory; -import javax.sip.header.ViaHeader; +import javax.sip.header.*; import javax.sip.message.MessageFactory; import javax.sip.message.Request; import javax.sip.message.Response; @@ -59,9 +58,6 @@ public abstract class SIPRequestProcessorParent { public ServerTransaction getServerTransaction(RequestEvent evt) { Request request = evt.getRequest(); ServerTransaction serverTransaction = evt.getServerTransaction(); - if (serverTransaction != null) { - System.out.println(serverTransaction.getState().toString()); - } // 判断TCP还是UDP boolean isTcp = false; ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); @@ -123,105 +119,107 @@ public abstract class SIPRequestProcessorParent { return null; } + class ResponseAckExtraParam{ + String content; + ContentTypeHeader contentTypeHeader; + SipURI sipURI; + int expires = -1; + } + /*** * 回复状态码 * 100 trying * 200 OK * 400 * 404 - * @param evt - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException */ - public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); - ServerTransaction serverTransaction = getServerTransaction(evt); - if (serverTransaction == null) { - logger.warn("回复失败:{}", response); - return; - } - serverTransaction.sendResponse(response); - if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) { - - if (serverTransaction.getDialog() != null) { - serverTransaction.getDialog().delete(); - } - } + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode) throws SipException, InvalidArgumentException, ParseException { + return responseAck(serverTransaction, statusCode, null); } - public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); - response.setReasonPhrase(msg); - ServerTransaction serverTransaction = getServerTransaction(evt); + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException { + return responseAck(serverTransaction, statusCode, msg, null); + } + + public SIPResponse responseAck(ServerTransaction serverTransaction, int statusCode, String msg, ResponseAckExtraParam responseAckExtraParam) throws SipException, InvalidArgumentException, ParseException { + ToHeader toHeader = (ToHeader) serverTransaction.getRequest().getHeader(ToHeader.NAME); + if (toHeader.getTag() == null) { + toHeader.setTag(SipUtils.getNewTag()); + } + SIPResponse response = (SIPResponse)getMessageFactory().createResponse(statusCode, serverTransaction.getRequest()); + if (msg != null) { + response.setReasonPhrase(msg); + } + if (responseAckExtraParam != null) { + if (responseAckExtraParam.sipURI != null && serverTransaction.getRequest().getMethod().equals(Request.INVITE)) { + logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort()); + Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress( + SipFactory.getInstance().createAddressFactory().createSipURI(responseAckExtraParam.sipURI.getUser(), responseAckExtraParam.sipURI.getHost()+":"+responseAckExtraParam.sipURI.getPort() + )); + response.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); + } + if (responseAckExtraParam.contentTypeHeader != null) { + response.setContent(responseAckExtraParam.content, responseAckExtraParam.contentTypeHeader); + } + + if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) { + if (responseAckExtraParam.expires == -1) { + logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header"); + }else { + ExpiresHeader expiresHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(responseAckExtraParam.expires); + response.addHeader(expiresHeader); + } + } + }else { + if (serverTransaction.getRequest().getMethod().equals(Request.SUBSCRIBE)) { + logger.error("[参数不全] 2xx的SUBSCRIBE回复,必须设置Expires header"); + } + } serverTransaction.sendResponse(response); - if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(evt.getRequest().getMethod())) { + if (statusCode >= 200 && !"NOTIFY".equalsIgnoreCase(serverTransaction.getRequest().getMethod())) { if (serverTransaction.getDialog() != null) { serverTransaction.getDialog().delete(); } } + return response; } /** * 回复带sdp的200 - * @param evt - * @param sdp - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException */ - public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); - SipFactory sipFactory = SipFactory.getInstance(); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); - response.setContent(sdp, contentTypeHeader); + public SIPResponse responseSdpAck(ServerTransaction serverTransaction, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { + + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); // 兼容国标中的使用编码@域名作为RequestURI的情况 - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); + SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI(); if (sipURI.getPort() == -1) { - sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); + sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); } - logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); + ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam(); + responseAckExtraParam.contentTypeHeader = contentTypeHeader; + responseAckExtraParam.content = sdp; + responseAckExtraParam.sipURI = sipURI; - Address concatAddress = sipFactory.createAddressFactory().createAddress( - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() - )); - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); - ServerTransaction serverTransaction = getServerTransaction(evt); - if (serverTransaction == null) { - - } - getServerTransaction(evt).sendResponse(response); + return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam); } /** * 回复带xml的200 - * @param evt - * @param xml - * @throws SipException - * @throws InvalidArgumentException - * @throws ParseException */ - public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); - SipFactory sipFactory = SipFactory.getInstance(); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); - response.setContent(xml, contentTypeHeader); + public SIPResponse responseXmlAck(ServerTransaction serverTransaction, String xml, ParentPlatform platform, Integer expires) throws SipException, InvalidArgumentException, ParseException { + ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); - // 兼容国标中的使用编码@域名作为RequestURI的情况 - SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); + SipURI sipURI = (SipURI)serverTransaction.getRequest().getRequestURI(); if (sipURI.getPort() == -1) { - sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); + sipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); } - logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); - - Address concatAddress = sipFactory.createAddressFactory().createAddress( - sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() - )); - response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); - response.addHeader(evt.getRequest().getHeader(ExpiresHeader.NAME)); - getServerTransaction(evt).sendResponse(response); - return response; + ResponseAckExtraParam responseAckExtraParam = new ResponseAckExtraParam(); + responseAckExtraParam.contentTypeHeader = contentTypeHeader; + responseAckExtraParam.content = xml; + responseAckExtraParam.sipURI = sipURI; + responseAckExtraParam.expires = expires; + return responseAck(serverTransaction, Response.OK, null, responseAckExtraParam); } public Element getRootElement(RequestEvent evt) throws DocumentException { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index 5c1ba9ce4..f8c3abfb6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -87,53 +87,46 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In */ @Override public void process(RequestEvent evt) { - Dialog dialog = evt.getDialog(); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); - if (dialog == null) { - return; + + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + logger.info("[收到ACK]: platformGbId->{}", platformGbId); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId); + // 取消设置的超时任务 + dynamicTask.stop(callIdHeader.getCallId()); + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); + String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); + Map param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",sendRtpItem.getApp()); + param.put("stream",sendRtpItem.getStreamId()); + param.put("ssrc", sendRtpItem.getSsrc()); + param.put("dst_url",sendRtpItem.getIp()); + param.put("dst_port", sendRtpItem.getPort()); + param.put("is_udp", is_Udp); + param.put("src_port", sendRtpItem.getLocalPort()); + param.put("pt", sendRtpItem.getPt()); + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); + if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) { + // 开启rtcp保活 + param.put("udp_rtcp_timeout", "1"); } - if (dialog.getState()== DialogState.CONFIRMED) { - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); - logger.info("ACK请求: platformGbId->{}", platformGbId); - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId); - // 取消设置的超时任务 - dynamicTask.stop(callIdHeader.getCallId()); - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); - String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); - Map param = new HashMap<>(); - param.put("vhost","__defaultVhost__"); - param.put("app",sendRtpItem.getApp()); - param.put("stream",sendRtpItem.getStreamId()); - param.put("ssrc", sendRtpItem.getSsrc()); - param.put("dst_url",sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - param.put("is_udp", is_Udp); - param.put("src_port", sendRtpItem.getLocalPort()); - param.put("pt", sendRtpItem.getPt()); - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); - if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) { - // 开启rtcp保活 - param.put("udp_rtcp_timeout", "1"); - } - if (mediaInfo == null) { - RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( - sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), - sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), - sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); - redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{ - startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); - }); - }else { - JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); + if (mediaInfo == null) { + RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), + sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); + redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{ startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); - } - - + }); + }else { + JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); + startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); } } private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform, @@ -141,12 +134,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In if (jsonObject == null) { logger.error("RTP推流失败: 请检查ZLM服务"); } else if (jsonObject.getInteger("code") == 0) { + logger.info("调用ZLM推流接口, 结果: {}", jsonObject); logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); - sendRtpItem.setDialog(dialogByteArray); - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); - sendRtpItem.setTransaction(transactionByteArray); - redisCatchStorage.updateSendRTPSever(sendRtpItem); } else { logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); if (sendRtpItem.isOnlyAudio()) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java index a1f0aae59..4211417b7 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java @@ -78,73 +78,67 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @Override public void process(RequestEvent evt) { try { - responseAck(evt, Response.OK); - Dialog dialog = evt.getDialog(); + responseAck(getServerTransaction(evt), Response.OK); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); - if (dialog == null) { - return; - } - if (dialog.getState().equals(DialogState.TERMINATED)) { - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); - logger.info("收到bye, [{}/{}]", platformGbId, channelId); - if (sendRtpItem != null){ - String streamId = sendRtpItem.getStreamId(); - Map param = new HashMap<>(); - param.put("vhost","__defaultVhost__"); - param.put("app",sendRtpItem.getApp()); - param.put("stream",streamId); - param.put("ssrc",sendRtpItem.getSsrc()); - logger.info("收到bye:停止向上级推流:" + streamId); - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null); - zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); - int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); - if (totalReaderCount <= 0) { - logger.info("收到bye: {} 无其它观看者,通知设备停止推流", streamId); - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null); - } - if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), - sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); - } + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); + logger.info("[收到bye] {}/{}", platformGbId, channelId); + if (sendRtpItem != null){ + String streamId = sendRtpItem.getStreamId(); + Map param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",sendRtpItem.getApp()); + param.put("stream",streamId); + param.put("ssrc",sendRtpItem.getSsrc()); + logger.info("[收到bye] 停止向上级推流:{}", streamId); + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null); + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); + if (totalReaderCount <= 0) { + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null); + } + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), + sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); } } - // 可能是设备主动停止 - Device device = storager.queryVideoDeviceByChannelId(platformGbId); - if (device != null) { - storager.stopPlay(device.getDeviceId(), channelId); - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); - if (streamInfo != null) { - redisCatchStorage.stopPlay(streamInfo); - mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream()); - } - SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); - if (ssrcTransactionForPlay != null){ - SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog()); - if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){ - // 释放ssrc - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); - if (mediaServerItem != null) { - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc()); - } - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream()); - } - } - SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null); - if (ssrcTransactionForPlayBack != null) { + } + // 可能是设备主动停止 + Device device = storager.queryVideoDeviceByChannelId(platformGbId); + if (device != null) { + storager.stopPlay(device.getDeviceId(), channelId); + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); + if (streamInfo != null) { + redisCatchStorage.stopPlay(streamInfo); + mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream()); + } + SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); + if (ssrcTransactionForPlay != null){ + SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog()); + if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){ // 释放ssrc - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId()); + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); if (mediaServerItem != null) { - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc()); + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc()); } - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream()); } } + SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null); + if (ssrcTransactionForPlayBack != null) { + // 释放ssrc + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId()); + if (mediaServerItem != null) { + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc()); + } + streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); + } } } catch (SipException e) { e.printStackTrace(); 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 abcffe2cd..6ff5c0f7a 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 @@ -8,7 +8,6 @@ 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.cmd.ISIPCommander; -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.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; @@ -28,9 +27,10 @@ import com.genersoft.iot.vmp.service.impl.RedisPushStreamResponseListener; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; -import com.genersoft.iot.vmp.utils.SerializeUtils; import gov.nist.javax.sdp.TimeDescriptionImpl; import gov.nist.javax.sdp.fields.TimeField; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.message.SIPResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -128,17 +128,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements String channelId = SipUtils.getChannelIdFromRequest(request); String requesterId = SipUtils.getUserIdFromFromHeader(request); CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); + ServerTransaction serverTransaction = getServerTransaction(evt); if (requesterId == null || channelId == null) { logger.info("无法从FromHeader的Address中获取到平台id,返回400"); // 参数不全, 发400,请求错误 - responseAck(evt, Response.BAD_REQUEST); + responseAck(serverTransaction, Response.BAD_REQUEST); return; } + // 查询请求是否来自上级平台\设备 ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); if (platform == null) { - inviteFromDeviceHandle(evt, requesterId); + inviteFromDeviceHandle(serverTransaction, requesterId); } else { // 查询平台下是否有该通道 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); @@ -150,12 +152,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements StreamProxyItem proxyByAppAndStream =null; // 不是通道可能是直播流 if (channel != null && gbStream == null) { - if (channel.getStatus() == 0) { - logger.info("通道离线,返回400"); - responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); - return; - } - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 +// if (channel.getStatus() == 0) { +// logger.info("通道离线,返回400"); +// responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); +// return; +// } + // 通道存在,发100,TRYING + responseAck(serverTransaction, Response.TRYING); } else if (channel == null && gbStream != null) { String mediaServerId = gbStream.getMediaServerId(); @@ -163,13 +166,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (mediaServerItem == null) { if ("proxy".equals(gbStream.getStreamType())) { logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); - responseAck(evt, Response.GONE); + responseAck(serverTransaction, Response.GONE); return; } else { streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) { logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); - responseAck(evt, Response.GONE); + responseAck(serverTransaction, Response.GONE); return; } } @@ -178,25 +181,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); if (streamPushItem == null) { logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); - responseAck(evt, Response.GONE); + responseAck(serverTransaction, Response.GONE); return; } }else if("proxy".equals(gbStream.getStreamType())){ proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream()); if (proxyByAppAndStream == null) { logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); - responseAck(evt, Response.GONE); + responseAck(serverTransaction, Response.GONE); return; } } } - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 + responseAck(serverTransaction, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 } else if (catalog != null) { - responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播 + responseAck(serverTransaction, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播 return; } else { logger.info("通道不存在,返回404"); - responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在 + responseAck(serverTransaction, Response.NOT_FOUND); // 通道不存在,发404,资源不存在 return; } // 解析sdp消息, 使用jainsip 自带的sdp解析方式 @@ -209,7 +212,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements String ssrc; SessionDescription sdp; if (ssrcIndex >= 0) { - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 + //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段 ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); String substring = contentString.substring(0, contentString.indexOf("y=")); sdp = SdpFactory.getInstance().createSessionDescription(substring); @@ -256,9 +259,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements mediaTransmissionTCP = true; if ("active".equalsIgnoreCase(setup)) { tcpActive = true; - // 不支持tcp主动 - responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 目录不支持点播 - return; } else if ("passive".equalsIgnoreCase(setup)) { tcpActive = false; } @@ -270,7 +270,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (port == -1) { logger.info("不支持的媒体格式,返回415"); // 回复不支持的格式 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 return; } String username = sdp.getOrigin().getUsername(); @@ -283,24 +283,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); if (device == null) { logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel); - responseAck(evt, Response.SERVER_INTERNAL_ERROR); + responseAck(serverTransaction, Response.SERVER_INTERNAL_ERROR); return; } mediaServerItem = playService.getNewMediaServerItem(device); if (mediaServerItem == null) { logger.warn("未找到可用的zlm"); - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); return; } SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, device.getDeviceId(), channelId, mediaTransmissionTCP); + if (tcpActive != null) { sendRtpItem.setTcpActive(tcpActive); } if (sendRtpItem == null) { logger.warn("服务器端口资源不足"); - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); return; } sendRtpItem.setCallId(callIdHeader.getCallId()); @@ -342,7 +343,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements // 回复bye cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId()); }, 60 * 1000); - responseSdpAck(evt, content.toString(), platform); + responseSdpAck(serverTransaction, content.toString(), platform); } catch (SipException e) { e.printStackTrace(); @@ -357,8 +358,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements Response response = null; try { response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); - ServerTransaction serverTransaction = getServerTransaction(evt); serverTransaction.sendResponse(response); + System.out.println("未知错误。直接转发设备点播的错误"); if (serverTransaction.getDialog() != null) { serverTransaction.getDialog().delete(); } @@ -382,7 +383,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); try { - responseAck(evt, Response.REQUEST_TIMEOUT); + responseAck(serverTransaction, Response.REQUEST_TIMEOUT); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -420,6 +421,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); logger.info(JSONObject.toJSONString(ssrcInfo)); sendRtpItem.setStreamId(ssrcInfo.getStream()); + // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> { @@ -440,26 +442,26 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if("push".equals(gbStream.getStreamType())) { if (streamPushItem != null && streamPushItem.isPushIng()) { // 推流状态 - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } else { // 未推流 拉起 - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } }else if ("proxy".equals(gbStream.getStreamType())){ if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){ - pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, + pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); }else{ //开启代理拉流 boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream()); if(start1) { - pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, + pushProxyStream(evt, serverTransaction, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); }else{ //失败后通知 - notifyStreamOnline(evt, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, serverTransaction,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } } @@ -482,7 +484,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements /** * 安排推流 */ - private void pushProxyStream(RequestEvent evt, GbStream gbStream, ParentPlatform platform, + private void pushProxyStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, ParentPlatform platform, CallIdHeader callIdHeader, MediaServerItem mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { @@ -495,7 +497,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (sendRtpItem == null) { logger.warn("服务器端口资源不足"); - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); return; } if (tcpActive != null) { @@ -505,17 +507,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements // 写入redis, 超时时回复 sendRtpItem.setStatus(1); sendRtpItem.setCallId(callIdHeader.getCallId()); - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); - sendRtpItem.setDialog(dialogByteArray); - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); - sendRtpItem.setTransaction(transactionByteArray); + SIPRequest request = (SIPRequest) evt.getRequest(); + sendRtpItem.setFromTag(request.getFromTag()); + + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt); + if (response != null) { + sendRtpItem.setToTag(response.getToTag()); + } redisCatchStorage.updateSendRTPSever(sendRtpItem); - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt); } } - private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, + private void pushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, CallIdHeader callIdHeader, MediaServerItem mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { @@ -530,7 +534,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (sendRtpItem == null) { logger.warn("服务器端口资源不足"); - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); return; } if (tcpActive != null) { @@ -540,39 +544,43 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements // 写入redis, 超时时回复 sendRtpItem.setStatus(1); sendRtpItem.setCallId(callIdHeader.getCallId()); - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); - sendRtpItem.setDialog(dialogByteArray); - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); - sendRtpItem.setTransaction(transactionByteArray); + + SIPRequest request = (SIPRequest) evt.getRequest(); + sendRtpItem.setFromTag(request.getFromTag()); + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt); + if (response != null) { + sendRtpItem.setToTag(response.getToTag()); + } + redisCatchStorage.updateSendRTPSever(sendRtpItem); - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt); + } else { // 不在线 拉起 - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, serverTransaction,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } } else { // 其他平台内容 - otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } } /** * 通知流上线 */ - private void notifyStreamOnline(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, + private void notifyStreamOnline(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, CallIdHeader callIdHeader, MediaServerItem mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { if ("proxy".equals(gbStream.getStreamType())) { // TODO 控制启用以使设备上线 logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream()); - responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); + responseAck(serverTransaction, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); } else if ("push".equals(gbStream.getStreamType())) { if (!platform.isStartOfflinePush()) { // 平台设置中关闭了拉起离线的推流则直接回复 - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing"); + responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing"); return; } // 发送redis消息以使设备上线 @@ -587,7 +595,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream()); try { mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); - responseAck(evt, Response.REQUEST_TIMEOUT); // 超时 + responseAck(serverTransaction, Response.REQUEST_TIMEOUT); // 超时 } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -610,7 +618,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (sendRtpItem == null) { logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足"); try { - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -627,15 +635,17 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements // 写入redis, 超时时回复 sendRtpItem.setStatus(1); sendRtpItem.setCallId(callIdHeader.getCallId()); - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); - sendRtpItem.setDialog(dialogByteArray); - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); - sendRtpItem.setTransaction(transactionByteArray); + + SIPRequest request = (SIPRequest) evt.getRequest(); + sendRtpItem.setFromTag(request.getFromTag()); + SIPResponse response = sendStreamAck(mediaServerItem, serverTransaction, sendRtpItem, platform, evt); + if (response != null) { + sendRtpItem.setToTag(response.getToTag()); + } redisCatchStorage.updateSendRTPSever(sendRtpItem); - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt); } else { // 其他平台内容 - otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + otherWvpPushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } }); @@ -646,7 +656,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements dynamicTask.stop(callIdHeader.getCallId()); mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); try { - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, response.getMsg()); + responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg()); } catch (SipException e) { throw new RuntimeException(e); } catch (InvalidArgumentException e) { @@ -662,7 +672,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements /** * 来自其他wvp的推流 */ - private void otherWvpPushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, + private void otherWvpPushStream(RequestEvent evt, ServerTransaction serverTransaction, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, CallIdHeader callIdHeader, MediaServerItem mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { @@ -675,7 +685,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) { logger.warn("服务器端口资源不足"); try { - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -693,12 +703,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements // 写入redis, 超时时回复 sendRtpItem.setStatus(1); sendRtpItem.setCallId(callIdHeader.getCallId()); - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); - sendRtpItem.setDialog(dialogByteArray); - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); - sendRtpItem.setTransaction(transactionByteArray); + + SIPRequest request = (SIPRequest) evt.getRequest(); + sendRtpItem.setFromTag(request.getFromTag()); + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), serverTransaction,sendRtpItem, platform, evt); + if (response != null) { + sendRtpItem.setToTag(response.getToTag()); + } redisCatchStorage.updateSendRTPSever(sendRtpItem); - sendStreamAck(responseSendItemMsg.getMediaServerItem(), sendRtpItem, platform, evt); }, (wvpResult) -> { try { // 错误 @@ -708,12 +720,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream()); if (currentStreamPushItem.isPushIng()) { // 在线状态 - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + pushStream(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } else { // 不在线 拉起 - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, serverTransaction, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } } @@ -727,7 +739,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements try { - responseAck(evt, Response.BUSY_HERE); + responseAck(serverTransaction, Response.BUSY_HERE); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -739,7 +751,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements }); } - public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { + public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, ServerTransaction serverTransaction, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); @@ -762,7 +774,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements content.append("f=\r\n"); try { - responseSdpAck(evt, content.toString(), platform); + return responseSdpAck(serverTransaction, content.toString(), platform); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -770,18 +782,18 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } catch (ParseException e) { e.printStackTrace(); } + return null; } - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { + public void inviteFromDeviceHandle(ServerTransaction serverTransaction, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) Device device = redisCatchStorage.getDevice(requesterId); - Request request = evt.getRequest(); if (device != null) { logger.info("收到设备" + requesterId + "的语音广播Invite请求"); - responseAck(evt, Response.TRYING); + responseAck(serverTransaction, Response.TRYING); - String contentString = new String(request.getRawContent()); + String contentString = new String(serverTransaction.getRequest().getRawContent()); // jainSip不支持y=字段, 移除移除以解析。 String substring = contentString; String ssrc = "0000000404"; @@ -829,7 +841,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (port == -1) { logger.info("不支持的媒体格式,返回415"); // 回复不支持的格式 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 return; } String username = sdp.getOrigin().getUsername(); @@ -838,7 +850,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } else { logger.warn("来自无效设备/平台的请求"); - responseAck(evt, Response.BAD_REQUEST); + responseAck(serverTransaction, Response.BAD_REQUEST); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java index 9438471ad..206a1599d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java @@ -34,6 +34,7 @@ import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.header.FromHeader; import javax.sip.message.Response; @@ -94,7 +95,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements public void process(RequestEvent evt) { try { taskQueue.offer(new HandlerCatchData(evt, null, null)); - responseAck(evt, Response.OK); + ServerTransaction serverTransaction = getServerTransaction(evt); + responseAck(serverTransaction, Response.OK); if (!taskQueueHandlerRun) { taskQueueHandlerRun = true; taskExecutor.execute(()-> { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java index 8c04368a1..2ec40238e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java @@ -17,6 +17,12 @@ import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import gov.nist.javax.sip.SipProviderImpl; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.message.SIPResponse; +import gov.nist.javax.sip.stack.SIPClientTransaction; +import gov.nist.javax.sip.stack.SIPDialog; +import gov.nist.javax.sip.stack.SIPServerTransaction; +import gov.nist.javax.sip.stack.SIPServerTransactionImpl; import org.dom4j.DocumentException; import org.dom4j.Element; import org.slf4j.Logger; @@ -49,22 +55,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @Autowired private IVideoManagerStorage storager; - @Lazy - @Autowired - @Qualifier(value="tcpSipProvider") - private SipProviderImpl tcpSipProvider; - - @Lazy - @Autowired - @Qualifier(value="udpSipProvider") - private SipProviderImpl udpSipProvider; - - @Autowired - private DynamicTask dynamicTask; - - @Autowired - private UserSetting userSetting; - @Autowired private SubscribeHolder subscribeHolder; @@ -81,6 +71,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme */ @Override public void process(RequestEvent evt) { + ServerTransaction serverTransaction = getServerTransaction(evt); Request request = evt.getRequest(); try { Element rootElement = getRootElement(evt); @@ -90,12 +81,12 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme } String cmd = XmlUtil.getText(rootElement, "CmdType"); if (CmdType.MOBILE_POSITION.equals(cmd)) { - processNotifyMobilePosition(evt, rootElement); + processNotifyMobilePosition(serverTransaction, rootElement); // } else if (CmdType.ALARM.equals(cmd)) { // logger.info("接收到Alarm订阅"); -// processNotifyAlarm(evt, rootElement); +// processNotifyAlarm(serverTransaction, rootElement); } else if (CmdType.CATALOG.equals(cmd)) { - processNotifyCatalogList(evt, rootElement); + processNotifyCatalogList(serverTransaction, rootElement); } else { logger.info("接收到消息:" + cmd); @@ -108,7 +99,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme ServerTransaction transaction = getServerTransaction(evt); if (transaction != null) { transaction.sendResponse(response); - transaction.getDialog().delete(); transaction.terminate(); } else { logger.info("processRequest serverTransactionId is null."); @@ -123,24 +113,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme /** * 处理移动位置订阅消息 */ - private void processNotifyMobilePosition(RequestEvent evt, Element rootElement) throws SipException { - String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + private void processNotifyMobilePosition(ServerTransaction serverTransaction, Element rootElement) throws SipException { + if (serverTransaction == null) { + return; + } + String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest()); String deviceId = XmlUtil.getText(rootElement, "DeviceID"); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); - SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); + SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId); if (platform == null) { return; } - if (evt.getServerTransaction() == null) { - ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest()) - : udpSipProvider.getNewServerTransaction(evt.getRequest()); - subscribeInfo.setTransaction(serverTransaction); - Dialog dialog = serverTransaction.getDialog(); - dialog.terminateOnBye(false); - subscribeInfo.setDialog(dialog); - } + String sn = XmlUtil.getText(rootElement, "SN"); - logger.info("[回复 移动位置订阅]: {}", platformId); + logger.info("[回复上级的移动位置订阅请求]: {}", platformId); StringBuilder resultXml = new StringBuilder(200); resultXml.append("\r\n") .append("\r\n") @@ -158,17 +144,19 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme }else { subscribeInfo.setGpsInterval(Integer.parseInt(interval)); } - subscribeInfo.setSn(sn); - subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo); - - }else if (subscribeInfo.getExpires() == 0) { - subscribeHolder.removeMobilePositionSubscribe(platformId); } try { ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); - responseXmlAck(evt, resultXml.toString(), parentPlatform); + SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires()); + if (subscribeInfo.getExpires() == 0) { + subscribeHolder.removeMobilePositionSubscribe(platformId); + }else { + subscribeInfo.setResponse(response); + subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo); + } + } catch (SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); } @@ -178,25 +166,20 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme } - private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException { - - String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + private void processNotifyCatalogList(ServerTransaction serverTransaction, Element rootElement) throws SipException { + if (serverTransaction == null) { + return; + } + String platformId = SipUtils.getUserIdFromFromHeader(serverTransaction.getRequest()); String deviceId = XmlUtil.getText(rootElement, "DeviceID"); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); if (platform == null){ return; } - SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); - if (evt.getServerTransaction() == null) { - ServerTransaction serverTransaction = "TCP".equalsIgnoreCase(platform.getTransport()) ? tcpSipProvider.getNewServerTransaction(evt.getRequest()) - : udpSipProvider.getNewServerTransaction(evt.getRequest()); - subscribeInfo.setTransaction(serverTransaction); - Dialog dialog = serverTransaction.getDialog(); - dialog.terminateOnBye(false); - subscribeInfo.setDialog(dialog); - } + SubscribeInfo subscribeInfo = new SubscribeInfo(serverTransaction, platformId); + String sn = XmlUtil.getText(rootElement, "SN"); - logger.info("[回复 目录订阅]: {}/{}", platformId, deviceId); + logger.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId); StringBuilder resultXml = new StringBuilder(200); resultXml.append("\r\n") .append("\r\n") @@ -213,7 +196,13 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme } try { ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); - responseXmlAck(evt, resultXml.toString(), parentPlatform); + SIPResponse response = responseXmlAck(serverTransaction, resultXml.toString(), parentPlatform, subscribeInfo.getExpires()); + if (subscribeInfo.getExpires() == 0) { + subscribeHolder.removeCatalogSubscribe(platformId); + }else { + subscribeInfo.setResponse(response); + subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo); + } } catch (SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java index 98a2ec2d5..0b6ced0fe 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.header.*; import javax.sip.message.Response; @@ -65,9 +66,12 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); // 先从会话内查找 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 + + // 兼容海康 媒体通知 消息from字段不是设备ID的问题 + if (ssrcTransaction != null) { deviceId = ssrcTransaction.getDeviceId(); } + ServerTransaction serverTransaction = getServerTransaction(evt); // 查询设备是否存在 Device device = redisCatchStorage.getDevice(deviceId); // 查询上级平台是否存在 @@ -86,7 +90,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I } if (device == null && parentPlatform == null) { // 不存在则回复404 - responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found"); + responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found"); logger.warn("[设备未找到 ]: {}", deviceId); if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog())); @@ -101,14 +105,14 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I String streamId = sendRtpItem.getStreamId(); StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); if (null == streamInfo) { - responseAck(evt, Response.NOT_FOUND, "stream " + streamId + " not found"); + responseAck(serverTransaction, Response.NOT_FOUND, "stream " + streamId + " not found"); return; } Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID()); cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> { // 失败的回复 try { - responseAck(evt, eventResult.statusCode, eventResult.msg); + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -119,7 +123,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I }, eventResult -> { // 成功的回复 try { - responseAck(evt, eventResult.statusCode); + responseAck(serverTransaction, eventResult.statusCode); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { 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 9e0f8dca2..bd4ca6505 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 @@ -23,6 +23,7 @@ import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.address.SipURI; import javax.sip.header.CSeqHeader; @@ -79,6 +80,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement if (ssrcTransaction != null) { deviceId = ssrcTransaction.getDeviceId(); } + + ServerTransaction serverTransaction = getServerTransaction(evt); + // 查询设备是否存在 Device device = redisCatchStorage.getDevice(deviceId); // 查询上级平台是否存在 @@ -98,7 +102,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement } if (device == null && parentPlatform == null) { // 不存在则回复404 - responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found"); + responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found"); logger.warn("[设备未找到 ]: {}", deviceId); if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog())); @@ -110,13 +114,13 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement rootElement = getRootElement(evt); if (rootElement == null) { logger.error("处理MESSAGE请求 未获取到消息体{}", evt.getRequest()); - responseAck(evt, Response.BAD_REQUEST, "content is null"); + responseAck(serverTransaction, Response.BAD_REQUEST, "content is null"); return; } } catch (DocumentException e) { logger.warn("解析XML消息内容异常", e); // 不存在则回复404 - responseAck(evt, Response.BAD_REQUEST, e.getMessage()); + responseAck(serverTransaction, Response.BAD_REQUEST, e.getMessage()); } String name = rootElement.getName(); IMessageHandler messageHandler = messageHandlerMap.get(name); @@ -129,7 +133,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement }else { // 不支持的message // 不存在则回复415 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response"); + responseAck(serverTransaction, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response"); } } } catch (SipException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java index 9589bdfb8..094e656bc 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java @@ -61,6 +61,8 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @Override public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { + ServerTransaction serverTransaction = getServerTransaction(evt); + // 此处是上级发出的DeviceControl指令 String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); String channelId = getText(rootElement, "DeviceID"); @@ -107,7 +109,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); if (deviceForPlatform == null) { try { - responseAck(evt, Response.NOT_FOUND); + responseAck(serverTransaction, Response.NOT_FOUND); return; } catch (SipException e) { e.printStackTrace(); @@ -120,7 +122,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> { // 失败的回复 try { - responseAck(evt, eventResult.statusCode, eventResult.msg); + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -131,7 +133,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent }, eventResult -> { // 成功的回复 try { - responseAck(evt, eventResult.statusCode); + responseAck(serverTransaction, eventResult.statusCode); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java index 98fd7a7c1..add32d1b8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java @@ -77,7 +77,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme logger.info("[收到报警通知]设备:{}", device.getDeviceId()); // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[收到报警通知], 回复200OK失败", e); } @@ -179,7 +179,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme if (sipConfig.isAlarm()) { deviceAlarmService.add(deviceAlarm); } - + logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) { publisher.deviceAlarmEventPublish(deviceAlarm); } @@ -190,7 +190,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme logger.info("收到来自平台[{}]的报警通知", parentPlatform.getServerGBId()); // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); } catch (SipException e) { throw new RuntimeException(e); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java index 30297465c..63dc7d8f8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java @@ -69,7 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp } device.setKeepaliveTime(DateUtil.getNow()); // 回复200 OK - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); if (device.getOnline() == 1) { deviceService.updateDevice(device); }else { 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 5e724e711..332fc671b 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 @@ -66,7 +66,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java index 255fc00d3..b5051c0aa 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java @@ -65,7 +65,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen rootElement = getRootElement(evt, device.getCharset()); if (rootElement == null) { logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest()); - responseAck(evt, Response.BAD_REQUEST); + responseAck(getServerTransaction(evt), Response.BAD_REQUEST); return; } MobilePosition mobilePosition = new MobilePosition(); @@ -116,7 +116,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen } storager.updateChannelPosition(deviceChannel); //回复 200 OK - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); // 发送redis消息。 通知位置信息的变化 JSONObject jsonObject = new JSONObject(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java index 8c884d5a9..e35da0ea0 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java @@ -58,7 +58,7 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen logger.info("不支持alarm查询"); try { - responseAck(evt, Response.NOT_FOUND, "not support alarm query"); + responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query"); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { 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 d2db8f06c..cd98094de 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 @@ -66,7 +66,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); try { // 回复200 OK - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); Element snElement = rootElement.element("SN"); String sn = snElement.getText(); // 准备回复通道信息 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java index 19183e07e..27d9200b6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java @@ -48,7 +48,7 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); try { // 回复200 OK - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java index 64df786a4..05d2714ff 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java @@ -61,7 +61,7 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java index 4b6c9026f..49e04e9b2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.header.FromHeader; import javax.sip.message.Response; @@ -68,7 +69,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); - + ServerTransaction serverTransaction = getServerTransaction(evt); Element snElement = rootElement.element("SN"); int sn = Integer.parseInt(snElement.getText()); Element deviceIDElement = rootElement.element("DeviceID"); @@ -108,7 +109,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> { // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(serverTransaction, Response.OK); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -119,7 +120,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp }),(eventResult -> { // 查询失败 try { - responseAck(evt, eventResult.statusCode, eventResult.msg); + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -132,7 +133,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp }else if (channelSources.get(1).getCount() > 0) { // 直播流 // TODO try { - responseAck(evt, Response.NOT_IMPLEMENTED); // 回复未实现 + responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现 } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -142,7 +143,7 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp } }else { // 错误的请求 try { - responseAck(evt, Response.BAD_REQUEST); + responseAck(serverTransaction, Response.BAD_REQUEST); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java index ac946551b..b1bd489d2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java @@ -18,6 +18,7 @@ import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; @@ -46,8 +47,9 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i try { String channelId = getText(rootElement, "DeviceID"); String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId; + ServerTransaction serverTransaction = getServerTransaction(evt); // 回复200 OK - responseAck(evt, Response.OK); + responseAck(serverTransaction, Response.OK); // 此处是对本平台发出Broadcast指令的应答 JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); 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 be01fd70c..3cff19d48 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 @@ -27,6 +27,7 @@ import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; @@ -87,7 +88,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp taskQueue.offer(new HandlerCatchData(evt, device, element)); // 回复200 OK try { - responseAck(evt, Response.OK); + ServerTransaction serverTransaction = getServerTransaction(evt); + responseAck(serverTransaction, Response.OK); if (!taskQueueHandlerRun) { taskQueueHandlerRun = true; taskExecutor.execute(()-> { @@ -103,7 +105,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp Element sumNumElement = rootElement.element("SumNum"); Element snElement = rootElement.element("SN"); if (snElement == null || sumNumElement == null || deviceListElement == null) { - responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error"); + responseAck(serverTransaction, Response.BAD_REQUEST, "xml error"); continue; } int sumNum = Integer.parseInt(sumNumElement.getText()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java index d1a2893f5..200677a18 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java @@ -52,7 +52,7 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + device.getDeviceId() + channelId; try { // 回复200 OK - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); // 此处是对本平台发出DeviceControl指令的应答 JSONObject json = new JSONObject(); XmlUtil.node2Json(element, json); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java index 0c9b8353f..cd6d1b836 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java @@ -46,7 +46,7 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare public void handForDevice(RequestEvent evt, Device device, Element element) { // 此处是对本平台发出DeviceControl指令的应答 try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); JSONObject json = new JSONObject(); String channelId = getText(element, "DeviceID"); XmlUtil.node2Json(element, json); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java index 98e5ac007..a0109edd5 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java @@ -25,6 +25,7 @@ import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; @@ -74,11 +75,12 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]:" + (device != null ? device.getDeviceId():"" )); return; } + ServerTransaction serverTransaction = getServerTransaction(evt); try { rootElement = getRootElement(evt, device.getCharset()); if (rootElement == null) { logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest()); - responseAck(evt, Response.BAD_REQUEST); + responseAck(serverTransaction, Response.BAD_REQUEST); return; } Element deviceIdElement = rootElement.element("DeviceID"); @@ -99,7 +101,7 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent msg.setData(device); deferredResultHolder.invokeAllResult(msg); // 回复200 OK - responseAck(evt, Response.OK); + responseAck(serverTransaction, Response.OK); } catch (DocumentException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java index 5854261b8..b324b5d2e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java @@ -59,7 +59,7 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen } // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java index 42666db53..158f5b712 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java @@ -25,6 +25,7 @@ import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; @@ -64,11 +65,13 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar @Override public void handForDevice(RequestEvent evt, Device device, Element rootElement) { + ServerTransaction serverTransaction = getServerTransaction(evt); + try { rootElement = getRootElement(evt, device.getCharset()); if (rootElement == null) { logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest()); - responseAck(evt, Response.BAD_REQUEST); + responseAck(serverTransaction, Response.BAD_REQUEST); return; } MobilePosition mobilePosition = new MobilePosition(); @@ -130,7 +133,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar jsonObject.put("speed", mobilePosition.getSpeed()); redisCatchStorage.sendMobilePositionMsg(jsonObject); //回复 200 OK - responseAck(evt, Response.OK); + responseAck(serverTransaction, Response.OK); } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java index abc9440d9..1febeae60 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Component; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; @@ -51,10 +52,13 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent public void handForDevice(RequestEvent evt, Device device, Element element) { Element rootElement = null; try { + + ServerTransaction serverTransaction = getServerTransaction(evt); + rootElement = getRootElement(evt, device.getCharset()); if (rootElement == null) { logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest()); - responseAck(evt, Response.BAD_REQUEST); + responseAck(serverTransaction, Response.BAD_REQUEST); return; } Element presetListNumElement = rootElement.element("PresetList"); @@ -63,7 +67,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent String deviceId = getText(rootElement, "DeviceID"); String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId; if (snElement == null || presetListNumElement == null) { - responseAck(evt, Response.BAD_REQUEST, "xml error"); + responseAck(serverTransaction, Response.BAD_REQUEST, "xml error"); return; } int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num")); @@ -93,7 +97,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent requestMessage.setKey(key); requestMessage.setData(presetQuerySipReqList); deferredResultHolder.invokeAllResult(requestMessage); - responseAck(evt, Response.OK); + responseAck(serverTransaction, Response.OK); } catch (DocumentException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java index d96b6225a..e9ee32d90 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java @@ -72,7 +72,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent // 回复200 OK try { - responseAck(evt, Response.OK); + responseAck(getServerTransaction(evt), Response.OK); taskQueue.offer(new HandlerCatchData(evt, device, rootElement)); if (!taskQueueHandlerRun) { taskQueueHandlerRun = true; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java index a2bc6e1f1..9b090299f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java @@ -7,6 +7,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcesso import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.utils.GitUtil; import gov.nist.javax.sip.ResponseEventExt; +import gov.nist.javax.sip.message.SIPResponse; +import gov.nist.javax.sip.stack.SIPClientTransaction; import gov.nist.javax.sip.stack.SIPDialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -78,7 +80,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { // 下发ack if (statusCode == Response.OK) { ResponseEventExt event = (ResponseEventExt)evt; - SIPDialog dialog = (SIPDialog)evt.getDialog(); + SIPDialog dialog = new SIPDialog((SIPClientTransaction) event.getClientTransaction(), (SIPResponse) event.getResponse()); CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); Request reqAck = dialog.createAck(cseq.getSeqNumber()); SipURI requestURI = (SipURI) reqAck.getRequestURI(); 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 b78997427..f645b8a8b 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 @@ -103,7 +103,7 @@ public class ZLMHttpHookListener { @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") public JSONObject onServerKeepalive(@RequestBody JSONObject json){ - logger.info("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString()); + logger.info("[ ZLM HOOK ]on_server_keepalive API调用,参数:" + json.toString()); String mediaServerId = json.getString("mediaServerId"); List subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); if (subscribes != null && subscribes.size() > 0) { @@ -453,6 +453,7 @@ public class ZLMHttpHookListener { storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); // 如果正在给上级推送,则发送bye + }else{ streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null); if (streamInfo != null) { @@ -509,6 +510,19 @@ public class ZLMHttpHookListener { } } } + if (!regist) { + List sendRtpItems = redisCatchStorage.querySendRTPServerByStream(stream); + if (sendRtpItems.size() > 0) { + for (SendRtpItem sendRtpItem : sendRtpItems) { + if (sendRtpItem.getApp().equals(app)) { + String platformId = sendRtpItem.getPlatformId(); + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); + + commanderFroPlatform.streamByeCmd(platform, sendRtpItem); + } + } + } + } } JSONObject ret = new JSONObject(); 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 50a1fa59a..b545ccc9e 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 @@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.text.ParseException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -83,7 +84,11 @@ public class ZLMMediaListManager { } if (transform != null) { if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) { - getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId()); + try { + getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId()); + } catch (ParseException e) { + throw new RuntimeException(e); + } removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); } } @@ -95,7 +100,11 @@ public class ZLMMediaListManager { // 查看推流状态 if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { if (getChannelOnlineEventLister(app, stream) != null) { - getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId); + try { + getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId); + } catch (ParseException e) { + throw new RuntimeException(e); + } removedChannelOnlineEventLister(app, stream); } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index f1f407209..91b5a5172 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -330,12 +330,12 @@ public class ZLMRTPServerFactory { Boolean result = false; JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); if (jsonObject == null) { - logger.error("停止RTP推流失败: 请检查ZLM服务"); + logger.error("[停止RTP推流] 失败: 请检查ZLM服务"); } else if (jsonObject.getInteger("code") == 0) { result= true; - logger.info("停止RTP推流成功"); + logger.info("[停止RTP推流] 成功"); } else { - logger.error("停止RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); + logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"),JSONObject.toJSON(param), jsonObject); } return result; } 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 823bdabb4..19ffdc49e 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 @@ -137,8 +137,6 @@ public class ZlmHttpHookSubscribe { @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 public void execute(){ - logger.info("[hook订阅] 清理"); - Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); int total = 0; for (HookType hookType : allSubscribes.keySet()) { @@ -153,6 +151,5 @@ public class ZlmHttpHookSubscribe { } } } - logger.info("[hook订阅] 清理结束,共清理{}条过期数据", total); } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java index 21e6ca032..714838edb 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java @@ -1,9 +1,11 @@ package com.genersoft.iot.vmp.media.zlm.dto; +import java.text.ParseException; + /** * @author lin */ public interface ChannelOnlineEvent { - void run(String app, String stream, String serverId); + void run(String app, String stream, String serverId) throws ParseException; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java index b5f3c5b7c..ddc91ebd7 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java @@ -1,8 +1,13 @@ package com.genersoft.iot.vmp.service; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.github.pagehelper.PageInfo; +import java.util.List; + /** * 国标平台的业务类 * @author lin @@ -42,4 +47,10 @@ public interface IPlatformService { * @param parentPlatform */ void login(ParentPlatform parentPlatform); + + /** + * 向上级平台发送位置订阅 + * @param platformId 平台 + */ + void sendNotifyMobilePosition(String platformId); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java index d0245502c..22d195efd 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java @@ -73,7 +73,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { result = platformChannelMapper.addChannels(platformId, channelReducesToAdd); // TODO 后续给平台增加控制开关以控制是否响应目录订阅 List deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform); - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); + if (deviceChannelList != null) { + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); + } } return result; @@ -83,7 +85,7 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { List deviceChannelList = new ArrayList<>(); if (channelReduces.size() > 0){ PlatformCatalog catalog = catalogManager.select(catalogId); - if (catalog == null && !catalogId.equals(platform.getServerGBId())) { + if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) { logger.warn("未查询到目录{}的信息", catalogId); return null; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java index 6df1483b3..dedc7c19f 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -1,17 +1,16 @@ package com.genersoft.iot.vmp.service.impl; import com.genersoft.iot.vmp.conf.DynamicTask; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; +import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlatformService; +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -57,6 +56,9 @@ public class PlatformServiceImpl implements IPlatformService { @Autowired private SubscribeHolder subscribeHolder; + @Autowired + private GbStreamMapper gbStreamMapper; + @Override @@ -228,4 +230,34 @@ public class PlatformServiceImpl implements IPlatformService { 60*1000); }, null); } + + @Override + public void sendNotifyMobilePosition(String platformId) { + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId); + if (platform == null) { + return; + } + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()); + if (subscribe != null) { + + // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 + List gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId()); + if (gbStreams.size() == 0) { + return; + } + for (DeviceChannel deviceChannel : gbStreams) { + String gbId = deviceChannel.getChannelId(); + GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); + // 无最新位置不发送 + if (gpsMsgInfo != null) { + // 经纬度都为0不发送 + if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { + continue; + } + // 发送GPS消息 + commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe); + } + } + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java index ff82cd7f6..e327d0f29 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java @@ -23,6 +23,7 @@ import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.stereotype.Component; +import java.text.ParseException; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -86,7 +87,7 @@ public class RedisGbPlayMsgListener implements MessageListener { public interface PlayMsgCallback{ - void handler(ResponseSendItemMsg responseSendItemMsg); + void handler(ResponseSendItemMsg responseSendItemMsg) throws ParseException; } public interface PlayMsgCallbackForStartSendRtpStream{ @@ -134,7 +135,11 @@ public class RedisGbPlayMsgListener implements MessageListener { PlayMsgCallback playMsgCallback = callbacks.get(key); if (playMsgCallback != null) { callbacksForError.remove(key); - playMsgCallback.handler(responseSendItemMsg); + try { + playMsgCallback.handler(responseSendItemMsg); + } catch (ParseException e) { + throw new RuntimeException(e); + } } break; case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: 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 9d30fef35..258b956b0 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 @@ -710,14 +710,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public void sendMobilePositionMsg(JSONObject jsonObject) { String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION; - logger.info("[redis发送通知]移动位置 {}: {}", key, jsonObject.toString()); + logger.info("[redis发送通知] 移动位置 {}: {}", key, jsonObject.toString()); RedisUtil.convertAndSend(key, jsonObject); } @Override public void sendStreamPushRequestedMsg(MessageForPushChannel msg) { String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED; - logger.info("[redis发送通知]推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream()); + logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream()); RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java index 9c7d203a0..eb79fc79b 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java @@ -413,24 +413,20 @@ public class DeviceQuery { @GetMapping("/{deviceId}/subscribe_info") @Operation(summary = "获取设备的订阅状态") @Parameter(name = "deviceId", description = "设备国标编号", required = true) - public WVPResult> getSubscribeInfo(@PathVariable String deviceId) { + public WVPResult> getSubscribeInfo(@PathVariable String deviceId) { Set allKeys = dynamicTask.getAllKeys(); - Map dialogStateMap = new HashMap<>(); + Map dialogStateMap = new HashMap<>(); for (String key : allKeys) { if (key.startsWith(deviceId)) { ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key); - DialogState dialogState = subscribeTask.getDialogState(); - if (dialogState == null) { - continue; - } if (subscribeTask instanceof CatalogSubscribeTask) { - dialogStateMap.put("catalog", dialogState.toString()); + dialogStateMap.put("catalog", 1); }else if (subscribeTask instanceof MobilePositionSubscribeTask) { - dialogStateMap.put("mobilePosition", dialogState.toString()); + dialogStateMap.put("mobilePosition", 1); } } } - WVPResult> wvpResult = new WVPResult<>(); + WVPResult> wvpResult = new WVPResult<>(); wvpResult.setCode(0); wvpResult.setData(dialogStateMap); return wvpResult; diff --git a/web_src/src/components/dialog/recordDownload.vue b/web_src/src/components/dialog/recordDownload.vue index df3880c44..b0b8feac4 100644 --- a/web_src/src/components/dialog/recordDownload.vue +++ b/web_src/src/components/dialog/recordDownload.vue @@ -84,12 +84,13 @@ export default { method: 'get', url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}` }).then((res)=> { + console.log(res) if (res.data.code === 0) { this.streamInfo = res.data.data; if (parseFloat(res.data.progress) == 1) { this.percentage = 100; }else { - this.percentage = (res.data.data.progress*100).toFixed(1); + this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1); } if (callback)callback(); } From 5e73874880cdfd5b6b99147a0cdd8a6eabcfbf16 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 22 Sep 2022 11:22:08 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=98=9F=E5=88=97?= =?UTF-8?q?=E5=A4=84=E7=90=86redis=E6=B6=88=E6=81=AF=E5=92=8Csip=E6=B6=88?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8=E6=8E=A8?= =?UTF-8?q?=E6=B5=81=E7=8A=B6=E6=80=81=E4=BD=9C=E4=B8=BA=E9=80=9A=E9=81=93?= =?UTF-8?q?=E5=9C=A8=E7=BA=BF=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/conf/UserSetting.java | 10 + .../iot/vmp/conf/redis/RedisConfig.java | 2 +- .../iot/vmp/gb28181/bean/SipMsgInfo.java | 56 +++++ .../request/impl/AckRequestProcessor.java | 5 +- .../request/impl/InviteRequestProcessor.java | 4 +- .../notify/cmd/AlarmNotifyMessageHandler.java | 219 ++++++++++-------- .../MobilePositionNotifyMessageHandler.java | 152 +++++++----- .../vmp/service/impl/PlatformServiceImpl.java | 6 +- .../iot/vmp/service/impl/PlayServiceImpl.java | 32 ++- .../service/impl/RedisAlarmMsgListener.java | 77 ------ .../impl/RedisPushStreamResponseListener.java | 62 ----- .../RedisPushStreamStatusListMsgListener.java | 81 ------- .../service/impl/RedisStreamMsgListener.java | 72 ------ .../redisMsg/RedisAlarmMsgListener.java | 100 ++++++++ .../RedisGbPlayMsgListener.java | 180 +++++++------- .../RedisGpsMsgListener.java | 3 +- .../RedisPushStreamResponseListener.java | 75 ++++++ .../RedisPushStreamStatusListMsgListener.java | 103 ++++++++ .../RedisPushStreamStatusMsgListener.java | 18 +- .../redisMsg/RedisStreamMsgListener.java | 91 ++++++++ .../iot/vmp/storager/dao/GbStreamMapper.java | 13 +- .../impl/VideoManagerStorageImpl.java | 6 +- src/main/resources/all-application.yml | 2 + 23 files changed, 789 insertions(+), 580 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamResponseListener.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusListMsgListener.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java create mode 100644 src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java rename src/main/java/com/genersoft/iot/vmp/service/{impl => redisMsg}/RedisGbPlayMsgListener.java (67%) rename src/main/java/com/genersoft/iot/vmp/service/{impl => redisMsg}/RedisGpsMsgListener.java (96%) create mode 100644 src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java create mode 100644 src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java rename src/main/java/com/genersoft/iot/vmp/service/{impl => redisMsg}/RedisPushStreamStatusMsgListener.java (82%) create mode 100644 src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java index 017b39db4..cad6e69de 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java @@ -31,6 +31,8 @@ public class UserSetting { private Boolean logInDatebase = Boolean.TRUE; + private Boolean usePushingAsStatus = Boolean.TRUE; + private String serverId = "000000"; private String thirdPartyGBIdReg = "[\\s\\S]*"; @@ -136,4 +138,12 @@ public class UserSetting { public void setPlatformPlayTimeout(int platformPlayTimeout) { this.platformPlayTimeout = platformPlayTimeout; } + + public Boolean isUsePushingAsStatus() { + return usePushingAsStatus; + } + + public void setUsePushingAsStatus(Boolean usePushingAsStatus) { + this.usePushingAsStatus = usePushingAsStatus; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java index 0b653cf57..e412f719c 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java @@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.conf.redis; import com.alibaba.fastjson.parser.ParserConfig; import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.service.impl.*; +import com.genersoft.iot.vmp.service.redisMsg.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java new file mode 100644 index 000000000..302539b6a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java @@ -0,0 +1,56 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +import org.dom4j.Element; + +import javax.sip.RequestEvent; + +public class SipMsgInfo { + private RequestEvent evt; + private Device device; + private ParentPlatform platform; + private Element rootElement; + + public SipMsgInfo(RequestEvent evt, Device device, Element rootElement) { + this.evt = evt; + this.device = device; + this.rootElement = rootElement; + } + + public SipMsgInfo(RequestEvent evt, ParentPlatform platform, Element rootElement) { + this.evt = evt; + this.platform = platform; + this.rootElement = rootElement; + } + + public RequestEvent getEvt() { + return evt; + } + + public void setEvt(RequestEvent evt) { + this.evt = evt; + } + + public Device getDevice() { + return device; + } + + public void setDevice(Device device) { + this.device = device; + } + + public ParentPlatform getPlatform() { + return platform; + } + + public void setPlatform(ParentPlatform platform) { + this.platform = platform; + } + + public Element getRootElement() { + return rootElement; + } + + public void setRootElement(Element rootElement) { + this.rootElement = rootElement; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index f8c3abfb6..33cc6e6d6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -14,18 +14,15 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; -import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener; +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.utils.SerializeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.sip.Dialog; -import javax.sip.DialogState; import javax.sip.RequestEvent; import javax.sip.address.SipURI; import javax.sip.header.CallIdHeader; 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 6ff5c0f7a..ff3c78f04 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 @@ -22,8 +22,8 @@ import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.SSRCInfo; -import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener; -import com.genersoft.iot.vmp.service.impl.RedisPushStreamResponseListener; +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; +import com.genersoft.iot.vmp.service.redisMsg.RedisPushStreamResponseListener; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java index add32d1b8..da2cb9c3e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java @@ -21,6 +21,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -31,6 +33,7 @@ import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; +import java.util.concurrent.ConcurrentLinkedQueue; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*; @@ -67,6 +70,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @Autowired private IDeviceChannelService deviceChannelService; + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + @Override public void afterPropertiesSet() throws Exception { notifyMessageHandler.addHandler(cmdType, this); @@ -75,114 +87,127 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @Override public void handForDevice(RequestEvent evt, Device device, Element rootElement) { logger.info("[收到报警通知]设备:{}", device.getDeviceId()); - // 回复200 OK - try { - responseAck(getServerTransaction(evt), Response.OK); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[收到报警通知], 回复200OK失败", e); - } - Element deviceIdElement = rootElement.element("DeviceID"); - String channelId = deviceIdElement.getText().toString(); + taskQueue.offer(new SipMsgInfo(evt, device, rootElement)); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + SipMsgInfo sipMsgInfo = taskQueue.poll(); + // 回复200 OK + try { + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[收到报警通知], 回复200OK失败", e); + } - DeviceAlarm deviceAlarm = new DeviceAlarm(); - deviceAlarm.setCreateTime(DateUtil.getNow()); - deviceAlarm.setDeviceId(device.getDeviceId()); - deviceAlarm.setChannelId(channelId); - deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority")); - deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod")); - String alarmTime = XmlUtil.getText(rootElement, "AlarmTime"); - if (alarmTime == null) { - return; - } - deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); - String alarmDescription = getText(rootElement, "AlarmDescription"); - if (alarmDescription == null) { - deviceAlarm.setAlarmDescription(""); - } else { - deviceAlarm.setAlarmDescription(alarmDescription); - } - String longitude = getText(rootElement, "Longitude"); - if (longitude != null && NumericUtil.isDouble(longitude)) { - deviceAlarm.setLongitude(Double.parseDouble(longitude)); - } else { - deviceAlarm.setLongitude(0.00); - } - String latitude = getText(rootElement, "Latitude"); - if (latitude != null && NumericUtil.isDouble(latitude)) { - deviceAlarm.setLatitude(Double.parseDouble(latitude)); - } else { - deviceAlarm.setLatitude(0.00); - } + Element deviceIdElement = sipMsgInfo.getRootElement().element("DeviceID"); + String channelId = deviceIdElement.getText().toString(); - if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) { - if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) { - MobilePosition mobilePosition = new MobilePosition(); - mobilePosition.setCreateTime(DateUtil.getNow()); - mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); - mobilePosition.setTime(deviceAlarm.getAlarmTime()); - mobilePosition.setLongitude(deviceAlarm.getLongitude()); - mobilePosition.setLatitude(deviceAlarm.getLatitude()); - mobilePosition.setReportSource("GPS Alarm"); + DeviceAlarm deviceAlarm = new DeviceAlarm(); + deviceAlarm.setCreateTime(DateUtil.getNow()); + deviceAlarm.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); + deviceAlarm.setChannelId(channelId); + deviceAlarm.setAlarmPriority(getText(sipMsgInfo.getRootElement(), "AlarmPriority")); + deviceAlarm.setAlarmMethod(getText(sipMsgInfo.getRootElement(), "AlarmMethod")); + String alarmTime = XmlUtil.getText(sipMsgInfo.getRootElement(), "AlarmTime"); + if (alarmTime == null) { + return; + } + deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); + String alarmDescription = getText(sipMsgInfo.getRootElement(), "AlarmDescription"); + if (alarmDescription == null) { + deviceAlarm.setAlarmDescription(""); + } else { + deviceAlarm.setAlarmDescription(alarmDescription); + } + String longitude = getText(sipMsgInfo.getRootElement(), "Longitude"); + if (longitude != null && NumericUtil.isDouble(longitude)) { + deviceAlarm.setLongitude(Double.parseDouble(longitude)); + } else { + deviceAlarm.setLongitude(0.00); + } + String latitude = getText(sipMsgInfo.getRootElement(), "Latitude"); + if (latitude != null && NumericUtil.isDouble(latitude)) { + deviceAlarm.setLatitude(Double.parseDouble(latitude)); + } else { + deviceAlarm.setLatitude(0.00); + } - // 更新device channel 的经纬度 - DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setDeviceId(device.getDeviceId()); - deviceChannel.setChannelId(channelId); - deviceChannel.setLongitude(mobilePosition.getLongitude()); - deviceChannel.setLatitude(mobilePosition.getLatitude()); - deviceChannel.setGpsTime(mobilePosition.getTime()); + if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) { + if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) { + MobilePosition mobilePosition = new MobilePosition(); + mobilePosition.setCreateTime(DateUtil.getNow()); + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); + mobilePosition.setTime(deviceAlarm.getAlarmTime()); + mobilePosition.setLongitude(deviceAlarm.getLongitude()); + mobilePosition.setLatitude(deviceAlarm.getLatitude()); + mobilePosition.setReportSource("GPS Alarm"); - deviceChannel = deviceChannelService.updateGps(deviceChannel, device); + // 更新device channel 的经纬度 + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); + deviceChannel.setChannelId(channelId); + deviceChannel.setLongitude(mobilePosition.getLongitude()); + deviceChannel.setLatitude(mobilePosition.getLatitude()); + deviceChannel.setGpsTime(mobilePosition.getTime()); - mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); - mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); - mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); - mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); + deviceChannel = deviceChannelService.updateGps(deviceChannel, sipMsgInfo.getDevice()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); + + if (userSetting.getSavePositionHistory()) { + storager.insertMobilePosition(mobilePosition); + } + storager.updateChannelPosition(deviceChannel); + + // 发送redis消息。 通知位置信息的变化 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("time", mobilePosition.getTime()); + jsonObject.put("serial", deviceChannel.getDeviceId()); + jsonObject.put("code", deviceChannel.getChannelId()); + jsonObject.put("longitude", mobilePosition.getLongitude()); + jsonObject.put("latitude", mobilePosition.getLatitude()); + jsonObject.put("altitude", mobilePosition.getAltitude()); + jsonObject.put("direction", mobilePosition.getDirection()); + jsonObject.put("speed", mobilePosition.getSpeed()); + redisCatchStorage.sendMobilePositionMsg(jsonObject); + } + } + if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) { + if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) { + deviceAlarm.setAlarmType(getText(sipMsgInfo.getRootElement().element("Info"), "AlarmType")); + } + } + + if ("7".equals(deviceAlarm.getAlarmMethod()) ) { + // 发送给平台的报警信息。 发送redis通知 + AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); + alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); + alarmChannelMessage.setGbId(channelId); + redisCatchStorage.sendAlarmMsg(alarmChannelMessage); + return; + } + + logger.debug("存储报警信息、报警分类"); + // 存储报警信息、报警分类 + if (sipConfig.isAlarm()) { + deviceAlarmService.add(deviceAlarm); + } + logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); + if (redisCatchStorage.deviceIsOnline(sipMsgInfo.getDevice().getDeviceId())) { + publisher.deviceAlarmEventPublish(deviceAlarm); + } } - storager.updateChannelPosition(deviceChannel); - - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", mobilePosition.getTime()); - jsonObject.put("serial", deviceChannel.getDeviceId()); - jsonObject.put("code", deviceChannel.getChannelId()); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); - } - } - if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) { - if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) { - deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType")); - } + taskQueueHandlerRun = false; + }); } - if ("7".equals(deviceAlarm.getAlarmMethod()) ) { - // 发送给平台的报警信息。 发送redis通知 - AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); - alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); - alarmChannelMessage.setGbId(channelId); - redisCatchStorage.sendAlarmMsg(alarmChannelMessage); - return; - } - logger.debug("存储报警信息、报警分类"); - // 存储报警信息、报警分类 - if (sipConfig.isAlarm()) { - deviceAlarmService.add(deviceAlarm); - } - logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) { - publisher.deviceAlarmEventPublish(deviceAlarm); - } } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java index b5051c0aa..67d26d771 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java @@ -17,6 +17,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -26,6 +28,7 @@ import javax.sip.RequestEvent; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; +import java.util.concurrent.ConcurrentLinkedQueue; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; @@ -53,6 +56,14 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen @Autowired private IDeviceChannelService deviceChannelService; + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + @Override public void afterPropertiesSet() throws Exception { notifyMessageHandler.addHandler(cmdType, this); @@ -61,78 +72,91 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen @Override public void handForDevice(RequestEvent evt, Device device, Element rootElement) { - try { - rootElement = getRootElement(evt, device.getCharset()); - if (rootElement == null) { - logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest()); - responseAck(getServerTransaction(evt), Response.BAD_REQUEST); - return; - } - MobilePosition mobilePosition = new MobilePosition(); - mobilePosition.setCreateTime(DateUtil.getNow()); - if (!ObjectUtils.isEmpty(device.getName())) { - mobilePosition.setDeviceName(device.getName()); - } - mobilePosition.setDeviceId(device.getDeviceId()); - mobilePosition.setChannelId(getText(rootElement, "DeviceID")); - mobilePosition.setTime(getText(rootElement, "Time")); - mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); - mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); - if (NumericUtil.isDouble(getText(rootElement, "Speed"))) { - mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed"))); - } else { - mobilePosition.setSpeed(0.0); - } - if (NumericUtil.isDouble(getText(rootElement, "Direction"))) { - mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction"))); - } else { - mobilePosition.setDirection(0.0); - } - if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) { - mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude"))); - } else { - mobilePosition.setAltitude(0.0); - } - mobilePosition.setReportSource("Mobile Position"); + taskQueue.offer(new SipMsgInfo(evt, device, rootElement)); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + SipMsgInfo sipMsgInfo = taskQueue.poll(); + try { + Element rootElementAfterCharset = getRootElement(sipMsgInfo.getEvt(), sipMsgInfo.getDevice().getCharset()); + if (rootElementAfterCharset == null) { + logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", sipMsgInfo.getEvt().getRequest()); + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.BAD_REQUEST); + return; + } + MobilePosition mobilePosition = new MobilePosition(); + mobilePosition.setCreateTime(DateUtil.getNow()); + if (!ObjectUtils.isEmpty(sipMsgInfo.getDevice().getName())) { + mobilePosition.setDeviceName(sipMsgInfo.getDevice().getName()); + } + mobilePosition.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); + mobilePosition.setChannelId(getText(rootElementAfterCharset, "DeviceID")); + mobilePosition.setTime(getText(rootElementAfterCharset, "Time")); + mobilePosition.setLongitude(Double.parseDouble(getText(rootElementAfterCharset, "Longitude"))); + mobilePosition.setLatitude(Double.parseDouble(getText(rootElementAfterCharset, "Latitude"))); + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Speed"))) { + mobilePosition.setSpeed(Double.parseDouble(getText(rootElementAfterCharset, "Speed"))); + } else { + mobilePosition.setSpeed(0.0); + } + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Direction"))) { + mobilePosition.setDirection(Double.parseDouble(getText(rootElementAfterCharset, "Direction"))); + } else { + mobilePosition.setDirection(0.0); + } + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Altitude"))) { + mobilePosition.setAltitude(Double.parseDouble(getText(rootElementAfterCharset, "Altitude"))); + } else { + mobilePosition.setAltitude(0.0); + } + mobilePosition.setReportSource("Mobile Position"); - // 更新device channel 的经纬度 - DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setDeviceId(device.getDeviceId()); - deviceChannel.setChannelId(mobilePosition.getChannelId()); - deviceChannel.setLongitude(mobilePosition.getLongitude()); - deviceChannel.setLatitude(mobilePosition.getLatitude()); - deviceChannel.setGpsTime(mobilePosition.getTime()); + // 更新device channel 的经纬度 + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); + deviceChannel.setChannelId(mobilePosition.getChannelId()); + deviceChannel.setLongitude(mobilePosition.getLongitude()); + deviceChannel.setLatitude(mobilePosition.getLatitude()); + deviceChannel.setGpsTime(mobilePosition.getTime()); - deviceChannel = deviceChannelService.updateGps(deviceChannel, device); + deviceChannel = deviceChannelService.updateGps(deviceChannel, sipMsgInfo.getDevice()); - mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); - mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); - mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); - mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); - } - storager.updateChannelPosition(deviceChannel); - //回复 200 OK - responseAck(getServerTransaction(evt), Response.OK); + if (userSetting.getSavePositionHistory()) { + storager.insertMobilePosition(mobilePosition); + } + storager.updateChannelPosition(deviceChannel); + //回复 200 OK + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK); - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", mobilePosition.getTime()); - jsonObject.put("serial", deviceChannel.getDeviceId()); - jsonObject.put("code", deviceChannel.getChannelId()); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); + // 发送redis消息。 通知位置信息的变化 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("time", mobilePosition.getTime()); + jsonObject.put("serial", deviceChannel.getDeviceId()); + jsonObject.put("code", deviceChannel.getChannelId()); + jsonObject.put("longitude", mobilePosition.getLongitude()); + jsonObject.put("latitude", mobilePosition.getLatitude()); + jsonObject.put("altitude", mobilePosition.getAltitude()); + jsonObject.put("direction", mobilePosition.getDirection()); + jsonObject.put("speed", mobilePosition.getSpeed()); + redisCatchStorage.sendMobilePositionMsg(jsonObject); - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { - e.printStackTrace(); + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + + } + taskQueueHandlerRun = false; + }); } + + } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java index dedc7c19f..3c5644b31 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.service.impl; import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; @@ -59,6 +60,9 @@ public class PlatformServiceImpl implements IPlatformService { @Autowired private GbStreamMapper gbStreamMapper; + @Autowired + private UserSetting userSetting; + @Override @@ -241,7 +245,7 @@ public class PlatformServiceImpl implements IPlatformService { if (subscribe != null) { // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 - List gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId()); + List gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId(), userSetting.isUsePushingAsStatus()); if (gbStreams.size() == 0) { return; } 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 c0b9e95bf..6662738cb 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 @@ -131,23 +131,6 @@ public class PlayServiceImpl implements IPlayService { StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); playResult.setDevice(device); - result.onCompletion(()->{ - // 点播结束时调用截图接口 - taskExecutor.execute(()->{ - // TODO 应该在上流时调用更好,结束也可能是错误结束 - String path = "snap"; - String fileName = deviceId + "_" + channelId + ".jpg"; - WVPResult wvpResult = (WVPResult)result.getResult(); - if (Objects.requireNonNull(wvpResult).getCode() == 0) { - StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); - MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); - String streamUrl = streamInfoForSuccess.getFmp4(); - // 请求截图 - logger.info("[请求截图]: " + fileName); - zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); - } - }); - }); if (streamInfo != null) { String streamId = streamInfo.getStream(); if (streamId == null) { @@ -209,6 +192,21 @@ public class PlayServiceImpl implements IPlayService { SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); logger.info(JSONObject.toJSONString(ssrcInfo)); play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{ + // 点播结束时调用截图接口 + taskExecutor.execute(()->{ + // TODO 应该在上流时调用更好,结束也可能是错误结束 + String path = "snap"; + String fileName = deviceId + "_" + channelId + ".jpg"; + WVPResult wvpResult = (WVPResult)result.getResult(); + if (Objects.requireNonNull(wvpResult).getCode() == 0) { + StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); + MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); + String streamUrl = streamInfoForSuccess.getFmp4(); + // 请求截图 + logger.info("[请求截图]: " + fileName); + zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); + } + }); if (hookEvent != null) { hookEvent.response(mediaServerItem, response); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java deleted file mode 100644 index 1634234a4..000000000 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.genersoft.iot.vmp.service.impl; - -import com.alibaba.fastjson.JSON; -import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; -import com.genersoft.iot.vmp.service.IPlatformChannelService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.utils.DateUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; - -import java.util.List; - - -@Component -public class RedisAlarmMsgListener implements MessageListener { - - private final static Logger logger = LoggerFactory.getLogger(RedisAlarmMsgListener.class); - - @Autowired - private ISIPCommander commander; - - @Autowired - private ISIPCommanderForPlatform commanderForPlatform; - - @Autowired - private IVideoManagerStorage storage; - - @Override - public void onMessage(Message message, byte[] bytes) { - logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); - AlarmChannelMessage alarmChannelMessage = JSON.parseObject(message.getBody(), AlarmChannelMessage.class); - if (alarmChannelMessage == null) { - logger.warn("[REDIS的ALARM通知]消息解析失败"); - return; - } - String gbId = alarmChannelMessage.getGbId(); - - DeviceAlarm deviceAlarm = new DeviceAlarm(); - deviceAlarm.setCreateTime(DateUtil.getNow()); - deviceAlarm.setChannelId(gbId); - deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); - deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); - deviceAlarm.setAlarmPriority("1"); - deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); - deviceAlarm.setAlarmType("1"); - deviceAlarm.setLongitude(0); - deviceAlarm.setLatitude(0); - - if (ObjectUtils.isEmpty(gbId)) { - // 发送给所有的上级 - List parentPlatforms = storage.queryEnableParentPlatformList(true); - if (parentPlatforms.size() > 0) { - for (ParentPlatform parentPlatform : parentPlatforms) { - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); - } - } - }else { - Device device = storage.queryVideoDevice(gbId); - ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); - if (device != null && platform == null) { - commander.sendAlarmMessage(device, deviceAlarm); - }else if (device == null && platform != null){ - commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); - }else { - logger.warn("无法确定" + gbId + "是平台还是设备"); - } - } - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamResponseListener.java deleted file mode 100644 index 56c9ff312..000000000 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamResponseListener.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.genersoft.iot.vmp.service.impl; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.media.zlm.dto.ChannelOnlineEvent; -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; -import com.genersoft.iot.vmp.service.IGbStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IStreamPushService; -import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse; -import com.genersoft.iot.vmp.utils.DateUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 接收redis返回的推流结果 - * @author lin - */ -@Component -public class RedisPushStreamResponseListener implements MessageListener { - - private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamResponseListener.class); - - private Map responseEvents = new ConcurrentHashMap<>(); - - public interface PushStreamResponseEvent{ - void run(MessageForPushChannelResponse response); - } - - @Override - public void onMessage(Message message, byte[] bytes) { - // - logger.warn("[REDIS消息-请求推流结果]: {}", new String(message.getBody())); - MessageForPushChannelResponse response = JSON.parseObject(new String(message.getBody()), MessageForPushChannelResponse.class); - if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){ - logger.info("[REDIS消息-请求推流结果]:参数不全"); - return; - } - // 查看正在等待的invite消息 - if (responseEvents.get(response.getApp() + response.getStream()) != null) { - responseEvents.get(response.getApp() + response.getStream()).run(response); - } - } - - public void addEvent(String app, String stream, PushStreamResponseEvent callback) { - responseEvents.put(app + stream, callback); - } - - public void removeEvent(String app, String stream) { - responseEvents.remove(app + stream); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusListMsgListener.java deleted file mode 100644 index bedbf4472..000000000 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusListMsgListener.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.genersoft.iot.vmp.service.impl; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; -import com.genersoft.iot.vmp.service.IGbStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IStreamPushService; -import com.genersoft.iot.vmp.utils.DateUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.*; - -/** - * @Auther: JiangFeng - * @Date: 2022/8/16 11:32 - * @Description: 接收redis发送的推流设备列表更新通知 - */ -@Component -public class RedisPushStreamStatusListMsgListener implements MessageListener { - - private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusListMsgListener.class); - @Resource - private IMediaServerService mediaServerService; - - @Resource - private IStreamPushService streamPushService; - @Resource - private IGbStreamService gbStreamService; - - @Override - public void onMessage(Message message, byte[] bytes) { - // - logger.warn("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody())); - List streamPushItems = JSON.parseArray(new String(message.getBody()), StreamPushItem.class); - //查询全部的app+stream 用于判断是添加还是修改 - List allAppAndStream = streamPushService.getAllAppAndStream(); - - /** - * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表 - */ - List streamPushItemForSave = new ArrayList<>(); - List streamPushItemForUpdate = new ArrayList<>(); - for (StreamPushItem streamPushItem : streamPushItems) { - String app = streamPushItem.getApp(); - String stream = streamPushItem.getStream(); - boolean contains = allAppAndStream.contains(app + stream); - //不存在就添加 - if (!contains) { - streamPushItem.setStreamType("push"); - streamPushItem.setCreateTime(DateUtil.getNow()); - streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); - streamPushItem.setOriginType(2); - streamPushItem.setOriginTypeStr("rtsp_push"); - streamPushItem.setTotalReaderCount("0"); - streamPushItemForSave.add(streamPushItem); - } else { - //存在就只修改 name和gbId - streamPushItemForUpdate.add(streamPushItem); - } - } - if (streamPushItemForSave.size() > 0) { - - logger.info("添加{}条",streamPushItemForSave.size()); - logger.info(JSONObject.toJSONString(streamPushItemForSave)); - streamPushService.batchAdd(streamPushItemForSave); - - } - if(streamPushItemForUpdate.size()>0){ - logger.info("修改{}条",streamPushItemForUpdate.size()); - logger.info(JSONObject.toJSONString(streamPushItemForUpdate)); - gbStreamService.updateGbIdOrName(streamPushItemForUpdate); - } - - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java deleted file mode 100644 index 118a2274f..000000000 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.genersoft.iot.vmp.service.impl; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.conf.UserSetting; - -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; -import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; -import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.connection.MessageListener; -import org.springframework.stereotype.Component; - - -/** - * 接收其他wvp发送流变化通知 - * @author lin - */ -@Component -public class RedisStreamMsgListener implements MessageListener { - - private final static Logger logger = LoggerFactory.getLogger(RedisStreamMsgListener.class); - - @Autowired - private UserSetting userSetting; - - @Autowired - private ZLMMediaListManager zlmMediaListManager; - - @Override - public void onMessage(Message message, byte[] bytes) { - - JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class); - if (steamMsgJson == null) { - logger.warn("[收到redis 流变化]消息解析失败"); - return; - } - String serverId = steamMsgJson.getString("serverId"); - - if (userSetting.getServerId().equals(serverId)) { - // 自己发送的消息忽略即可 - return; - } - logger.info("[收到redis 流变化]: {}", new String(message.getBody())); - String app = steamMsgJson.getString("app"); - String stream = steamMsgJson.getString("stream"); - boolean register = steamMsgJson.getBoolean("register"); - String mediaServerId = steamMsgJson.getString("mediaServerId"); - MediaItem mediaItem = new MediaItem(); - mediaItem.setSeverId(serverId); - mediaItem.setApp(app); - mediaItem.setStream(stream); - mediaItem.setRegist(register); - mediaItem.setMediaServerId(mediaServerId); - mediaItem.setCreateStamp(System.currentTimeMillis()/1000); - mediaItem.setAliveSecond(0L); - mediaItem.setTotalReaderCount("0"); - mediaItem.setOriginType(0); - mediaItem.setOriginTypeStr("0"); - mediaItem.setOriginTypeStr("unknown"); - if (register) { - zlmMediaListManager.addPush(mediaItem); - }else { - zlmMediaListManager.removeMedia(app, stream); - } - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java new file mode 100644 index 000000000..84f5ef71a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java @@ -0,0 +1,100 @@ +package com.genersoft.iot.vmp.service.redisMsg; + +import com.alibaba.fastjson.JSON; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; + + +@Component +public class RedisAlarmMsgListener implements MessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RedisAlarmMsgListener.class); + + @Autowired + private ISIPCommander commander; + + @Autowired + private ISIPCommanderForPlatform commanderForPlatform; + + @Autowired + private IVideoManagerStorage storage; + + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + @Override + public void onMessage(Message message, byte[] bytes) { + logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); + + taskQueue.offer(message); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + Message msg = taskQueue.poll(); + + AlarmChannelMessage alarmChannelMessage = JSON.parseObject(msg.getBody(), AlarmChannelMessage.class); + if (alarmChannelMessage == null) { + logger.warn("[REDIS的ALARM通知]消息解析失败"); + return; + } + String gbId = alarmChannelMessage.getGbId(); + + DeviceAlarm deviceAlarm = new DeviceAlarm(); + deviceAlarm.setCreateTime(DateUtil.getNow()); + deviceAlarm.setChannelId(gbId); + deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); + deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); + deviceAlarm.setAlarmPriority("1"); + deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); + deviceAlarm.setAlarmType("1"); + deviceAlarm.setLongitude(0); + deviceAlarm.setLatitude(0); + + if (ObjectUtils.isEmpty(gbId)) { + // 发送给所有的上级 + List parentPlatforms = storage.queryEnableParentPlatformList(true); + if (parentPlatforms.size() > 0) { + for (ParentPlatform parentPlatform : parentPlatforms) { + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); + } + } + }else { + Device device = storage.queryVideoDevice(gbId); + ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); + if (device != null && platform == null) { + commander.sendAlarmMessage(device, deviceAlarm); + }else if (device == null && platform != null){ + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); + }else { + logger.warn("无法确定" + gbId + "是平台还是设备"); + } + } + } + taskQueueHandlerRun = false; + }); + } + + + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java similarity index 67% rename from src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java rename to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java index e327d0f29..e6ba9b6b8 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -1,4 +1,4 @@ -package com.genersoft.iot.vmp.service.impl; +package com.genersoft.iot.vmp.service.redisMsg; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; @@ -19,8 +19,10 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import java.text.ParseException; @@ -28,6 +30,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; /** @@ -85,6 +88,14 @@ public class RedisGbPlayMsgListener implements MessageListener { @Autowired private ZlmHttpHookSubscribe subscribe; + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + public interface PlayMsgCallback{ void handler(ResponseSendItemMsg responseSendItemMsg) throws ParseException; @@ -100,94 +111,107 @@ public class RedisGbPlayMsgListener implements MessageListener { @Override public void onMessage(Message message, byte[] bytes) { - JSONObject msgJSON = JSON.parseObject(message.getBody(), JSONObject.class); - WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class); - if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { - return; - } - if (WvpRedisMsg.isRequest(wvpRedisMsg)) { - logger.info("[收到REDIS通知] 请求: {}", new String(message.getBody())); - switch (wvpRedisMsg.getCmd()){ - case WvpRedisMsgCmd.GET_SEND_ITEM: - RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class); - requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); - break; - case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: - RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);; - requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); - break; - default: - break; - } + taskQueue.offer(message); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + Message msg = taskQueue.poll(); + JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class); + WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class); + if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { + return; + } + if (WvpRedisMsg.isRequest(wvpRedisMsg)) { + logger.info("[收到REDIS通知] 请求: {}", new String(msg.getBody())); - }else { - logger.info("[收到REDIS通知] 回复: {}", new String(message.getBody())); - switch (wvpRedisMsg.getCmd()){ - case WvpRedisMsgCmd.GET_SEND_ITEM: + switch (wvpRedisMsg.getCmd()){ + case WvpRedisMsgCmd.GET_SEND_ITEM: + RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class); + requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); + break; + case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: + RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);; + requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); + break; + default: + break; + } - WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); + }else { + logger.info("[收到REDIS通知] 回复: {}", new String(msg.getBody())); + switch (wvpRedisMsg.getCmd()){ + case WvpRedisMsgCmd.GET_SEND_ITEM: - String key = wvpRedisMsg.getSerial(); - switch (content.getCode()) { - case 0: - ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class); - PlayMsgCallback playMsgCallback = callbacks.get(key); - if (playMsgCallback != null) { - callbacksForError.remove(key); - try { - playMsgCallback.handler(responseSendItemMsg); - } catch (ParseException e) { - throw new RuntimeException(e); + WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); + + String key = wvpRedisMsg.getSerial(); + switch (content.getCode()) { + case 0: + ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class); + PlayMsgCallback playMsgCallback = callbacks.get(key); + if (playMsgCallback != null) { + callbacksForError.remove(key); + try { + playMsgCallback.handler(responseSendItemMsg); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + break; + case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: + case ERROR_CODE_OFFLINE: + case ERROR_CODE_TIMEOUT: + PlayMsgErrorCallback errorCallback = callbacksForError.get(key); + if (errorCallback != null) { + callbacks.remove(key); + errorCallback.handler(content); + } + break; + default: + break; } - } - break; - case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: - case ERROR_CODE_OFFLINE: - case ERROR_CODE_TIMEOUT: - PlayMsgErrorCallback errorCallback = callbacksForError.get(key); - if (errorCallback != null) { - callbacks.remove(key); - errorCallback.handler(content); - } - break; - default: - break; + break; + case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: + WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); + String serial = wvpRedisMsg.getSerial(); + switch (wvpResult.getCode()) { + case 0: + JSONObject jsonObject = (JSONObject)wvpResult.getData(); + PlayMsgCallbackForStartSendRtpStream playMsgCallback = callbacksForStartSendRtpStream.get(serial); + if (playMsgCallback != null) { + callbacksForError.remove(serial); + playMsgCallback.handler(jsonObject); + } + break; + case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: + case ERROR_CODE_OFFLINE: + case ERROR_CODE_TIMEOUT: + PlayMsgErrorCallback errorCallback = callbacksForError.get(serial); + if (errorCallback != null) { + callbacks.remove(serial); + errorCallback.handler(wvpResult); + } + break; + default: + break; + } + break; + default: + break; + } } - break; - case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: - WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); - String serial = wvpRedisMsg.getSerial(); - switch (wvpResult.getCode()) { - case 0: - JSONObject jsonObject = (JSONObject)wvpResult.getData(); - PlayMsgCallbackForStartSendRtpStream playMsgCallback = callbacksForStartSendRtpStream.get(serial); - if (playMsgCallback != null) { - callbacksForError.remove(serial); - playMsgCallback.handler(jsonObject); - } - break; - case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: - case ERROR_CODE_OFFLINE: - case ERROR_CODE_TIMEOUT: - PlayMsgErrorCallback errorCallback = callbacksForError.get(serial); - if (errorCallback != null) { - callbacks.remove(serial); - errorCallback.handler(wvpResult); - } - break; - default: - break; - } - break; - default: - break; - } + } + taskQueueHandlerRun = false; + }); } + + } /** diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java similarity index 96% rename from src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java rename to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java index 4e94d68ad..bb2f4ad56 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java @@ -1,7 +1,6 @@ -package com.genersoft.iot.vmp.service.impl; +package com.genersoft.iot.vmp.service.redisMsg; import com.alibaba.fastjson.JSON; -import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java new file mode 100644 index 000000000..13e68740b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java @@ -0,0 +1,75 @@ +package com.genersoft.iot.vmp.service.redisMsg; + +import com.alibaba.fastjson.JSON; +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; +import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * 接收redis返回的推流结果 + * @author lin + */ +@Component +public class RedisPushStreamResponseListener implements MessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamResponseListener.class); + + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + + private Map responseEvents = new ConcurrentHashMap<>(); + + public interface PushStreamResponseEvent{ + void run(MessageForPushChannelResponse response); + } + + @Override + public void onMessage(Message message, byte[] bytes) { + logger.warn("[REDIS消息-请求推流结果]: {}", new String(message.getBody())); + taskQueue.offer(message); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + Message msg = taskQueue.poll(); + MessageForPushChannelResponse response = JSON.parseObject(new String(msg.getBody()), MessageForPushChannelResponse.class); + if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){ + logger.info("[REDIS消息-请求推流结果]:参数不全"); + return; + } + // 查看正在等待的invite消息 + if (responseEvents.get(response.getApp() + response.getStream()) != null) { + responseEvents.get(response.getApp() + response.getStream()).run(response); + } + } + taskQueueHandlerRun = false; + }); + } + } + + public void addEvent(String app, String stream, PushStreamResponseEvent callback) { + responseEvents.put(app + stream, callback); + } + + public void removeEvent(String app, String stream) { + responseEvents.remove(app + stream); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java new file mode 100644 index 000000000..392583647 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java @@ -0,0 +1,103 @@ +package com.genersoft.iot.vmp.service.redisMsg; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.service.IGbStreamService; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.service.IStreamPushService; +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; +import com.genersoft.iot.vmp.utils.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * @Auther: JiangFeng + * @Date: 2022/8/16 11:32 + * @Description: 接收redis发送的推流设备列表更新通知 + */ +@Component +public class RedisPushStreamStatusListMsgListener implements MessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusListMsgListener.class); + @Resource + private IMediaServerService mediaServerService; + + @Resource + private IStreamPushService streamPushService; + @Resource + private IGbStreamService gbStreamService; + + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + @Override + public void onMessage(Message message, byte[] bytes) { + logger.info("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody())); + + taskQueue.offer(message); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + Message msg = taskQueue.poll(); + List streamPushItems = JSON.parseArray(new String(msg.getBody()), StreamPushItem.class); + //查询全部的app+stream 用于判断是添加还是修改 + List allAppAndStream = streamPushService.getAllAppAndStream(); + + /** + * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表 + */ + List streamPushItemForSave = new ArrayList<>(); + List streamPushItemForUpdate = new ArrayList<>(); + for (StreamPushItem streamPushItem : streamPushItems) { + String app = streamPushItem.getApp(); + String stream = streamPushItem.getStream(); + boolean contains = allAppAndStream.contains(app + stream); + //不存在就添加 + if (!contains) { + streamPushItem.setStreamType("push"); + streamPushItem.setCreateTime(DateUtil.getNow()); + streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); + streamPushItem.setOriginType(2); + streamPushItem.setOriginTypeStr("rtsp_push"); + streamPushItem.setTotalReaderCount("0"); + streamPushItemForSave.add(streamPushItem); + } else { + //存在就只修改 name和gbId + streamPushItemForUpdate.add(streamPushItem); + } + } + if (streamPushItemForSave.size() > 0) { + + logger.info("添加{}条",streamPushItemForSave.size()); + logger.info(JSONObject.toJSONString(streamPushItemForSave)); + streamPushService.batchAdd(streamPushItemForSave); + + } + if(streamPushItemForUpdate.size()>0){ + logger.info("修改{}条",streamPushItemForUpdate.size()); + logger.info(JSONObject.toJSONString(streamPushItemForUpdate)); + gbStreamService.updateGbIdOrName(streamPushItemForUpdate); + } + } + taskQueueHandlerRun = false; + }); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java similarity index 82% rename from src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java rename to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java index 50e894a62..4b1c2d503 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java @@ -1,24 +1,11 @@ -package com.genersoft.iot.vmp.service.impl; +package com.genersoft.iot.vmp.service.redisMsg; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.DynamicTask; -import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.GbStream; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; -import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; -import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.service.IStreamPushService; -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto; -import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -30,8 +17,6 @@ import org.springframework.data.redis.connection.MessageListener; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; @@ -65,7 +50,6 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic @Override public void onMessage(Message message, byte[] bytes) { - // TODO 增加队列 logger.warn("[REDIS消息-推流设备状态变化]: {}", new String(message.getBody())); taskQueue.offer(message); diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java new file mode 100644 index 000000000..1897b6fce --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java @@ -0,0 +1,91 @@ +package com.genersoft.iot.vmp.service.redisMsg; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.conf.UserSetting; + +import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; +import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; + +import java.util.concurrent.ConcurrentLinkedQueue; + + +/** + * 接收其他wvp发送流变化通知 + * @author lin + */ +@Component +public class RedisStreamMsgListener implements MessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RedisStreamMsgListener.class); + + @Autowired + private UserSetting userSetting; + + @Autowired + private ZLMMediaListManager zlmMediaListManager; + + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + @Override + public void onMessage(Message message, byte[] bytes) { + + taskQueue.offer(message); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(() -> { + while (!taskQueue.isEmpty()) { + Message msg = taskQueue.poll(); + JSONObject steamMsgJson = JSON.parseObject(msg.getBody(), JSONObject.class); + if (steamMsgJson == null) { + logger.warn("[收到redis 流变化]消息解析失败"); + return; + } + String serverId = steamMsgJson.getString("serverId"); + + if (userSetting.getServerId().equals(serverId)) { + // 自己发送的消息忽略即可 + return; + } + logger.info("[收到redis 流变化]: {}", new String(message.getBody())); + String app = steamMsgJson.getString("app"); + String stream = steamMsgJson.getString("stream"); + boolean register = steamMsgJson.getBoolean("register"); + String mediaServerId = steamMsgJson.getString("mediaServerId"); + MediaItem mediaItem = new MediaItem(); + mediaItem.setSeverId(serverId); + mediaItem.setApp(app); + mediaItem.setStream(stream); + mediaItem.setRegist(register); + mediaItem.setMediaServerId(mediaServerId); + mediaItem.setCreateStamp(System.currentTimeMillis()/1000); + mediaItem.setAliveSecond(0L); + mediaItem.setTotalReaderCount("0"); + mediaItem.setOriginType(0); + mediaItem.setOriginTypeStr("0"); + mediaItem.setOriginTypeStr("unknown"); + if (register) { + zlmMediaListManager.addPush(mediaItem); + }else { + zlmMediaListManager.removeMedia(app, stream); + } + } + taskQueueHandlerRun = false; + }); + } + } +} 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 5e74d99ea..8a5d4550c 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 @@ -75,18 +75,23 @@ public interface GbStreamMapper { "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'") GbStream queryStreamInPlatform(String platformId, String gbId); - @Select("select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," + + @Select("") + List queryGbStreamListInPlatform(String platformId, boolean usPushingAsStatus); @Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " + diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java index 702b5bed4..f8a74fef9 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.impl; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; @@ -83,6 +84,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @Autowired private GbStreamMapper gbStreamMapper; + @Autowired + private UserSetting userSetting; + @Autowired private PlatformCatalogMapper catalogMapper; @@ -614,7 +618,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { */ @Override public List queryGbStreamListInPlatform(String platformId) { - return gbStreamMapper.queryGbStreamListInPlatform(platformId); + return gbStreamMapper.queryGbStreamListInPlatform(platformId, userSetting.isUsePushingAsStatus()); } /** diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 3569de2ea..ed025b9a8 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -188,6 +188,8 @@ user-settings: record-sip: true # 是否将日志存储进数据库 logInDatebase: true + # 使用推流状态作为推流通道状态 + use-pushing-as-status: true # 关闭在线文档(生产环境建议关闭) springdoc: From 1abfced3b459a9ec99fd0e9f606dc1133e5f3ef6 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 22 Sep 2022 11:32:01 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=82=B9=E6=92=AD?= =?UTF-8?q?=E5=90=8Ebye=E4=BF=A1=E6=81=AF=E7=9A=84=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 0368ee4ac..d08201f8a 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 @@ -26,6 +26,7 @@ import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.stack.SIPClientTransaction; import gov.nist.javax.sip.stack.SIPDialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -433,7 +434,14 @@ public class SIPCommander implements ISIPCommander { }), e ->{ // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 streamSession.put(device.getDeviceId(), channelId ,"play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play); - streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog); + Dialog sipDialog = null; + if (e.dialog == null) { + SIPClientTransaction clientTransaction = (SIPClientTransaction)((ResponseEvent)e.event).getClientTransaction(); + sipDialog = new SIPDialog(clientTransaction, clientTransaction.getLastResponse()); + }else { + sipDialog = e.dialog; + } + streamSession.put(device.getDeviceId(), channelId ,"play", sipDialog); okEvent.response(e); }); From 70c20364af15fce16992fce499efc623823ce221 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 22 Sep 2022 14:10:26 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B5=81=E6=B3=A8?= =?UTF-8?q?=E9=94=80=E6=97=B6=E7=A7=BB=E9=99=A4=E6=B5=81=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/gb28181/bean/SipTransactionInfo.java | 53 +++++++++++++++++++ .../vmp/media/zlm/ZLMHttpHookListener.java | 17 +++--- 2 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java new file mode 100644 index 000000000..c68be129e --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java @@ -0,0 +1,53 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +import gov.nist.javax.sip.message.SIPRequest; + +public class SipTransactionInfo { + + private String callId; + private String fromTag; + private String toTag; + private String viaBranch; + + public SipTransactionInfo(SIPRequest request) { + this.callId = request.getCallIdHeader().getCallId(); + this.fromTag = request.getFromTag(); + this.toTag = request.getToTag(); + this.viaBranch = request.getTopmostViaHeader().getBranch(); + } + + public SipTransactionInfo() { + } + + public String getCallId() { + return callId; + } + + public void setCallId(String callId) { + this.callId = callId; + } + + public String getFromTag() { + return fromTag; + } + + public void setFromTag(String fromTag) { + this.fromTag = fromTag; + } + + public String getToTag() { + return toTag; + } + + public void setToTag(String toTag) { + this.toTag = toTag; + } + + public String getViaBranch() { + return viaBranch; + } + + public void setViaBranch(String viaBranch) { + this.viaBranch = viaBranch; + } +} 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 f645b8a8b..cbecf0fed 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 @@ -417,10 +417,11 @@ public class ZLMHttpHookListener { String schema = item.getSchema(); List tracks = item.getTracks(); boolean regist = item.isRegist(); - if (item.getOriginType() == OriginType.RTMP_PUSH.ordinal() - || item.getOriginType() == OriginType.RTSP_PUSH.ordinal() - || item.getOriginType() == OriginType.RTC_PUSH.ordinal()) { - if (regist) { + if (regist) { + if (item.getOriginType() == OriginType.RTMP_PUSH.ordinal() + || item.getOriginType() == OriginType.RTSP_PUSH.ordinal() + || item.getOriginType() == OriginType.RTC_PUSH.ordinal()) { + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); if (streamAuthorityInfo == null) { streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item); @@ -429,9 +430,9 @@ public class ZLMHttpHookListener { streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr()); } redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo); - }else { - redisCatchStorage.removeStreamAuthorityInfo(app, stream); } + }else { + redisCatchStorage.removeStreamAuthorityInfo(app, stream); } if ("rtsp".equals(schema)){ @@ -451,16 +452,12 @@ public class ZLMHttpHookListener { if (streamInfo!=null){ redisCatchStorage.stopPlay(streamInfo); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - // 如果正在给上级推送,则发送bye - - }else{ streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null); if (streamInfo != null) { redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream(), null); } - // 如果正在给上级推送,则发送bye } }else { if (!"rtp".equals(app)){ From a574ff094428decbdc35332d184cd0d210716a44 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 22 Sep 2022 16:56:20 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=98=9F=E5=88=97=E5=AF=BC=E8=87=B4=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/NotifyRequestProcessor.java | 2 +- .../notify/cmd/AlarmNotifyMessageHandler.java | 13 ++++---- .../MobilePositionNotifyMessageHandler.java | 4 +-- .../iot/vmp/service/impl/PlayServiceImpl.java | 33 ++++++++++--------- .../redisMsg/RedisAlarmMsgListener.java | 8 +++-- .../redisMsg/RedisGbPlayMsgListener.java | 4 +-- .../service/redisMsg/RedisGpsMsgListener.java | 2 +- .../RedisPushStreamResponseListener.java | 4 +-- .../RedisPushStreamStatusListMsgListener.java | 2 +- .../RedisPushStreamStatusMsgListener.java | 4 +-- .../redisMsg/RedisStreamMsgListener.java | 6 ++-- 11 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java index 206a1599d..84bf0b8c4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java @@ -79,7 +79,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java index da2cb9c3e..ec750152a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java @@ -72,7 +72,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -92,13 +92,14 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme if (!taskQueueHandlerRun) { taskQueueHandlerRun = true; taskExecutor.execute(() -> { + logger.info("[处理报警通知]待处理数量:{}", taskQueue.size() ); while (!taskQueue.isEmpty()) { SipMsgInfo sipMsgInfo = taskQueue.poll(); // 回复200 OK try { responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK); } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[收到报警通知], 回复200OK失败", e); + logger.error("[处理报警通知], 回复200OK失败", e); } Element deviceIdElement = sipMsgInfo.getRootElement().element("DeviceID"); @@ -112,7 +113,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme deviceAlarm.setAlarmMethod(getText(sipMsgInfo.getRootElement(), "AlarmMethod")); String alarmTime = XmlUtil.getText(sipMsgInfo.getRootElement(), "AlarmTime"); if (alarmTime == null) { - return; + continue; } deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); String alarmDescription = getText(sipMsgInfo.getRootElement(), "AlarmDescription"); @@ -182,7 +183,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme deviceAlarm.setAlarmType(getText(sipMsgInfo.getRootElement().element("Info"), "AlarmType")); } } - + logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); if ("7".equals(deviceAlarm.getAlarmMethod()) ) { // 发送给平台的报警信息。 发送redis通知 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); @@ -190,7 +191,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); alarmChannelMessage.setGbId(channelId); redisCatchStorage.sendAlarmMsg(alarmChannelMessage); - return; + continue; } logger.debug("存储报警信息、报警分类"); @@ -198,7 +199,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme if (sipConfig.isAlarm()) { deviceAlarmService.add(deviceAlarm); } - logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); + if (redisCatchStorage.deviceIsOnline(sipMsgInfo.getDevice().getDeviceId())) { publisher.deviceAlarmEventPublish(deviceAlarm); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java index 67d26d771..652cd830b 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java @@ -58,7 +58,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -83,7 +83,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen if (rootElementAfterCharset == null) { logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", sipMsgInfo.getEvt().getRequest()); responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.BAD_REQUEST); - return; + continue; } MobilePosition mobilePosition = new MobilePosition(); mobilePosition.setCreateTime(DateUtil.getNow()); 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 6662738cb..cdbbf3325 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 @@ -131,6 +131,24 @@ public class PlayServiceImpl implements IPlayService { StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); playResult.setDevice(device); + result.onCompletion(()->{ + // 点播结束时调用截图接口 + taskExecutor.execute(()->{ + // TODO 应该在上流时调用更好,结束也可能是错误结束 + String path = "snap"; + String fileName = deviceId + "_" + channelId + ".jpg"; + WVPResult wvpResult = (WVPResult)result.getResult(); + if (Objects.requireNonNull(wvpResult).getCode() == 0) { + StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); + MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); + String streamUrl = streamInfoForSuccess.getFmp4(); + // 请求截图 + logger.info("[请求截图]: " + fileName); + zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); + } + }); + }); + if (streamInfo != null) { String streamId = streamInfo.getStream(); if (streamId == null) { @@ -192,21 +210,6 @@ public class PlayServiceImpl implements IPlayService { SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); logger.info(JSONObject.toJSONString(ssrcInfo)); play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{ - // 点播结束时调用截图接口 - taskExecutor.execute(()->{ - // TODO 应该在上流时调用更好,结束也可能是错误结束 - String path = "snap"; - String fileName = deviceId + "_" + channelId + ".jpg"; - WVPResult wvpResult = (WVPResult)result.getResult(); - if (Objects.requireNonNull(wvpResult).getCode() == 0) { - StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); - MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); - String streamUrl = streamInfoForSuccess.getFmp4(); - // 请求截图 - logger.info("[请求截图]: " + fileName); - zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); - } - }); if (hookEvent != null) { hookEvent.response(mediaServerItem, response); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java index 84f5ef71a..8d1b066ef 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java @@ -16,6 +16,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; +import javax.validation.constraints.NotNull; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; @@ -36,19 +37,20 @@ public class RedisAlarmMsgListener implements MessageListener { private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired private ThreadPoolTaskExecutor taskExecutor; @Override - public void onMessage(Message message, byte[] bytes) { + public void onMessage(@NotNull Message message, byte[] bytes) { logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); taskQueue.offer(message); if (!taskQueueHandlerRun) { taskQueueHandlerRun = true; + logger.info("[线程池信息]活动线程数:{}, 最大线程数: {}", taskExecutor.getActiveCount(), taskExecutor.getMaxPoolSize()); taskExecutor.execute(() -> { while (!taskQueue.isEmpty()) { Message msg = taskQueue.poll(); @@ -56,7 +58,7 @@ public class RedisAlarmMsgListener implements MessageListener { AlarmChannelMessage alarmChannelMessage = JSON.parseObject(msg.getBody(), AlarmChannelMessage.class); if (alarmChannelMessage == null) { logger.warn("[REDIS的ALARM通知]消息解析失败"); - return; + continue; } String gbId = alarmChannelMessage.getGbId(); diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java index e6ba9b6b8..2d4a82fb6 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -90,7 +90,7 @@ public class RedisGbPlayMsgListener implements MessageListener { private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -121,7 +121,7 @@ public class RedisGbPlayMsgListener implements MessageListener { JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class); WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class); if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { - return; + continue; } if (WvpRedisMsg.isRequest(wvpRedisMsg)) { logger.info("[收到REDIS通知] 请求: {}", new String(msg.getBody())); diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java index bb2f4ad56..b5d02a5c0 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java @@ -35,7 +35,7 @@ public class RedisGpsMsgListener implements MessageListener { @Autowired private IVideoManagerStorage storager; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java index 13e68740b..4fff32d92 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java @@ -28,7 +28,7 @@ public class RedisPushStreamResponseListener implements MessageListener { private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -53,7 +53,7 @@ public class RedisPushStreamResponseListener implements MessageListener { MessageForPushChannelResponse response = JSON.parseObject(new String(msg.getBody()), MessageForPushChannelResponse.class); if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){ logger.info("[REDIS消息-请求推流结果]:参数不全"); - return; + continue; } // 查看正在等待的invite消息 if (responseEvents.get(response.getApp() + response.getStream()) != null) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java index 392583647..b69a587aa 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java @@ -40,7 +40,7 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java index 4b1c2d503..2faf3b8af 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java @@ -42,7 +42,7 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -61,7 +61,7 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(msg.getBody(), PushStreamStatusChangeFromRedisDto.class); if (statusChangeFromPushStream == null) { logger.warn("[REDIS消息]推流设备状态变化消息解析失败"); - return; + continue; } // 取消定时任务 dynamicTask.stop(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED); diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java index 1897b6fce..415787e77 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java @@ -35,7 +35,7 @@ public class RedisStreamMsgListener implements MessageListener { private boolean taskQueueHandlerRun = false; - private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -53,13 +53,13 @@ public class RedisStreamMsgListener implements MessageListener { JSONObject steamMsgJson = JSON.parseObject(msg.getBody(), JSONObject.class); if (steamMsgJson == null) { logger.warn("[收到redis 流变化]消息解析失败"); - return; + continue; } String serverId = steamMsgJson.getString("serverId"); if (userSetting.getServerId().equals(serverId)) { // 自己发送的消息忽略即可 - return; + continue; } logger.info("[收到redis 流变化]: {}", new String(message.getBody())); String app = steamMsgJson.getString("app");