Commit 19a52a20f358b22211dde9da9d25b65c9cbaddcf
1 parent
acac24f0
固定时区为Asia/Shanghai
Showing
5 changed files
with
117 additions
and
40 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
| @@ -104,6 +104,14 @@ public interface ISIPCommanderForPlatform { | @@ -104,6 +104,14 @@ public interface ISIPCommanderForPlatform { | ||
| 104 | boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo); | 104 | boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo); |
| 105 | 105 | ||
| 106 | /** | 106 | /** |
| 107 | + * 录像播放推送完成时发送MediaStatus消息 | ||
| 108 | + * @param platform | ||
| 109 | + * @param sendRtpItem | ||
| 110 | + * @return | ||
| 111 | + */ | ||
| 112 | + boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem); | ||
| 113 | + | ||
| 114 | + /** | ||
| 107 | * 向发起点播的上级回复bye | 115 | * 向发起点播的上级回复bye |
| 108 | * @param platform 平台信息 | 116 | * @param platform 平台信息 |
| 109 | * @param callId callId | 117 | * @param callId callId |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| @@ -746,6 +746,56 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -746,6 +746,56 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 746 | } | 746 | } |
| 747 | 747 | ||
| 748 | @Override | 748 | @Override |
| 749 | + public boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) { | ||
| 750 | + if (sendRtpItem == null) { | ||
| 751 | + return false; | ||
| 752 | + } | ||
| 753 | + if (platform == null) { | ||
| 754 | + return false; | ||
| 755 | + } | ||
| 756 | + | ||
| 757 | + byte[] dialogByteArray = sendRtpItem.getDialog(); | ||
| 758 | + if (dialogByteArray == null) { | ||
| 759 | + return false; | ||
| 760 | + } | ||
| 761 | + try{ | ||
| 762 | + SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray); | ||
| 763 | + SIPRequest messageRequest = (SIPRequest)dialog.createRequest(Request.MESSAGE); | ||
| 764 | + String characterSet = platform.getCharacterSet(); | ||
| 765 | + StringBuffer mediaStatusXml = new StringBuffer(200); | ||
| 766 | + mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); | ||
| 767 | + mediaStatusXml.append("<Notify>\r\n"); | ||
| 768 | + mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n"); | ||
| 769 | + mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | ||
| 770 | + mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n"); | ||
| 771 | + mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n"); | ||
| 772 | + mediaStatusXml.append("</Notify>\r\n"); | ||
| 773 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | ||
| 774 | + messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader); | ||
| 775 | + SipURI sipURI = (SipURI) messageRequest.getRequestURI(); | ||
| 776 | + sipURI.setHost(platform.getServerIP()); | ||
| 777 | + sipURI.setPort(platform.getServerPort()); | ||
| 778 | + | ||
| 779 | + ClientTransaction transaction = null; | ||
| 780 | + if ("TCP".equals(platform.getTransport())) { | ||
| 781 | + transaction = tcpSipProvider.getNewClientTransaction(messageRequest); | ||
| 782 | + } else if ("UDP".equals(platform.getTransport())) { | ||
| 783 | + transaction = udpSipProvider.getNewClientTransaction(messageRequest); | ||
| 784 | + } | ||
| 785 | + transaction.sendRequest(); | ||
| 786 | + } catch (SipException e) { | ||
| 787 | + e.printStackTrace(); | ||
| 788 | + return false; | ||
| 789 | + } catch (ParseException e) { | ||
| 790 | + e.printStackTrace(); | ||
| 791 | + return false; | ||
| 792 | + } | ||
| 793 | + return true; | ||
| 794 | + | ||
| 795 | + | ||
| 796 | + } | ||
| 797 | + | ||
| 798 | + @Override | ||
| 749 | public void streamByeCmd(ParentPlatform platform, String callId) { | 799 | public void streamByeCmd(ParentPlatform platform, String callId) { |
| 750 | if (platform == null) { | 800 | if (platform == null) { |
| 751 | return; | 801 | return; |
| @@ -765,41 +815,40 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -765,41 +815,40 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 765 | SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog); | 815 | SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog); |
| 766 | if (dialog != sipDialog) { | 816 | if (dialog != sipDialog) { |
| 767 | dialog = sipDialog; | 817 | dialog = sipDialog; |
| 768 | - } else { | ||
| 769 | - try { | ||
| 770 | - dialog.setSipProvider(udpSipProvider); | ||
| 771 | - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack"); | ||
| 772 | - sipStackField.setAccessible(true); | ||
| 773 | - sipStackField.set(dialog, sipStack); | ||
| 774 | - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners"); | ||
| 775 | - eventListenersField.setAccessible(true); | ||
| 776 | - eventListenersField.set(dialog, new HashSet<>()); | ||
| 777 | - | ||
| 778 | - byte[] transactionByteArray = sendRtpItem.getTransaction(); | ||
| 779 | - ClientTransaction clientTransaction = (ClientTransaction) SerializeUtils.deSerialize(transactionByteArray); | ||
| 780 | - Request byeRequest = dialog.createRequest(Request.BYE); | ||
| 781 | - | ||
| 782 | - SipURI byeURI = (SipURI) byeRequest.getRequestURI(); | ||
| 783 | - SIPRequest request = (SIPRequest) clientTransaction.getRequest(); | ||
| 784 | - byeURI.setHost(request.getRemoteAddress().getHostAddress()); | ||
| 785 | - byeURI.setPort(request.getRemotePort()); | ||
| 786 | - if ("TCP".equals(platform.getTransport())) { | ||
| 787 | - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); | ||
| 788 | - } else if ("UDP".equals(platform.getTransport())) { | ||
| 789 | - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); | ||
| 790 | - } | ||
| 791 | - dialog.sendRequest(clientTransaction); | ||
| 792 | - } catch (SipException e) { | ||
| 793 | - e.printStackTrace(); | ||
| 794 | - } catch (ParseException e) { | ||
| 795 | - e.printStackTrace(); | ||
| 796 | - } catch (NoSuchFieldException e) { | ||
| 797 | - e.printStackTrace(); | ||
| 798 | - } catch (IllegalAccessException e) { | ||
| 799 | - e.printStackTrace(); | 818 | + } |
| 819 | + try { | ||
| 820 | + dialog.setSipProvider(udpSipProvider); | ||
| 821 | + Field sipStackField = SIPDialog.class.getDeclaredField("sipStack"); | ||
| 822 | + sipStackField.setAccessible(true); | ||
| 823 | + sipStackField.set(dialog, sipStack); | ||
| 824 | + Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners"); | ||
| 825 | + eventListenersField.setAccessible(true); | ||
| 826 | + eventListenersField.set(dialog, new HashSet<>()); | ||
| 827 | + | ||
| 828 | + byte[] transactionByteArray = sendRtpItem.getTransaction(); | ||
| 829 | + ClientTransaction clientTransaction = (ClientTransaction) SerializeUtils.deSerialize(transactionByteArray); | ||
| 830 | + Request byeRequest = dialog.createRequest(Request.BYE); | ||
| 831 | + | ||
| 832 | + SipURI byeURI = (SipURI) byeRequest.getRequestURI(); | ||
| 833 | + SIPRequest request = (SIPRequest) clientTransaction.getRequest(); | ||
| 834 | + byeURI.setHost(request.getRemoteAddress().getHostAddress()); | ||
| 835 | + byeURI.setPort(request.getRemotePort()); | ||
| 836 | + if ("TCP".equals(platform.getTransport())) { | ||
| 837 | + clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); | ||
| 838 | + } else if ("UDP".equals(platform.getTransport())) { | ||
| 839 | + clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); | ||
| 800 | } | 840 | } |
| 801 | - | 841 | + dialog.sendRequest(clientTransaction); |
| 842 | + } catch (SipException e) { | ||
| 843 | + e.printStackTrace(); | ||
| 844 | + } catch (ParseException e) { | ||
| 845 | + e.printStackTrace(); | ||
| 846 | + } catch (NoSuchFieldException e) { | ||
| 847 | + e.printStackTrace(); | ||
| 848 | + } catch (IllegalAccessException e) { | ||
| 849 | + e.printStackTrace(); | ||
| 802 | } | 850 | } |
| 851 | + | ||
| 803 | } | 852 | } |
| 804 | } | 853 | } |
| 805 | } | 854 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| @@ -188,8 +188,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -188,8 +188,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 188 | startTime = startTimeFiled.getStartTime(); | 188 | startTime = startTimeFiled.getStartTime(); |
| 189 | stopTime = startTimeFiled.getStopTime(); | 189 | stopTime = startTimeFiled.getStopTime(); |
| 190 | 190 | ||
| 191 | - start = Instant.ofEpochMilli(startTime*1000); | ||
| 192 | - end = Instant.ofEpochMilli(stopTime*1000); | 191 | + start = Instant.ofEpochSecond(startTime); |
| 192 | + end = Instant.ofEpochSecond(stopTime); | ||
| 193 | } | 193 | } |
| 194 | // 获取支持的格式 | 194 | // 获取支持的格式 |
| 195 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); | 195 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
| @@ -3,13 +3,16 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify | @@ -3,13 +3,16 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 4 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 5 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | ||
| 6 | import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; | 7 | import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; |
| 7 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 8 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 9 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 10 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | ||
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; |
| 11 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; |
| 12 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 14 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 15 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 13 | import org.dom4j.Element; | 16 | import org.dom4j.Element; |
| 14 | import org.slf4j.Logger; | 17 | import org.slf4j.Logger; |
| 15 | import org.slf4j.LoggerFactory; | 18 | import org.slf4j.LoggerFactory; |
| @@ -39,9 +42,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -39,9 +42,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 39 | private SIPCommander cmder; | 42 | private SIPCommander cmder; |
| 40 | 43 | ||
| 41 | @Autowired | 44 | @Autowired |
| 45 | + private SIPCommanderFroPlatform sipCommanderFroPlatform; | ||
| 46 | + | ||
| 47 | + @Autowired | ||
| 42 | private IRedisCatchStorage redisCatchStorage; | 48 | private IRedisCatchStorage redisCatchStorage; |
| 43 | 49 | ||
| 44 | @Autowired | 50 | @Autowired |
| 51 | + private IVideoManagerStorage storage; | ||
| 52 | + | ||
| 53 | + @Autowired | ||
| 45 | private VideoStreamSessionManager sessionManager; | 54 | private VideoStreamSessionManager sessionManager; |
| 46 | 55 | ||
| 47 | @Override | 56 | @Override |
| @@ -64,7 +73,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -64,7 +73,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 64 | } | 73 | } |
| 65 | CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); | 74 | CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); |
| 66 | String NotifyType =getText(rootElement, "NotifyType"); | 75 | String NotifyType =getText(rootElement, "NotifyType"); |
| 67 | - if (NotifyType.equals("121")){ | 76 | + if ("121".equals(NotifyType)){ |
| 68 | logger.info("[录像流]推送完毕,收到关流通知"); | 77 | logger.info("[录像流]推送完毕,收到关流通知"); |
| 69 | // 查询是设备 | 78 | // 查询是设备 |
| 70 | StreamInfo streamInfo = redisCatchStorage.queryDownload(null, null, null, callIdHeader.getCallId()); | 79 | StreamInfo streamInfo = redisCatchStorage.queryDownload(null, null, null, callIdHeader.getCallId()); |
| @@ -78,8 +87,17 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -78,8 +87,17 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 78 | SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); | 87 | SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); |
| 79 | if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 | 88 | if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 |
| 80 | cmder.streamByeCmd(device.getDeviceId(), ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); | 89 | cmder.streamByeCmd(device.getDeviceId(), ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); |
| 90 | + // 如果级联播放,需要给上级发送此通知 | ||
| 91 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); | ||
| 92 | + if (sendRtpItem != null) { | ||
| 93 | + ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); | ||
| 94 | + if (parentPlatform == null) { | ||
| 95 | + logger.warn("[级联消息发送]:发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId()); | ||
| 96 | + return; | ||
| 97 | + } | ||
| 98 | + sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem); | ||
| 99 | + } | ||
| 81 | } | 100 | } |
| 82 | - // TODO 如果级联播放,需要给上级发送此通知 | ||
| 83 | 101 | ||
| 84 | } | 102 | } |
| 85 | } | 103 | } |
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java
| @@ -32,12 +32,14 @@ public class DateUtil { | @@ -32,12 +32,14 @@ public class DateUtil { | ||
| 32 | */ | 32 | */ |
| 33 | public static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; | 33 | public static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; |
| 34 | 34 | ||
| 35 | + public static final String zoneStr = "Asia/Shanghai"; | ||
| 35 | 36 | ||
| 36 | - public static final DateTimeFormatter formatterCompatibleISO8601 = DateTimeFormatter.ofPattern(ISO8601_COMPATIBLE_PATTERN, Locale.getDefault()).withZone(ZoneId.systemDefault()); | ||
| 37 | - public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(ISO8601_PATTERN, Locale.getDefault()).withZone(ZoneId.systemDefault()); | ||
| 38 | - public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.systemDefault()); | 37 | + public static final DateTimeFormatter formatterCompatibleISO8601 = DateTimeFormatter.ofPattern(ISO8601_COMPATIBLE_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); |
| 38 | + public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(ISO8601_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); | ||
| 39 | + public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); | ||
| 39 | 40 | ||
| 40 | public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { | 41 | public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { |
| 42 | + | ||
| 41 | return formatterISO8601.format(formatter.parse(formatTime)); | 43 | return formatterISO8601.format(formatter.parse(formatTime)); |
| 42 | } | 44 | } |
| 43 | 45 |