From 26739237e2d93460eb869067a6004bfa63a1bdb8 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期一, 27 六月 2022 10:16:21 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/wvp-28181-2.0' into commercial --- src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java | 17 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java | 4 src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java | 9 src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java | 23 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java | 2 src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java | 19 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java | 2 src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java | 4 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java | 23 src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java | 15 src/main/resources/application-dev.yml | 2 src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java | 12 src/main/java/com/genersoft/iot/vmp/service/IPlayService.java | 2 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java | 5 web_src/src/components/DeviceList.vue | 58 src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java | 377 ++++ src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java | 116 + src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 105 src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java | 14 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java | 22 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java | 21 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java | 9 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java | 1 web_src/src/components/service/DeviceService.js | 46 web_src/src/components/common/DeviceTree.vue | 24 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java | 13 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 85 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java | 38 src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java | 1 pom.xml | 9 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java | 6 src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java | 12 src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java | 17 web_src/src/components/dialog/deviceEdit.vue | 6 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java | 2 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java | 2 src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java | 17 src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java | 10 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java | 18 web_src/src/components/ParentPlatformList.vue | 32 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java | 91 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java | 141 + src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java | 4 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 47 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java | 167 + web_src/src/components/control.vue | 6 src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java | 31 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java | 4 src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java | 3 web_src/src/components/dialog/rtcPlayer.vue | 18 src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java | 2 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java | 15 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java | 14 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java | 35 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java | 3 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | 8 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java | 3 src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java | 3 src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java | 52 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java | 10 sql/mysql.sql | 1 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java | 8 src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java | 7 src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java | 2 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java | 13 web_src/src/components/StreamProxyList.vue | 50 src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java | 45 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java | 143 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java | 2 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java | 2 web_src/package.json | 2 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java | 45 web_src/src/components/map.vue | 38 src/main/java/com/genersoft/iot/vmp/service/bean/RequestPushStreamMsg.java | 170 ++ README.md | 5 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java | 1 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java | 1224 +++++++------ src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java | 16 src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java | 173 ++ web_src/src/router/index.js | 12 web_src/src/layout/UiHeader.vue | 12 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java | 7 sql/update.sql | 26 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java | 106 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java | 15 src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java | 19 web_src/src/App.vue | 6 src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java | 44 web_src/src/components/PushVideoList.vue | 51 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java | 143 + web_src/src/components/CloudRecord.vue | 16 src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java | 83 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java | 8 web_src/src/components/dialog/devicePlayer.vue | 300 ++ src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java | 24 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java | 2 web_src/src/components/MediaServerManger.vue | 2 src/main/resources/application-docker.yml | 2 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java | 73 src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java | 30 src/main/resources/all-application.yml | 2 /dev/null | 23 web_src/src/components/channelList.vue | 163 + web_src/src/components/common/jessibuca.vue | 79 DOCKERFILE | 3 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java | 30 106 files changed, 3,638 insertions(+), 1,447 deletions(-) diff --git a/DOCKERFILE b/DOCKERFILE index d55e06a..f2a2ffa 100644 --- a/DOCKERFILE +++ b/DOCKERFILE @@ -1,3 +1,6 @@ +#寰堜箙娌$淮鎶や簡锛屽凡缁忎笌瀹氬墠鐗堟湰涓嶅尮閰� + + FROM ubuntu:20.04 AS build ARG DEBIAN_FRONTEND=noninteractive diff --git a/README.md b/README.md index 7ba443f..1c5f868 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,8 @@ - [X] 浜戠褰曞儚锛堥渶瑕侀儴缃插崟鐙湇鍔¢厤鍚堜娇鐢級 - [X] 澶氭祦濯掍綋鑺傜偣锛岃嚜鍔ㄩ�夋嫨璐熻浇鏈�浣庣殑鑺傜偣浣跨敤銆� - [X] WEB绔敮鎸佹挱鏀綡264涓嶩265锛岄煶棰戞敮鎸丟.711A/G.711U/AAC,瑕嗙洊鍥芥爣甯哥敤缂栫爜鏍煎紡銆� +- [X] 鏀寔鐢靛瓙鍦板浘銆� +- [X] 鏀寔鎺ュ叆WGS84鍜孏CJ02涓ょ鍧愭爣绯汇�� [//]: # (# docker蹇�熶綋楠�) @@ -143,7 +145,7 @@ # 鍚堜綔 鐩墠寰堝鎵撶潃鍚堜綔鐨勫箤瀛愭潵绉佽亰鐨勶紝鍏跺疄澶у澶у彲涓嶅繀锛岀洰鍓嶄綔鑰呮病鏈夌簿鍔涳紝浣犳湁闂鍙互浠樿垂鎵炬垜瑙g瓟锛屼篃鍙互鎻怭R -锛屽鏋滃浠g爜鏈夊缓璁彲浠ユ彁ISSUE锛涗篃鍙互鍔犵兢涓�璧疯亰鑱娿�傛垜浠杩庢墍鏈夋湁鍏磋叮浣嗛亣鍒伴」鐩腑鏉ョ殑浜恒�� +锛屽鏋滃浠g爜鏈夊缓璁彲浠ユ彁ISSUE锛涗篃鍙互鍔犵兢涓�璧疯亰鑱娿�傛垜浠杩庢墍鏈夋湁鍏磋叮鍙備笌鍒伴」鐩腑鏉ョ殑浜恒�� @@ -163,6 +165,7 @@ [hotcoffie](https://github.com/hotcoffie) [xiaomu](https://github.com/nikmu) [TristingChen](https://github.com/TristingChen) [chenparty](https://github.com/chenparty) [Hotleave](https://github.com/hotleave) [ydwxb](https://github.com/ydwxb) [ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666) +[mk1990](https://github.com/mk1990) ps: 鍒氬鍔犱簡杩欎釜鍚嶅崟锛岃偗瀹氶仐婕忎簡涓�浜涘ぇ浣紝娆㈣繋澶т浆鑱旂郴鎴戞坊鍔犮�� diff --git a/pom.xml b/pom.xml index 1546e39..1209124 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ <groupId>com.genersoft</groupId> <artifactId>wvp-pro</artifactId> - <version>2.2.1</version> + <version>2.3.1</version> <name>web video platform</name> <description>鍥芥爣28181瑙嗛骞冲彴</description> @@ -159,8 +159,9 @@ <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> - <version>1.2.73</version> + <version>1.2.83</version> </dependency> + <!-- okhttp --> <dependency> @@ -180,9 +181,9 @@ <!-- okhttp-digest --> <dependency> - <groupId>com.burgstaller</groupId> + <groupId>io.github.rburgst</groupId> <artifactId>okhttp-digest</artifactId> - <version>2.1</version> + <version>2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> diff --git a/sql/mysql.sql b/sql/mysql.sql index 4086d11..5e8467f 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -471,6 +471,7 @@ `createStamp` bigint(20) DEFAULT NULL, `aliveSecond` int(11) DEFAULT NULL, `mediaServerId` varchar(50) DEFAULT NULL, + `serverId` varchar(50) not NULL, PRIMARY KEY (`id`), UNIQUE KEY `stream_push_pk` (`app`,`stream`) ) ENGINE=InnoDB AUTO_INCREMENT=300838 DEFAULT CHARSET=utf8mb4; diff --git a/sql/update.sql b/sql/update.sql index 8bfe343..b7e98f8 100644 --- a/sql/update.sql +++ b/sql/update.sql @@ -1,5 +1,29 @@ +alter table parent_platform + add startOfflinePush int default 0 null; + +alter table parent_platform + add administrativeDivision varchar(50) not null; + +alter table parent_platform + add catalogGroup int default 1 null; + alter table device add audioChannelForReceive VARCHAR(50) null; alter table device - add audioChannelForSend VARCHAR(50) null; \ No newline at end of file + add audioChannelForSend VARCHAR(50) null; + +alter table stream_push + add serverId varchar(50) not null; +alter table device + add geoCoordSys varchar(50) not null; +update device set device.geoCoordSys='WGS84'; +alter table device_channel + add longitudeGcj02 double default null; +alter table device_channel + add latitudeGcj02 double default null; +alter table device_channel + add longitudeWgs84 double default null; +alter table device_channel + add latitudeWgs84 double default null; + diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index eb98f6f..57f764b 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -97,4 +97,5 @@ //************************** 绗笁鏂� **************************************** public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_"; public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_"; + } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java index 3b021de..ade2e62 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java @@ -103,12 +103,12 @@ public void stop(String key) { if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { - futureMap.get(key).cancel(true); - Runnable runnable = runnableMap.get(key); - if (runnable instanceof ISubscribeTask) { - ISubscribeTask subscribeTask = (ISubscribeTask) runnable; - subscribeTask.stop(); - } +// Runnable runnable = runnableMap.get(key); +// if (runnable instanceof ISubscribeTask) { +// ISubscribeTask subscribeTask = (ISubscribeTask) runnable; +// subscribeTask.stop(); +// } + futureMap.get(key).cancel(false); } } 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 85f4684..c24e0ca 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -6,6 +6,10 @@ import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.regex.Pattern; + @Configuration("mediaConfig") public class MediaConfig{ @@ -161,7 +165,18 @@ if (StringUtils.isEmpty(sdpIp)){ return ip; }else { - return sdpIp; + if (isValidIPAddress(sdpIp)) { + return sdpIp; + }else { + // 鎸夌収鍩熷悕瑙f瀽 + String hostAddress = null; + try { + hostAddress = InetAddress.getByName(sdpIp).getHostAddress(); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + return hostAddress; + } } } @@ -211,4 +226,11 @@ return mediaServerItem; } + private boolean isValidIPAddress(String ipAddress) { + if ((ipAddress != null) && (!ipAddress.isEmpty())) { + return Pattern.matches("^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", ipAddress); + } + return false; + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java index 6b45eb5..ec1f9ba 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java @@ -2,7 +2,9 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.service.impl.RedisAlarmMsgListener; -import com.genersoft.iot.vmp.service.impl.RedisGPSMsgListener; +import com.genersoft.iot.vmp.service.impl.RedisGpsMsgListener; +import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener; +import com.genersoft.iot.vmp.service.impl.RedisStreamMsgListener; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -47,10 +49,16 @@ private int poolMaxWait; @Autowired - private RedisGPSMsgListener redisGPSMsgListener; + private RedisGpsMsgListener redisGPSMsgListener; @Autowired private RedisAlarmMsgListener redisAlarmMsgListener; + + @Autowired + private RedisStreamMsgListener redisStreamMsgListener; + + @Autowired + private RedisGbPlayMsgListener redisGbPlayMsgListener; @Bean public JedisPool jedisPool() { @@ -98,6 +106,8 @@ container.setConnectionFactory(connectionFactory); container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS)); container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE)); + container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH")); + container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY)); return container; } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java b/src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java index 9690c6d..2d7e8a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java @@ -11,6 +11,9 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; +/** + * @author lin + */ @Component public class LoginSuccessHandler implements AuthenticationSuccessHandler { diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java index 47cfdab..a4bbdba 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java @@ -20,6 +20,7 @@ /** * 閰嶇疆Spring Security + * @author lin */ @Configuration @EnableWebSecurity @@ -132,15 +133,19 @@ .anyRequest().authenticated() // 寮傚父澶勭悊(鏉冮檺鎷掔粷銆佺櫥褰曞け鏁堢瓑) .and().exceptionHandling() - .authenticationEntryPoint(anonymousAuthenticationEntryPoint)//鍖垮悕鐢ㄦ埛璁块棶鏃犳潈闄愯祫婧愭椂鐨勫紓甯稿鐞� + //鍖垮悕鐢ㄦ埛璁块棶鏃犳潈闄愯祫婧愭椂鐨勫紓甯稿鐞� + .authenticationEntryPoint(anonymousAuthenticationEntryPoint) // .accessDeniedHandler(accessDeniedHandler)//鐧诲綍鐢ㄦ埛娌℃湁鏉冮檺璁块棶璧勬簮 - // 鐧诲叆 - .and().formLogin().permitAll()//鍏佽鎵�鏈夌敤鎴� - .successHandler(loginSuccessHandler)//鐧诲綍鎴愬姛澶勭悊閫昏緫 - .failureHandler(loginFailureHandler)//鐧诲綍澶辫触澶勭悊閫昏緫 + // 鐧诲叆 鍏佽鎵�鏈夌敤鎴� + .and().formLogin().permitAll() + //鐧诲綍鎴愬姛澶勭悊閫昏緫 + .successHandler(loginSuccessHandler) + //鐧诲綍澶辫触澶勭悊閫昏緫 + .failureHandler(loginFailureHandler) // 鐧诲嚭 - .and().logout().logoutUrl("/api/user/logout").permitAll()//鍏佽鎵�鏈夌敤鎴� - .logoutSuccessHandler(logoutHandler)//鐧诲嚭鎴愬姛澶勭悊閫昏緫 + .and().logout().logoutUrl("/api/user/logout").permitAll() + //鐧诲嚭鎴愬姛澶勭悊閫昏緫 + .logoutSuccessHandler(logoutHandler) .deleteCookies("JSESSIONID") // 浼氳瘽绠$悊 // .and().sessionManagement().invalidSessionStrategy(invalidSessionHandler) // 瓒呮椂澶勭悊 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 a095f51..c6406c5 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 @@ -1,6 +1,10 @@ package com.genersoft.iot.vmp.gb28181.bean; +/** + * 鍥芥爣璁惧/骞冲彴 + * @author lin + */ public class Device { /** @@ -127,7 +131,12 @@ /** * 鏄惁寮�鍚痵src鏍¢獙锛岄粯璁ゅ叧闂紝寮�鍚彲浠ラ槻姝覆娴� */ - private boolean ssrcCheck; + private boolean ssrcCheck = true; + + /** + * 鍦扮悊鍧愭爣绯伙紝 鐩墠鏀寔 WGS84,GCJ02 TODO CGCS2000 + */ + private String geoCoordSys; public String getDeviceId() { @@ -322,4 +331,12 @@ this.ssrcCheck = ssrcCheck; } + public String getGeoCoordSys() { + return geoCoordSys; + } + + public void setGeoCoordSys(String geoCoordSys) { + this.geoCoordSys = geoCoordSys; + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java index 95576f3..6345277 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java @@ -155,6 +155,26 @@ private double latitude; /** + * 缁忓害 GCJ02 + */ + private double longitudeGcj02; + + /** + * 绾害 GCJ02 + */ + private double latitudeGcj02; + + /** + * 缁忓害 WGS84 + */ + private double longitudeWgs84; + + /** + * 绾害 WGS84 + */ + private double latitudeWgs84; + + /** * 瀛愯澶囨暟 */ private int subCount; @@ -407,6 +427,38 @@ this.latitude = latitude; } + public double getLongitudeGcj02() { + return longitudeGcj02; + } + + public void setLongitudeGcj02(double longitudeGcj02) { + this.longitudeGcj02 = longitudeGcj02; + } + + public double getLatitudeGcj02() { + return latitudeGcj02; + } + + public void setLatitudeGcj02(double latitudeGcj02) { + this.latitudeGcj02 = latitudeGcj02; + } + + public double getLongitudeWgs84() { + return longitudeWgs84; + } + + public void setLongitudeWgs84(double longitudeWgs84) { + this.longitudeWgs84 = longitudeWgs84; + } + + public double getLatitudeWgs84() { + return latitudeWgs84; + } + + public void setLatitudeWgs84(double latitudeWgs84) { + this.latitudeWgs84 = latitudeWgs84; + } + public int getSubCount() { return subCount; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java new file mode 100644 index 0000000..97da863 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java @@ -0,0 +1,44 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +import org.dom4j.Element; + +import javax.sip.RequestEvent; + +/** + * @author lin + */ +public class HandlerCatchData { + private RequestEvent evt; + private Device device; + private Element rootElement; + + public HandlerCatchData(RequestEvent evt, Device device, Element rootElement) { + this.evt = evt; + this.device = device; + 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 Element getRootElement() { + return rootElement; + } + + public void setRootElement(Element rootElement) { + this.rootElement = rootElement; + } +} 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 c7f6182..41e1af7 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 @@ -72,6 +72,11 @@ private String mediaServerId; /** + * 浣跨敤鐨勬湇鍔$殑ID + */ + private String serverId; + + /** * invite鐨刢allId */ private String CallId; @@ -259,4 +264,12 @@ public void setOnlyAudio(boolean onlyAudio) { this.onlyAudio = onlyAudio; } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } } 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 f191c00..4a900c1 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 @@ -2,6 +2,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; 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.storager.IRedisCatchStorage; @@ -38,7 +39,6 @@ catalogMap.put(platformId, subscribeInfo); // 娣诲姞璁㈤槄鍒版湡 String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; - dynamicTask.stop(taskOverdueKey); // 娣诲姞浠诲姟澶勭悊璁㈤槄杩囨湡 dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()), subscribeInfo.getExpires() * 1000); @@ -49,10 +49,17 @@ } public void removeCatalogSubscribe(String platformId) { + catalogMap.remove(platformId); String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; + Runnable runnable = dynamicTask.get(taskOverdueKey); + if (runnable instanceof ISubscribeTask) { + ISubscribeTask subscribeTask = (ISubscribeTask) runnable; + subscribeTask.stop(); + } // 娣诲姞浠诲姟澶勭悊璁㈤槄杩囨湡 dynamicTask.stop(taskOverdueKey); + } public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { @@ -63,7 +70,6 @@ storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask), subscribeInfo.getGpsInterval() * 1000); String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; - dynamicTask.stop(taskOverdueKey); // 娣诲姞浠诲姟澶勭悊璁㈤槄杩囨湡 dynamicTask.startDelay(taskOverdueKey, () -> { removeMobilePositionSubscribe(subscribeInfo.getId()); @@ -81,6 +87,11 @@ // 缁撴潫浠诲姟澶勭悊GPS瀹氭椂鎺ㄩ�� dynamicTask.stop(key); String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; + Runnable runnable = dynamicTask.get(taskOverdueKey); + if (runnable instanceof ISubscribeTask) { + ISubscribeTask subscribeTask = (ISubscribeTask) runnable; + subscribeTask.stop(); + } // 娣诲姞浠诲姟澶勭悊璁㈤槄杩囨湡 dynamicTask.stop(taskOverdueKey); } 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 3d817c3..c6cfc7a 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 @@ -88,8 +88,8 @@ this.type = "timeout"; this.msg = "娑堟伅瓒呮椂鏈洖澶�"; this.statusCode = -1024; - this.callId = timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(); this.dialog = timeoutEvent.getClientTransaction().getDialog(); + this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null; }else if (event instanceof TransactionTerminatedEvent) { TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event; this.type = "transactionTerminated"; @@ -109,8 +109,8 @@ this.type = "deviceNotFoundEvent"; this.msg = "璁惧鏈壘鍒�"; this.statusCode = -1024; - this.callId = deviceNotFoundEvent.getDialog().getCallId().getCallId(); this.dialog = deviceNotFoundEvent.getDialog(); + this.callId = this.dialog != null ?deviceNotFoundEvent.getDialog().getCallId().getCallId() : null; } } } @@ -130,6 +130,9 @@ } public void removeErrorSubscribe(String key) { + if(key == null){ + return; + } errorSubscribes.remove(key); errorTimeSubscribes.remove(key); } @@ -139,6 +142,9 @@ } public void removeOkSubscribe(String key) { + if(key == null){ + return; + } okSubscribes.remove(key); okTimeSubscribes.remove(key); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java index 7e5ecb4..e38733d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java @@ -66,7 +66,7 @@ subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId()); if (subscribe == null) { - logger.info("鍙戦�佽闃呮秷鎭椂鍙戠幇璁㈤槄淇℃伅宸茬粡涓嶅瓨鍦�"); + logger.info("鍙戦�佽闃呮秷鎭椂鍙戠幇璁㈤槄淇℃伅宸茬粡涓嶅瓨鍦�: {}", event.getPlatformId()); return; } }else { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java index 85bc39d..a22d24d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -99,8 +99,8 @@ return dialog; } - public SIPDialog getDialogByCallId(String deviceId, String channelId, String callID){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callID, null); + public SIPDialog getDialogByCallId(String deviceId, String channelId, String callId){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null); if (ssrcTransaction == null) { return null; } @@ -108,11 +108,17 @@ if (dialogByteArray == null) { return null; } - SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray); - return dialog; + return (SIPDialog)SerializeUtils.deSerialize(dialogByteArray); } public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){ + + if (StringUtils.isEmpty(deviceId)) { + deviceId ="*"; + } + if (StringUtils.isEmpty(channelId)) { + channelId ="*"; + } if (StringUtils.isEmpty(callId)) { callId ="*"; } @@ -179,7 +185,7 @@ public List<SsrcTransaction> getAllSsrc() { - List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId() + "_" )); + List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId())); List<SsrcTransaction> result= new ArrayList<>(); for (int i = 0; i < ssrcTransactionKeys.size(); i++) { String key = (String)ssrcTransactionKeys.get(i); 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 c416766..66b57fe 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 @@ -71,7 +71,9 @@ String gbId = gbStream.getGbId(); GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); if (gpsMsgInfo != null) { // 鏃犳渶鏂颁綅缃笉鍙戦�� - logger.info("鏃犳渶鏂颁綅缃笉鍙戦��"); + if (logger.isDebugEnabled()) { + logger.debug("鏃犳渶鏂颁綅缃笉鍙戦��"); + } // 缁忕含搴﹂兘涓�0涓嶅彂閫� if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { continue; 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 a06a73d..a2fab81 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 @@ -150,30 +150,24 @@ public void processTimeout(TimeoutEvent timeoutEvent) { logger.info("[娑堟伅鍙戦�佽秴鏃禲"); ClientTransaction clientTransaction = timeoutEvent.getClientTransaction(); - eventPublisher.requestTimeOut(timeoutEvent); + if (clientTransaction != null) { + logger.info("[鍙戦�侀敊璇闃匽 clientTransaction != null"); Request request = clientTransaction.getRequest(); if (request != null) { + logger.info("[鍙戦�侀敊璇闃匽 request != null"); CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); if (callIdHeader != null) { + logger.info("[鍙戦�侀敊璇闃匽"); SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent); subscribe.response(eventResult); + sipSubscribe.removeOkSubscribe(callIdHeader.getCallId()); sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId()); } } } - -// Timeout timeout = timeoutEvent.getTimeout(); -// ServerTransaction serverTransaction = timeoutEvent.getServerTransaction(); -// if (serverTransaction != null) { -// Request request = serverTransaction.getRequest(); -// URI requestURI = request.getRequestURI(); -// Header header = request.getHeader(FromHeader.NAME); -// } -// if(timeoutProcessor != null) { -// timeoutProcessor.process(timeoutEvent); -// } + eventPublisher.requestTimeOut(timeoutEvent); } @Override 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 bd51cfa..bf6146a 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 @@ -148,6 +148,14 @@ * 鍥炴斁鍊嶉�熸挱鏀� */ void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed); + + /** + * 鍥炴斁鎺у埗 + * @param device + * @param streamInfo + * @param content + */ + void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent); /** 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 7007e5a..d000f5a 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 @@ -104,6 +104,14 @@ boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo); /** + * 褰曞儚鎾斁鎺ㄩ�佸畬鎴愭椂鍙戦�丮ediaStatus娑堟伅 + * @param platform + * @param sendRtpItem + * @return + */ + boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem); + + /** * 鍚戝彂璧风偣鎾殑涓婄骇鍥炲bye * @param platform 骞冲彴淇℃伅 * @param callId callId 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 d8deb5c..832f716 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 @@ -32,7 +32,9 @@ import org.springframework.util.StringUtils; import javax.sip.*; +import javax.sip.address.Address; import javax.sip.address.SipURI; +import javax.sip.address.URI; import javax.sip.header.*; import javax.sip.message.Request; import java.lang.reflect.Field; @@ -708,22 +710,19 @@ } SIPDialog dialog; if (callId != null) { - dialog = streamSession.getDialogByCallId(deviceId, channelId, callId); + dialog = streamSession.getDialogByCallId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), callId); }else { - if (stream == null) { + if (stream == null && ssrcTransaction == null && ssrcTransaction.getStream() == null) { return; } - dialog = streamSession.getDialogByStream(deviceId, channelId, stream); + dialog = streamSession.getDialogByStream(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); } - if (ssrcTransaction != null) { - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId()); - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc()); - mediaServerService.closeRTPServer(deviceId, channelId, ssrcTransaction.getStream()); - streamSession.remove(deviceId, channelId, ssrcTransaction.getStream()); - } + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); + mediaServerService.closeRTPServer(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); + streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); if (dialog == null) { - logger.warn("[ {} -> {}]鍋滄瑙嗛娴佺殑鏃跺�欏彂鐜板璇濆凡涓㈠け", deviceId, channelId); + logger.warn("[ {} -> {}]鍋滄瑙嗛娴佺殑鏃跺�欏彂鐜板璇濆凡涓㈠け", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); return; } SipStack sipStack = udpSipProvider.getSipStack(); @@ -1456,12 +1455,20 @@ Request request; if (dialog != null) { - logger.info("鍙戦�佺Щ鍔ㄤ綅缃闃呮秷鎭椂 dialog鐨勭姸鎬佷负锛� {}", dialog.getState()); + 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(subscribePostitionXml.toString(), contentTypeHeader); - ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition()); - request.addHeader(expireHeader); + + CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME); + cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ(Request.SUBSCRIBE)); + request.removeHeader(CSeqHeader.NAME); + request.addHeader(cSeqHeader); }else { String tm = Long.toString(System.currentTimeMillis()); CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() @@ -1552,12 +1559,21 @@ Request request; if (dialog != null) { - logger.info("鍙戦�佺洰褰曡闃呮秷鎭椂 dialog鐨勭姸鎬佷负锛� {}", dialog.getState()); + 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); - ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition()); - request.addHeader(expireHeader); + + CSeqHeader cSeqHeader = (CSeqHeader)request.getHeader(CSeqHeader.NAME); + cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ(Request.SUBSCRIBE)); + request.removeHeader(CSeqHeader.NAME); + request.addHeader(cSeqHeader); + }else { String tm = Long.toString(System.currentTimeMillis()); @@ -1779,6 +1795,43 @@ e.printStackTrace(); } } + + @Override + public void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) { + try { + Request request = headerProvider.createInfoRequest(device, streamInfo, content); + if (request == null) { + return; + } + logger.info(request.toString()); + ClientTransaction clientTransaction = null; + if ("TCP".equals(device.getTransport())) { + clientTransaction = tcpSipProvider.getNewClientTransaction(request); + } else if ("UDP".equals(device.getTransport())) { + clientTransaction = udpSipProvider.getNewClientTransaction(request); + } + CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME); + if(errorEvent != null) { + sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> { + errorEvent.response(eventResult); + sipSubscribe.removeErrorSubscribe(eventResult.callId); + sipSubscribe.removeOkSubscribe(eventResult.callId); + })); + } + + if(okEvent != null) { + sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> { + okEvent.response(eventResult); + sipSubscribe.removeOkSubscribe(eventResult.callId); + sipSubscribe.removeErrorSubscribe(eventResult.callId); + }); + } + clientTransaction.sendRequest(); + + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + } + } @Override public boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) { 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 a4fd507..2e70ea7 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 @@ -31,6 +31,7 @@ import javax.sip.header.*; import javax.sip.message.Request; import java.lang.reflect.Field; +import java.net.InetAddress; import java.text.ParseException; import java.util.ArrayList; import java.util.HashSet; @@ -276,8 +277,8 @@ catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n"); catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); - catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n"); - catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n"); + catalogXml.append("<Longitude>" + channel.getLongitudeWgs84() + "</Longitude>\r\n"); + catalogXml.append("<Latitude>" + channel.getLatitudeWgs84() + "</Latitude>\r\n"); catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n"); catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n"); catalogXml.append("<Info>\r\n"); @@ -546,14 +547,8 @@ } 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(parentPlatform.getServerIP()); - sipURI.setPort(parentPlatform.getServerPort()); - } + sipURI.setHost(parentPlatform.getServerIP()); + sipURI.setPort(parentPlatform.getServerPort()); ClientTransaction transaction = null; if ("TCP".equals(parentPlatform.getTransport())) { @@ -751,6 +746,82 @@ } @Override + public boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) { + if (sendRtpItem == null) { + return false; + } + if (platform == null) { + 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("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); + mediaStatusXml.append("<Notify>\r\n"); + mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n"); + mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); + mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n"); + mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n"); + mediaStatusXml.append("</Notify>\r\n"); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); + messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader); + SipURI sipURI = (SipURI) messageRequest.getRequestURI(); + sipURI.setHost(platform.getServerIP()); + sipURI.setPort(platform.getServerPort()); + ClientTransaction clientTransaction; + if ("TCP".equals(platform.getTransport())) { + clientTransaction = tcpSipProvider.getNewClientTransaction(messageRequest); + }else { + clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest); + } + dialog.sendRequest(clientTransaction); + } catch (SipException e) { + e.printStackTrace(); + return false; + } catch (ParseException e) { + e.printStackTrace(); + return false; + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + + + } + + @Override public void streamByeCmd(ParentPlatform platform, String callId) { if (platform == null) { return; @@ -766,45 +837,51 @@ byte[] dialogByteArray = sendRtpItem.getDialog(); if (dialogByteArray != null) { SIPDialog dialog = (SIPDialog) SerializeUtils.deSerialize(dialogByteArray); - SipStack sipStack = udpSipProvider.getSipStack(); + 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; - } else { - try { - 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<>()); - - byte[] transactionByteArray = sendRtpItem.getTransaction(); - ClientTransaction clientTransaction = (ClientTransaction) SerializeUtils.deSerialize(transactionByteArray); - Request byeRequest = dialog.createRequest(Request.BYE); - - SipURI byeURI = (SipURI) byeRequest.getRequestURI(); - SIPRequest request = (SIPRequest) clientTransaction.getRequest(); - byeURI.setHost(request.getRemoteAddress().getHostAddress()); - byeURI.setPort(request.getRemotePort()); - if ("TCP".equals(platform.getTransport())) { - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); - } else if ("UDP".equals(platform.getTransport())) { - 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(); - } - } + 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(); + } + } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java deleted file mode 100644 index dd098f7..0000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.transmit.event.request; - -import gov.nist.javax.sip.SipProviderImpl; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; - -/** - * @description:澶勭悊鎺ユ敹IPCamera鍙戞潵鐨凷IP鍗忚璇锋眰娑堟伅 - * @author: songww - * @date: 2020骞�5鏈�3鏃� 涓嬪崍4:42:22 - */ -public abstract class SIPRequestProcessorAbstract { - - - @Autowired - @Qualifier(value="tcpSipProvider") - private SipProviderImpl tcpSipProvider; - - @Autowired - @Qualifier(value="udpSipProvider") - private SipProviderImpl udpSipProvider; - -} 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 85ee647..33bee75 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 @@ -15,10 +15,13 @@ 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.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.stack.SIPDialog; +import com.genersoft.iot.vmp.utils.SerializeUtils; import org.ehcache.shadow.org.terracotta.offheapstore.storage.IntegerStorageEngine; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +49,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class); - private String method = "ACK"; + private final String method = "ACK"; @Autowired private SIPProcessorObserver sipProcessorObserver; @@ -83,6 +86,9 @@ @Autowired private AudioBroadcastManager audioBroadcastManager; + + @Autowired + private RedisGbPlayMsgListener redisGbPlayMsgListener; /** @@ -159,60 +165,41 @@ // 鍚戜笂绾у钩鍙� commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); } + 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); } -// if (streamInfo == null) { // 娴佽繕娌′笂鏉ワ紝瀵规柟灏卞洖澶峚ck -// logger.info("鐩戝惉娴佷互绛夊緟娴佷笂绾�1 rtp/{}", sendRtpItem.getStreamId()); -// // 鐩戝惉娴佷笂绾� -// // 娣诲姞璁㈤槄 -// JSONObject subscribeKey = new JSONObject(); -// subscribeKey.put("app", "rtp"); -// subscribeKey.put("stream", sendRtpItem.getStreamId()); -// subscribeKey.put("regist", true); -// subscribeKey.put("schema", "rtmp"); -// subscribeKey.put("mediaServerId", sendRtpItem.getMediaServerId()); -// subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, -// (MediaServerItem mediaServerItemInUse, JSONObject json)->{ -// Map<String, Object> param = new HashMap<>(); -// param.put("vhost","__defaultVhost__"); -// param.put("app",json.getString("app")); -// param.put("stream",json.getString("stream")); -// 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()); -// zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); -// }); -// }else { -// Map<String, Object> param = new HashMap<>(); -// param.put("vhost","__defaultVhost__"); -// param.put("app",streamInfo.getApp()); -// param.put("stream",streamInfo.getStream()); -// 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()); -// -// JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); -// if (jsonObject.getInteger("code") != 0) { -// logger.info("鐩戝惉娴佷互绛夊緟娴佷笂绾�2 {}/{}", streamInfo.getApp(), streamInfo.getStream()); -// // 鐩戝惉娴佷笂绾� -// // 娣诲姞璁㈤槄 -// JSONObject subscribeKey = new JSONObject(); -// subscribeKey.put("app", "rtp"); -// subscribeKey.put("stream", streamInfo.getStream()); -// subscribeKey.put("regist", true); -// subscribeKey.put("schema", "rtmp"); -// subscribeKey.put("mediaServerId", sendRtpItem.getMediaServerId()); -// subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, -// (MediaServerItem mediaServerItemInUse, JSONObject json)->{ -// zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); -// }); -// } -// } + } + } + private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform, + JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader) { + if (jsonObject == null) { + logger.error("RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); + } else if (jsonObject.getInteger("code") == 0) { + 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()) { + // TODO 鍙兘鏄闊冲璁� + }else { + // 鍚戜笂绾у钩鍙� + commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); + } } } } 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 7944787..628bc15 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 @@ -114,13 +114,9 @@ playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); } if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { - MessageForPushChannel messageForPushChannel = new MessageForPushChannel(); - messageForPushChannel.setType(0); - messageForPushChannel.setGbId(sendRtpItem.getChannelId()); - messageForPushChannel.setApp(sendRtpItem.getApp()); - messageForPushChannel.setStream(sendRtpItem.getStreamId()); - messageForPushChannel.setMediaServerId(sendRtpItem.getMediaServerId()); - messageForPushChannel.setPlatFormId(sendRtpItem.getPlatformId()); + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), + sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java index 0a818ee..b04352a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java @@ -15,7 +15,7 @@ @Component public class CancelRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { - private String method = "CANCEL"; + private final String method = "CANCEL"; @Autowired private SIPProcessorObserver sipProcessorObserver; 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 eabfd1a..095f5e2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -26,11 +26,14 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlayService; +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.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; @@ -66,33 +69,42 @@ @Component public class InviteRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { - private final static Logger logger = LoggerFactory.getLogger(InviteRequestProcessor.class); + private final static Logger logger = LoggerFactory.getLogger(InviteRequestProcessor.class); - private String method = "INVITE"; + private final String method = "INVITE"; - @Autowired - private SIPCommanderFroPlatform cmderFroPlatform; + @Autowired + private SIPCommanderFroPlatform cmderFroPlatform; - @Autowired - private IVideoManagerStorage storager; + @Autowired + private IVideoManagerStorage storager; - @Autowired - private IRedisCatchStorage redisCatchStorage; + @Autowired + private IStreamPushService streamPushService; - @Autowired - private DynamicTask dynamicTask; + @Autowired + private IRedisCatchStorage redisCatchStorage; - @Autowired - private SIPCommander cmder; + @Autowired + private DynamicTask dynamicTask; - @Autowired - private IPlayService playService; + @Autowired + private SIPCommander cmder; + @Autowired + private IPlayService playService; + + @Autowired + private ISIPCommander commander; + @Autowired private AudioBroadcastManager audioBroadcastManager; - @Autowired - private ZLMRTPServerFactory zlmrtpServerFactory; + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private IMediaServerService mediaServerService; @Autowired private ZLMRESTfulUtils zlmresTfulUtils; @@ -100,17 +112,17 @@ @Autowired private IMediaServerService mediaServerService; - @Autowired - private SIPProcessorObserver sipProcessorObserver; + @Autowired + private SIPProcessorObserver sipProcessorObserver; - @Autowired - private VideoStreamSessionManager sessionManager; + @Autowired + private VideoStreamSessionManager sessionManager; - @Autowired - private UserSetting userSetting; + @Autowired + private UserSetting userSetting; - @Autowired - private ZLMMediaListManager mediaListManager; + @Autowired + private ZLMMediaListManager mediaListManager; @Autowired private DeferredResultHolder resultHolder; @@ -123,542 +135,664 @@ - @Override - public void afterPropertiesSet() throws Exception { - // 娣诲姞娑堟伅澶勭悊鐨勮闃� - sipProcessorObserver.addRequestProcessor(method, this); - } - - /** - * 澶勭悊invite璇锋眰 - * - * @param evt - * 璇锋眰娑堟伅 - */ - @Override - public void process(RequestEvent evt) { - // Invite Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傝棰戞寚浠� - try { - Request request = evt.getRequest(); - SipURI sipURI = (SipURI) request.getRequestURI(); - //浠巗ubject璇诲彇channelId,涓嶅啀浠巖equest-line璇诲彇銆� 鏈変簺骞冲彴request-line鏄钩鍙板浗鏍囩紪鐮侊紝涓嶆槸璁惧鍥芥爣缂栫爜銆� - //String channelId = sipURI.getUser(); - String channelId = SipUtils.getChannelIdFromHeader(request); - String requesterId = SipUtils.getUserIdFromFromHeader(request); - CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME); - if (requesterId == null || channelId == null) { - logger.info("鏃犳硶浠嶧romHeader鐨凙ddress涓幏鍙栧埌骞冲彴id锛岃繑鍥�400"); - responseAck(evt, Response.BAD_REQUEST); // 鍙傛暟涓嶅叏锛� 鍙�400锛岃姹傞敊璇� - return; - } - - // 鏌ヨ璇锋眰鏄惁鏉ヨ嚜涓婄骇骞冲彴\璁惧 - ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); - if (platform == null) { - inviteFromDeviceHandle(evt, requesterId, channelId); - }else { - // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾 - DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); - GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); - PlatformCatalog catalog = storager.getCatalog(channelId); - MediaServerItem mediaServerItem = 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锛屽懠鍙浆鎺ヤ腑 - }else if(channel == null && gbStream != null){ - String mediaServerId = gbStream.getMediaServerId(); - mediaServerItem = mediaServerService.getOne(mediaServerId); - if (mediaServerItem == null) { - logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410",gbStream.getApp(), gbStream.getStream(), mediaServerId); - responseAck(evt, Response.GONE); - return; - } - responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑 - }else if (catalog != null) { - responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 鐩綍涓嶆敮鎸佺偣鎾� - return; - } else { - logger.info("閫氶亾涓嶅瓨鍦紝杩斿洖404"); - responseAck(evt, Response.NOT_FOUND); // 閫氶亾涓嶅瓨鍦紝鍙�404锛岃祫婧愪笉瀛樺湪 - return; - } - // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡 - String contentString = new String(request.getRawContent()); - - // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎浠ヨВ鏋愩�� - int ssrcIndex = contentString.indexOf("y="); - // 妫�鏌ユ槸鍚︽湁y瀛楁 - String ssrcDefault = "0000000000"; - String ssrc; - SessionDescription sdp; - if (ssrcIndex >= 0) { - //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); - String substring = contentString.substring(0, contentString.indexOf("y=")); - sdp = SdpFactory.getInstance().createSessionDescription(substring); - }else { - ssrc = ssrcDefault; - sdp = SdpFactory.getInstance().createSessionDescription(contentString); - } - String sessionName = sdp.getSessionName().getValue(); - - Long startTime = null; - Long stopTime = null; - Instant start = null; - Instant end = null; - if (sdp.getTimeDescriptions(false) != null && sdp.getTimeDescriptions(false).size() > 0) { - TimeDescriptionImpl timeDescription = (TimeDescriptionImpl)(sdp.getTimeDescriptions(false).get(0)); - TimeField startTimeFiled = (TimeField)timeDescription.getTime(); - startTime = startTimeFiled.getStartTime(); - stopTime = startTimeFiled.getStopTime(); - - start = Instant.ofEpochMilli(startTime*1000); - end = Instant.ofEpochMilli(stopTime*1000); - } - // 鑾峰彇鏀寔鐨勬牸寮� - Vector mediaDescriptions = sdp.getMediaDescriptions(true); - // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 - //String ip = null; - int port = -1; - boolean mediaTransmissionTCP = false; - Boolean tcpActive = null; - for (Object description : mediaDescriptions) { - MediaDescription mediaDescription = (MediaDescription) description; - Media media = mediaDescription.getMedia(); - - Vector mediaFormats = media.getMediaFormats(false); - if (mediaFormats.contains("96")) { - port = media.getMediaPort(); - //String mediaType = media.getMediaType(); - String protocol = media.getProtocol(); - - // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp - if ("TCP/RTP/AVP".equals(protocol)) { - String setup = mediaDescription.getAttribute("setup"); - if (setup != null) { - mediaTransmissionTCP = true; - if ("active".equals(setup)) { - tcpActive = true; - // 涓嶆敮鎸乼cp涓诲姩 - responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 鐩綍涓嶆敮鎸佺偣鎾� - return; - } else if ("passive".equals(setup)) { - tcpActive = false; - } - } - } - break; - } - } - if (port == -1) { - logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); - // 鍥炲涓嶆敮鎸佺殑鏍煎紡 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 - return; - } - String username = sdp.getOrigin().getUsername(); - String addressStr = sdp.getOrigin().getAddress(); - - logger.info("[涓婄骇鐐规挱]鐢ㄦ埛锛歿}锛� 鍦板潃锛歿}:{}锛� ssrc锛歿}", username, addressStr, port, ssrc); - Device device = null; - // 閫氳繃 channel 鍜� gbStream 鏄惁涓簄ull 鍊煎垽鏂潵婧愭槸鐩存挱娴佸悎閫傚浗鏍� - if (channel != null) { - device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); - if (device == null) { - logger.warn("鐐规挱骞冲彴{}鐨勯�氶亾{}鏃舵湭鎵惧埌璁惧淇℃伅", requesterId, channel); - responseAck(evt, Response.SERVER_INTERNAL_ERROR); - return; - } - mediaServerItem = playService.getNewMediaServerItem(device); - if (mediaServerItem == null) { - logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm"); - responseAck(evt, 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("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); - responseAck(evt, Response.BUSY_HERE); - return; - } - sendRtpItem.setCallId(callIdHeader.getCallId()); - sendRtpItem.setPlayType("Play".equals(sessionName)?InviteStreamType.PLAY:InviteStreamType.PLAYBACK); - byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog()); - sendRtpItem.setDialog(dialogByteArray); - byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction()); - sendRtpItem.setTransaction(transactionByteArray); - Long finalStartTime = startTime; - Long finalStopTime = stopTime; - ZLMHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON)->{ - String app = responseJSON.getString("app"); - String stream = responseJSON.getString("stream"); - logger.info("[涓婄骇鐐规挱]涓嬬骇宸茬粡寮�濮嬫帹娴併�� 鍥炲200OK(SDP)锛� {}/{}", app, stream); - // * 0 绛夊緟璁惧鎺ㄦ祦涓婃潵 - // * 1 涓嬬骇宸茬粡鎺ㄦ祦锛岀瓑寰呬笂绾у钩鍙板洖澶峚ck - // * 2 鎺ㄦ祦涓� - sendRtpItem.setStatus(1); - redisCatchStorage.updateSendRTPSever(sendRtpItem); - - StringBuffer content = new StringBuffer(200); - content.append("v=0\r\n"); - content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); - content.append("s=" + sessionName+"\r\n"); - content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); - if ("Playback".equals(sessionName)) { - content.append("t=" + finalStartTime + " " + finalStopTime + "\r\n"); - }else { - content.append("t=0 0\r\n"); - } - content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); - content.append("a=sendonly\r\n"); - content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("y="+ ssrc + "\r\n"); - content.append("f=\r\n"); - - try { - // 瓒呮椂鏈敹鍒癆ck搴旇鍥炲bye,褰撳墠绛夊緟鏃堕棿涓�10绉� - dynamicTask.startDelay(callIdHeader.getCallId(), ()->{ - logger.info("Ack 绛夊緟瓒呮椂"); - mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc); - // 鍥炲bye - cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId()); - }, 60*1000); - responseSdpAck(evt, content.toString(), platform); - - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - }; - SipSubscribe.Event errorEvent = ((event) -> { - // 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒 - Response response = null; - try { - response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); - ServerTransaction serverTransaction = getServerTransaction(evt); - serverTransaction.sendResponse(response); - if (serverTransaction.getDialog() != null) { - serverTransaction.getDialog().delete(); - } - } catch (ParseException | SipException | InvalidArgumentException e) { - e.printStackTrace(); - } - }); - sendRtpItem.setApp("rtp"); - if ("Playback".equals(sessionName)) { - sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true, true); - sendRtpItem.setStreamId(ssrcInfo.getStream()); - // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� - redisCatchStorage.updateSendRTPSever(sendRtpItem); - playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), - DateUtil.formatter.format(end), null, result -> { - if (result.getCode() != 0){ - logger.warn("褰曞儚鍥炴斁澶辫触"); - if (result.getEvent() != null) { - errorEvent.response(result.getEvent()); - } - redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); - try { - responseAck(evt, Response.REQUEST_TIMEOUT); - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - }else { - if (result.getMediaServerItem() != null) { - hookEvent.response(result.getMediaServerItem(), result.getResponse()); - } - } - }); - }else { - sendRtpItem.setPlayType(InviteStreamType.PLAY); - SsrcTransaction playTransaction = sessionManager.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); - if (playTransaction != null) { - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream()); - if (!streamReady) { - playTransaction = null; - } - } - if (playTransaction == null) { - String streamId = null; - if (mediaServerItem.isRtpEnable()) { - streamId = String.format("%s_%s", device.getDeviceId(), channelId); - } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, true, false); - sendRtpItem.setStreamId(ssrcInfo.getStream()); - // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� - redisCatchStorage.updateSendRTPSever(sendRtpItem); - playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg)->{ - redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); - }, null); - }else { - sendRtpItem.setStreamId(playTransaction.getStream()); - // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� - redisCatchStorage.updateSendRTPSever(sendRtpItem); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("app", sendRtpItem.getApp()); - jsonObject.put("stream", sendRtpItem.getStreamId()); - hookEvent.response(mediaServerItem, jsonObject); - } - } - }else if (gbStream != null) { - - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); - if (!streamReady ) { - if ("proxy".equals(gbStream.getStreamType())) { - // TODO 鎺у埗鍚敤浠ヤ娇璁惧涓婄嚎 - logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽惎鐢ㄦ祦鍚庡紑濮嬫帹娴�",gbStream.getApp(), gbStream.getStream()); - responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); - }else if ("push".equals(gbStream.getStreamType())) { - if (!platform.isStartOfflinePush()) { - responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel unavailable"); - return; - } - // 鍙戦�乺edis娑堟伅浠ヤ娇璁惧涓婄嚎 - logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽彂閫乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�",gbStream.getApp(), gbStream.getStream()); - MessageForPushChannel messageForPushChannel = new MessageForPushChannel(); - messageForPushChannel.setType(1); - messageForPushChannel.setGbId(gbStream.getGbId()); - messageForPushChannel.setApp(gbStream.getApp()); - messageForPushChannel.setStream(gbStream.getStream()); - // TODO 鑾峰彇浣庤礋杞界殑鑺傜偣 - messageForPushChannel.setMediaServerId(gbStream.getMediaServerId()); - messageForPushChannel.setPlatFormId(platform.getServerGBId()); - messageForPushChannel.setPlatFormName(platform.getName()); - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); - // 璁剧疆瓒呮椂 - dynamicTask.startDelay(callIdHeader.getCallId(), ()->{ - logger.info("[ app={}, stream={} ] 绛夊緟璁惧寮�濮嬫帹娴佽秴鏃�", gbStream.getApp(), gbStream.getStream()); - try { - mediaListManager.removedChannelOnlineEventLister(gbStream.getGbId()); - responseAck(evt, Response.REQUEST_TIMEOUT); // 瓒呮椂 - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - }, userSetting.getPlatformPlayTimeout()); - // 娣诲姞鐩戝惉 - MediaServerItem finalMediaServerItem = mediaServerItem; - int finalPort = port; - boolean finalMediaTransmissionTCP = mediaTransmissionTCP; - Boolean finalTcpActive = tcpActive; - mediaListManager.addChannelOnlineEventLister(gbStream.getGbId(), (app, stream)->{ - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(finalMediaServerItem, addressStr, finalPort, ssrc, requesterId, - app, stream, channelId, finalMediaTransmissionTCP); - - if (sendRtpItem == null) { - logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); - try { - responseAck(evt, Response.BUSY_HERE); - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return; - } - if (finalTcpActive != null) { - sendRtpItem.setTcpActive(finalTcpActive); - } - sendRtpItem.setPlayType(InviteStreamType.PUSH); - // 鍐欏叆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); - redisCatchStorage.updateSendRTPSever(sendRtpItem); - sendStreamAck(finalMediaServerItem, sendRtpItem, platform, evt); - - }); - } - }else { - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, - gbStream.getApp(), gbStream.getStream(), channelId, - mediaTransmissionTCP); - - if (sendRtpItem == null) { - logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); - responseAck(evt, Response.BUSY_HERE); - return; - } - if (tcpActive != null) { - sendRtpItem.setTcpActive(tcpActive); - } - sendRtpItem.setPlayType(InviteStreamType.PUSH); - // 鍐欏叆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); - redisCatchStorage.updateSendRTPSever(sendRtpItem); - sendStreamAck(mediaServerItem, sendRtpItem, platform, evt); - } + @Autowired + private RedisGbPlayMsgListener redisGbPlayMsgListener; - } + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } - } + /** + * 澶勭悊invite璇锋眰 + * + * @param evt 璇锋眰娑堟伅 + */ + @Override + public void process(RequestEvent evt) { + // Invite Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傝棰戞寚浠� + try { + Request request = evt.getRequest(); + SipURI sipUri = (SipURI) request.getRequestURI(); + //浠巗ubject璇诲彇channelId,涓嶅啀浠巖equest-line璇诲彇銆� 鏈変簺骞冲彴request-line鏄钩鍙板浗鏍囩紪鐮侊紝涓嶆槸璁惧鍥芥爣缂栫爜銆� + //String channelId = sipURI.getUser(); + String channelId = SipUtils.getChannelIdFromHeader(request); + String requesterId = SipUtils.getUserIdFromFromHeader(request); + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); + if (requesterId == null || channelId == null) { + logger.info("鏃犳硶浠嶧romHeader鐨凙ddress涓幏鍙栧埌骞冲彴id锛岃繑鍥�400"); + // 鍙傛暟涓嶅叏锛� 鍙�400锛岃姹傞敊璇� + responseAck(evt, Response.BAD_REQUEST); + return; + } - } catch (SipException | InvalidArgumentException | ParseException e) { - e.printStackTrace(); - logger.warn("sdp瑙f瀽閿欒"); - e.printStackTrace(); - } catch (SdpParseException e) { - e.printStackTrace(); - } catch (SdpException e) { - e.printStackTrace(); - } - } + // 鏌ヨ璇锋眰鏄惁鏉ヨ嚜涓婄骇骞冲彴\璁惧 + ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); + if (platform == null) { + inviteFromDeviceHandle(evt, requesterId); + } else { + // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾 + DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); + GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); + PlatformCatalog catalog = storager.getCatalog(channelId); - public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt){ + MediaServerItem mediaServerItem = null; + StreamPushItem streamPushItem = 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锛屽懠鍙浆鎺ヤ腑 + } else if (channel == null && gbStream != null) { - StringBuffer content = new StringBuffer(200); - content.append("v=0\r\n"); - content.append("o="+ sendRtpItem.getChannelId() +" 0 0 IN IP4 "+ mediaServerItem.getSdpIp()+"\r\n"); - content.append("s=Play\r\n"); - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); - content.append("t=0 0\r\n"); - content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); - content.append("a=sendonly\r\n"); - content.append("a=rtpmap:96 PS/90000\r\n"); - if (sendRtpItem.isTcp()) { - content.append("a=connection:new\r\n"); - if (!sendRtpItem.isTcpActive()) { - content.append("a=setup:active\r\n"); - }else { - content.append("a=setup:passive\r\n"); - } - } - content.append("y="+ sendRtpItem.getSsrc() + "\r\n"); - content.append("f=\r\n"); + String mediaServerId = gbStream.getMediaServerId(); + mediaServerItem = mediaServerService.getOne(mediaServerId); + if (mediaServerItem == null) { + if ("proxy".equals(gbStream.getStreamType())) { + logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId); + responseAck(evt, Response.GONE); + return; + } else { + streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); + if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) { + logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId); + responseAck(evt, Response.GONE); + return; + } + } + } else { + if ("push".equals(gbStream.getStreamType())) { + streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); + if (streamPushItem == null) { + logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId); + responseAck(evt, Response.GONE); + return; + } + } + } + responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑 + } else if (catalog != null) { + responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 鐩綍涓嶆敮鎸佺偣鎾� + return; + } else { + logger.info("閫氶亾涓嶅瓨鍦紝杩斿洖404"); + responseAck(evt, Response.NOT_FOUND); // 閫氶亾涓嶅瓨鍦紝鍙�404锛岃祫婧愪笉瀛樺湪 + return; + } + // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡 + String contentString = new String(request.getRawContent()); - try { - responseSdpAck(evt, content.toString(), platform); - } catch (SipException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - } + // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎浠ヨВ鏋愩�� + int ssrcIndex = contentString.indexOf("y="); + // 妫�鏌ユ槸鍚︽湁y瀛楁 + String ssrcDefault = "0000000000"; + String ssrc; + SessionDescription sdp; + if (ssrcIndex >= 0) { + //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + String substring = contentString.substring(0, contentString.indexOf("y=")); + sdp = SdpFactory.getInstance().createSessionDescription(substring); + } else { + ssrc = ssrcDefault; + sdp = SdpFactory.getInstance().createSessionDescription(contentString); + } + String sessionName = sdp.getSessionName().getValue(); - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId, String channelId1) throws InvalidArgumentException, ParseException, SipException, SdpException { + Long startTime = null; + Long stopTime = null; + Instant start = null; + Instant end = null; + if (sdp.getTimeDescriptions(false) != null && sdp.getTimeDescriptions(false).size() > 0) { + TimeDescriptionImpl timeDescription = (TimeDescriptionImpl) (sdp.getTimeDescriptions(false).get(0)); + TimeField startTimeFiled = (TimeField) timeDescription.getTime(); + startTime = startTimeFiled.getStartTime(); + stopTime = startTimeFiled.getStopTime(); - // 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛� - Device device = redisCatchStorage.getDevice(requesterId); - AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(requesterId, channelId1); - if (audioBroadcastCatch == null) { - logger.warn("鏉ヨ嚜璁惧鐨処nvite璇锋眰闈炶闊冲箍鎾紝宸插拷鐣�"); - responseAck(evt, Response.FORBIDDEN); - return; - } - Request request = evt.getRequest(); - if (device != null) { - logger.info("鏀跺埌璁惧" + requesterId + "鐨勮闊冲箍鎾璉nvite璇锋眰"); - responseAck(evt, Response.TRYING); + start = Instant.ofEpochSecond(startTime); + end = Instant.ofEpochSecond(stopTime); + } + // 鑾峰彇鏀寔鐨勬牸寮� + Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 + //String ip = null; + int port = -1; + boolean mediaTransmissionTCP = false; + Boolean tcpActive = null; + for (Object description : mediaDescriptions) { + MediaDescription mediaDescription = (MediaDescription) description; + Media media = mediaDescription.getMedia(); - String contentString = new String(request.getRawContent()); - // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎绉婚櫎浠ヨВ鏋愩�� - String substring = contentString; - String ssrc = "0000000404"; - int ssrcIndex = contentString.indexOf("y="); - if (ssrcIndex > 0) { - substring = contentString.substring(0, ssrcIndex); - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); - } - ssrcIndex = substring.indexOf("f="); - if (ssrcIndex > 0) { - substring = contentString.substring(0, ssrcIndex); - } - SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); + Vector mediaFormats = media.getMediaFormats(false); + if (mediaFormats.contains("96")) { + port = media.getMediaPort(); + //String mediaType = media.getMediaType(); + String protocol = media.getProtocol(); - // 鑾峰彇鏀寔鐨勬牸寮� - Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp + if ("TCP/RTP/AVP".equals(protocol)) { + String setup = mediaDescription.getAttribute("setup"); + if (setup != null) { + mediaTransmissionTCP = true; + if ("active".equals(setup)) { + tcpActive = true; + // 涓嶆敮鎸乼cp涓诲姩 + responseAck(evt, Response.NOT_IMPLEMENTED, "tcp active not support"); // 鐩綍涓嶆敮鎸佺偣鎾� + return; + } else if ("passive".equals(setup)) { + tcpActive = false; + } + } + } + break; + } + } + if (port == -1) { + logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); + // 鍥炲涓嶆敮鎸佺殑鏍煎紡 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 + return; + } + String username = sdp.getOrigin().getUsername(); + String addressStr = sdp.getOrigin().getAddress(); - // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 - int port = -1; - boolean mediaTransmissionTCP = false; - Boolean tcpActive = null; - for (int i = 0; i < mediaDescriptions.size(); i++) { - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); - Media media = mediaDescription.getMedia(); + logger.info("[涓婄骇鐐规挱]鐢ㄦ埛锛歿}锛� 閫氶亾锛歿}, 鍦板潃锛歿}:{}锛� ssrc锛歿}", username, channelId, addressStr, port, ssrc); + Device device = null; + // 閫氳繃 channel 鍜� gbStream 鏄惁涓簄ull 鍊煎垽鏂潵婧愭槸鐩存挱娴佸悎閫傚浗鏍� + if (channel != null) { + device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); + if (device == null) { + logger.warn("鐐规挱骞冲彴{}鐨勯�氶亾{}鏃舵湭鎵惧埌璁惧淇℃伅", requesterId, channel); + responseAck(evt, Response.SERVER_INTERNAL_ERROR); + return; + } + mediaServerItem = playService.getNewMediaServerItem(device); + if (mediaServerItem == null) { + logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm"); + responseAck(evt, 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("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + responseAck(evt, Response.BUSY_HERE); + return; + } + sendRtpItem.setCallId(callIdHeader.getCallId()); + sendRtpItem.setPlayType("Play".equals(sessionName) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK); - Vector mediaFormats = media.getMediaFormats(false); - if (mediaFormats.contains("8")) { - port = media.getMediaPort(); - String protocol = media.getProtocol(); - // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp - if ("TCP/RTP/AVP".equals(protocol)) { - String setup = mediaDescription.getAttribute("setup"); - if (setup != null) { - mediaTransmissionTCP = true; - if ("active".equals(setup)) { - tcpActive = true; - } else if ("passive".equals(setup)) { - tcpActive = false; - } - } - } - break; - } - } - if (port == -1) { - logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); - // 鍥炲涓嶆敮鎸佺殑鏍煎紡 - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 - return; - } - String addressStr = sdp.getOrigin().getAddress(); - logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", requesterId, addressStr, port, ssrc); + Long finalStartTime = startTime; + Long finalStopTime = stopTime; + ZLMHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> { + String app = responseJSON.getString("app"); + String stream = responseJSON.getString("stream"); + logger.info("[涓婄骇鐐规挱]涓嬬骇宸茬粡寮�濮嬫帹娴併�� 鍥炲200OK(SDP)锛� {}/{}", app, stream); + // * 0 绛夊緟璁惧鎺ㄦ祦涓婃潵 + // * 1 涓嬬骇宸茬粡鎺ㄦ祦锛岀瓑寰呬笂绾у钩鍙板洖澶峚ck + // * 2 鎺ㄦ祦涓� + sendRtpItem.setStatus(1); + redisCatchStorage.updateSendRTPSever(sendRtpItem); - MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device); - if (mediaServerItem == null) { - logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm"); - responseAck(evt, Response.BUSY_HERE); - return; - } - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, - device.getDeviceId(), audioBroadcastCatch.getChannelId(), - mediaTransmissionTCP); - if (sendRtpItem == null) { - logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); - responseAck(evt, Response.BUSY_HERE); - return; - } - sendRtpItem.setTcp(mediaTransmissionTCP); - if (tcpActive != null) { - sendRtpItem.setTcpActive(tcpActive); - } - String app = "broadcast"; - String stream = device.getDeviceId() + "_" + audioBroadcastCatch.getChannelId(); + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n"); + content.append("s=" + sessionName + "\r\n"); + content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n"); + if ("Playback".equals(sessionName)) { + content.append("t=" + finalStartTime + " " + finalStopTime + "\r\n"); + } else { + content.append("t=0 0\r\n"); + } + content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("y=" + ssrc + "\r\n"); + content.append("f=\r\n"); + try { + // 瓒呮椂鏈敹鍒癆ck搴旇鍥炲bye,褰撳墠绛夊緟鏃堕棿涓�10绉� + dynamicTask.startDelay(callIdHeader.getCallId(), () -> { + logger.info("Ack 绛夊緟瓒呮椂"); + mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc); + // 鍥炲bye + cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId()); + }, 60 * 1000); + responseSdpAck(evt, content.toString(), platform); + + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + }; + SipSubscribe.Event errorEvent = ((event) -> { + // 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒 + Response response = null; + try { + response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (serverTransaction.getDialog() != null) { + serverTransaction.getDialog().delete(); + } + } catch (ParseException | SipException | InvalidArgumentException e) { + e.printStackTrace(); + } + }); + sendRtpItem.setApp("rtp"); + if ("Playback".equals(sessionName)) { + sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true, true); + sendRtpItem.setStreamId(ssrcInfo.getStream()); + // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� + redisCatchStorage.updateSendRTPSever(sendRtpItem); + playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), + DateUtil.formatter.format(end), null, result -> { + if (result.getCode() != 0) { + logger.warn("褰曞儚鍥炴斁澶辫触"); + if (result.getEvent() != null) { + errorEvent.response(result.getEvent()); + } + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); + try { + responseAck(evt, Response.REQUEST_TIMEOUT); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } else { + if (result.getMediaServerItem() != null) { + hookEvent.response(result.getMediaServerItem(), result.getResponse()); + } + } + }); + } else { + sendRtpItem.setPlayType(InviteStreamType.PLAY); + SsrcTransaction playTransaction = sessionManager.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); + if (playTransaction != null) { + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, "rtp", playTransaction.getStream()); + if (!streamReady) { + playTransaction = null; + } + } + if (playTransaction == null) { + String streamId = null; + if (mediaServerItem.isRtpEnable()) { + streamId = String.format("%s_%s", device.getDeviceId(), channelId); + } + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); + sendRtpItem.setStreamId(ssrcInfo.getStream()); + // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� + redisCatchStorage.updateSendRTPSever(sendRtpItem); + playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg) -> { + logger.info("[涓婄骇鐐规挱]瓒呮椂, 鐢ㄦ埛锛歿}锛� 閫氶亾锛歿}", username, channelId); + redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); + }, null); + } else { + sendRtpItem.setStreamId(playTransaction.getStream()); + // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� + redisCatchStorage.updateSendRTPSever(sendRtpItem); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("app", sendRtpItem.getApp()); + jsonObject.put("stream", sendRtpItem.getStreamId()); + hookEvent.response(mediaServerItem, jsonObject); + } + } + } else if (gbStream != null) { + if (streamPushItem.isStatus()) { + // 鍦ㄧ嚎鐘舵�� + pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + } else { + // 涓嶅湪绾� 鎷夎捣 + notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + } + + } + + } + + } catch (SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + logger.warn("sdp瑙f瀽閿欒"); + e.printStackTrace(); + } catch (SdpParseException e) { + e.printStackTrace(); + } catch (SdpException e) { + e.printStackTrace(); + } + } + + /** + * 瀹夋帓鎺ㄦ祦 + */ + + private void pushStream(RequestEvent evt, 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 (streamPushItem.getServerId().equals(userSetting.getServerId())) { + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + if (streamReady) { + // 鑷钩鍙板唴瀹� + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + gbStream.getApp(), gbStream.getStream(), channelId, + mediaTransmissionTCP); + + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + responseAck(evt, Response.BUSY_HERE); + return; + } + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + sendRtpItem.setPlayType(InviteStreamType.PUSH); + // 鍐欏叆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); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + sendStreamAck(mediaServerItem, sendRtpItem, platform, evt); + } else { + // 涓嶅湪绾� 鎷夎捣 + notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + } + + } else { + // 鍏朵粬骞冲彴鍐呭 + otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + } + + } + + /** + * 閫氱煡娴佷笂绾� + */ + private void notifyStreamOnline(RequestEvent evt, 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"); + } else if ("push".equals(gbStream.getStreamType())) { + if (!platform.isStartOfflinePush()) { + responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel unavailable"); + return; + } + // 鍙戦�乺edis娑堟伅浠ヤ娇璁惧涓婄嚎 + logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽彂閫乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream()); + + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(1, + gbStream.getApp(), gbStream.getStream(), gbStream.getGbId(), gbStream.getPlatformId(), + platform.getName(), null, gbStream.getMediaServerId()); + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); + // 璁剧疆瓒呮椂 + dynamicTask.startDelay(callIdHeader.getCallId(), () -> { + logger.info("[ app={}, stream={} ] 绛夊緟璁惧寮�濮嬫帹娴佽秴鏃�", gbStream.getApp(), gbStream.getStream()); + try { + mediaListManager.removedChannelOnlineEventLister(gbStream.getGbId()); + responseAck(evt, Response.REQUEST_TIMEOUT); // 瓒呮椂 + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + }, userSetting.getPlatformPlayTimeout()); + // 娣诲姞鐩戝惉 + int finalPort = port; + Boolean finalTcpActive = tcpActive; + + // 娣诲姞鍦ㄦ湰鏈轰笂绾跨殑閫氱煡 + mediaListManager.addChannelOnlineEventLister(gbStream.getGbId(), (app, stream, serverId) -> { + dynamicTask.stop(callIdHeader.getCallId()); + if (serverId.equals(userSetting.getServerId())) { + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, + app, stream, channelId, mediaTransmissionTCP); + + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + try { + responseAck(evt, Response.BUSY_HERE); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return; + } + if (finalTcpActive != null) { + sendRtpItem.setTcpActive(finalTcpActive); + } + sendRtpItem.setPlayType(InviteStreamType.PUSH); + // 鍐欏叆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); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + sendStreamAck(mediaServerItem, sendRtpItem, platform, evt); + } else { + // 鍏朵粬骞冲彴鍐呭 + otherWvpPushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + } + }); + } + } + + /** + * 鏉ヨ嚜鍏朵粬wvp鐨勬帹娴� + */ + private void otherWvpPushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, + CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + int port, Boolean tcpActive, boolean mediaTransmissionTCP, + String channelId, String addressStr, String ssrc, String requesterId) { + logger.info("[绾ц仈鐐规挱]鐩存挱娴佹潵鑷叾浠栧钩鍙帮紝鍙戦�乺edis娑堟伅"); + // 鍙戦�乺edis娑堟伅 + redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(), + streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId, + channelId, mediaTransmissionTCP, null, responseSendItemMsg -> { + SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem(); + if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + try { + responseAck(evt, Response.BUSY_HERE); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return; + } + // 鏀跺埌sendItem + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + sendRtpItem.setPlayType(InviteStreamType.PUSH); + // 鍐欏叆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); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + sendStreamAck(responseSendItemMsg.getMediaServerItem(), sendRtpItem, platform, evt); + }, (wvpResult) -> { + try { + // 閿欒 + if (wvpResult.getCode() == RedisGbPlayMsgListener.ERROR_CODE_OFFLINE) { + // 绂荤嚎 + // 鏌ヨ鏄惁鍦ㄦ湰鏈轰笂绾夸簡 + StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream()); + if (currentStreamPushItem.isStatus()) { + // 鍦ㄧ嚎鐘舵�� + pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + + } else { + // 涓嶅湪绾� 鎷夎捣 + notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); + } + } + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } catch (SipException e) { + throw new RuntimeException(e); + } + + + try { + responseAck(evt, Response.BUSY_HERE); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return; + }); + } + + public void sendStreamAck(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { + + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o=" + sendRtpItem.getChannelId() + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); + content.append("t=0 0\r\n"); + content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + if (sendRtpItem.isTcp()) { + content.append("a=connection:new\r\n"); + if (!sendRtpItem.isTcpActive()) { + content.append("a=setup:active\r\n"); + } else { + content.append("a=setup:passive\r\n"); + } + } + content.append("y=" + sendRtpItem.getSsrc() + "\r\n"); + content.append("f=\r\n"); + + try { + responseSdpAck(evt, content.toString(), platform); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { + + // 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛� + Device device = redisCatchStorage.getDevice(requesterId); + Request request = evt.getRequest(); + if (device != null) { + logger.info("鏀跺埌璁惧" + requesterId + "鐨勮闊冲箍鎾璉nvite璇锋眰"); + responseAck(evt, Response.TRYING); + + String contentString = new String(request.getRawContent()); + // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎绉婚櫎浠ヨВ鏋愩�� + String substring = contentString; + String ssrc = "0000000404"; + int ssrcIndex = contentString.indexOf("y="); + if (ssrcIndex > 0) { + substring = contentString.substring(0, ssrcIndex); + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + } + ssrcIndex = substring.indexOf("f="); + if (ssrcIndex > 0) { + substring = contentString.substring(0, ssrcIndex); + } + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); + + // 鑾峰彇鏀寔鐨勬牸寮� + Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 + int port = -1; + //boolean recvonly = false; + boolean mediaTransmissionTCP = false; + Boolean tcpActive = null; + for (int i = 0; i < mediaDescriptions.size(); i++) { + MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i); + Media media = mediaDescription.getMedia(); + + Vector mediaFormats = media.getMediaFormats(false); + if (mediaFormats.contains("8")) { + port = media.getMediaPort(); + String protocol = media.getProtocol(); + // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp + if ("TCP/RTP/AVP".equals(protocol)) { + String setup = mediaDescription.getAttribute("setup"); + if (setup != null) { + mediaTransmissionTCP = true; + if ("active".equals(setup)) { + tcpActive = true; + } else if ("passive".equals(setup)) { + tcpActive = false; + } + } + } + break; + } + } + if (port == -1) { + logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); + // 鍥炲涓嶆敮鎸佺殑鏍煎紡 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 + return; + } + String username = sdp.getOrigin().getUsername(); + String addressStr = sdp.getOrigin().getAddress(); + logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", username, addressStr, port, ssrc); + + } else { + logger.warn("鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹�"); + responseAck(evt, Response.BAD_REQUEST); + } + } CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); sendRtpItem.setPlayType(InviteStreamType.PLAY); sendRtpItem.setCallId(callIdHeader.getCallId()); 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 e923a54..7e66658 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 @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; @@ -18,6 +17,7 @@ import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 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.redis.RedisUtil; import org.dom4j.DocumentException; import org.dom4j.Element; @@ -25,6 +25,8 @@ 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.StringUtils; @@ -35,6 +37,7 @@ import javax.sip.message.Response; import java.text.ParseException; import java.util.Iterator; +import java.util.concurrent.ConcurrentLinkedQueue; /** * SIP鍛戒护绫诲瀷锛� NOTIFY璇锋眰 @@ -63,10 +66,18 @@ @Autowired private EventPublisher publisher; - private String method = "NOTIFY"; + private final String method = "NOTIFY"; @Autowired private SIPProcessorObserver sipProcessorObserver; + + private boolean taskQueueHandlerRun = false; + + private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; @Override public void afterPropertiesSet() throws Exception { @@ -77,23 +88,40 @@ @Override public void process(RequestEvent evt) { try { - Element rootElement = getRootElement(evt); - String cmd = XmlUtil.getText(rootElement, "CmdType"); - if (CmdType.CATALOG.equals(cmd)) { - logger.info("鎺ユ敹鍒癈atalog閫氱煡"); - processNotifyCatalogList(evt); - } else if (CmdType.ALARM.equals(cmd)) { - logger.info("鎺ユ敹鍒癆larm閫氱煡"); - processNotifyAlarm(evt); - } else if (CmdType.MOBILE_POSITION.equals(cmd)) { - logger.info("鎺ユ敹鍒癕obilePosition閫氱煡"); - processNotifyMobilePosition(evt); - } else { - logger.info("鎺ユ敹鍒版秷鎭細" + cmd); - responseAck(evt, Response.OK); + taskQueue.offer(new HandlerCatchData(evt, null, null)); + responseAck(evt, Response.OK); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(()-> { + while (!taskQueue.isEmpty()) { + try { + HandlerCatchData take = taskQueue.poll(); + Element rootElement = getRootElement(take.getEvt()); + String cmd = XmlUtil.getText(rootElement, "CmdType"); + + if (CmdType.CATALOG.equals(cmd)) { + logger.info("鎺ユ敹鍒癈atalog閫氱煡"); + processNotifyCatalogList(take.getEvt()); + } else if (CmdType.ALARM.equals(cmd)) { + logger.info("鎺ユ敹鍒癆larm閫氱煡"); + processNotifyAlarm(take.getEvt()); + } else if (CmdType.MOBILE_POSITION.equals(cmd)) { + logger.info("鎺ユ敹鍒癕obilePosition閫氱煡"); + processNotifyMobilePosition(take.getEvt()); + } else { + logger.info("鎺ユ敹鍒版秷鎭細" + cmd); + } + } catch (DocumentException e) { + throw new RuntimeException(e); + } + } + taskQueueHandlerRun = false; + }); } - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + + + } catch (SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); } } @@ -166,8 +194,7 @@ jsonObject.put("direction", mobilePosition.getDirection()); jsonObject.put("speed", mobilePosition.getSpeed()); redisCatchStorage.sendMobilePositionMsg(jsonObject); - responseAck(evt, Response.OK); - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + } catch (DocumentException e) { e.printStackTrace(); } } @@ -188,6 +215,7 @@ Device device = redisCatchStorage.getDevice(deviceId); if (device == null) { + logger.warn("[ NotifyAlarm ] 鏈壘鍒拌澶囷細{}", deviceId); return; } rootElement = getRootElement(evt, device.getCharset()); @@ -195,7 +223,12 @@ deviceAlarm.setDeviceId(deviceId); deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); - deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); + String alarmTime = XmlUtil.getText(rootElement, "AlarmTime"); + if (alarmTime == null) { + logger.warn("[ NotifyAlarm ] AlarmTime cannot be null"); + return; + } + deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { deviceAlarm.setAlarmDescription(""); } else { @@ -212,7 +245,7 @@ deviceAlarm.setLatitude(0.00); } logger.info("[鏀跺埌Notify-Alarm]锛歿}/{}", device.getDeviceId(), deviceAlarm.getChannelId()); - if (deviceAlarm.getAlarmMethod().equals("4")) { + if ("4".equals(deviceAlarm.getAlarmMethod())) { MobilePosition mobilePosition = new MobilePosition(); mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); mobilePosition.setTime(deviceAlarm.getAlarmTime()); @@ -233,11 +266,10 @@ // TODO: 闇�瑕佸疄鐜板瓨鍌ㄦ姤璀︿俊鎭�佹姤璀﹀垎绫� // 鍥炲200 OK - responseAck(evt, Response.OK); if (redisCatchStorage.deviceIsOnline(deviceId)) { publisher.deviceAlarmEventPublish(deviceAlarm); } - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + } catch (DocumentException e) { e.printStackTrace(); } } @@ -273,64 +305,60 @@ continue; } Element eventElement = itemDevice.element("Event"); - DeviceChannel channel = XmlUtil.channelContentHander(itemDevice); + String event; + if (eventElement == null) { + logger.warn("[鏀跺埌 鐩綍璁㈤槄]锛歿}, 浣嗘槸Event涓虹┖, 璁句负榛樿鍊� ADD", (device != null ? device.getDeviceId():"" )); + event = CatalogEvent.ADD; + }else { + event = eventElement.getText().toUpperCase(); + } + DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device); channel.setDeviceId(device.getDeviceId()); logger.info("[鏀跺埌 鐩綍璁㈤槄]锛歿}/{}", device.getDeviceId(), channel.getChannelId()); - switch (eventElement.getText().toUpperCase()) { + switch (event) { case CatalogEvent.ON: // 涓婄嚎 logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾銆恵}銆戜笂绾块�氱煡", device.getDeviceId(), channel.getChannelId()); storager.deviceChannelOnline(deviceId, channel.getChannelId()); - // 鍥炲200 OK - responseAck(evt, Response.OK); break; case CatalogEvent.OFF : // 绂荤嚎 logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾銆恵}銆戠绾块�氱煡", device.getDeviceId(), channel.getChannelId()); storager.deviceChannelOffline(deviceId, channel.getChannelId()); - // 鍥炲200 OK - responseAck(evt, Response.OK); break; case CatalogEvent.VLOST: // 瑙嗛涓㈠け logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾銆恵}銆戣棰戜涪澶遍�氱煡", device.getDeviceId(), channel.getChannelId()); storager.deviceChannelOffline(deviceId, channel.getChannelId()); - // 鍥炲200 OK - responseAck(evt, Response.OK); break; case CatalogEvent.DEFECT: // 鏁呴殰 - // 鍥炲200 OK - responseAck(evt, Response.OK); break; case CatalogEvent.ADD: // 澧炲姞 logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑澧炲姞閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId()); storager.updateChannel(deviceId, channel); - responseAck(evt, Response.OK); break; case CatalogEvent.DEL: // 鍒犻櫎 logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑鍒犻櫎閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId()); storager.delChannel(deviceId, channel.getChannelId()); - responseAck(evt, Response.OK); break; case CatalogEvent.UPDATE: // 鏇存柊 logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑鏇存柊閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId()); storager.updateChannel(deviceId, channel); - responseAck(evt, Response.OK); break; default: - responseAck(evt, Response.BAD_REQUEST, "event not found"); + logger.warn("[ NotifyCatalog ] event not found 锛� {}", event ); } // 杞彂鍙樺寲淇℃伅 - eventPublisher.catalogEventPublish(null, channel, eventElement.getText().toUpperCase()); + eventPublisher.catalogEventPublish(null, channel, event); } } - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + } catch (DocumentException e) { e.printStackTrace(); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index 47a4e00..c2226a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -1,17 +1,13 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; -import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; +import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; import com.genersoft.iot.vmp.service.IDeviceService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sip.RequestEventExt; import gov.nist.javax.sip.address.AddressImpl; @@ -45,19 +41,10 @@ private final Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class); - public String method = "REGISTER"; + public final String method = "REGISTER"; @Autowired private SipConfig sipConfig; - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired - private IVideoManagerStorage storager; - - @Autowired - private EventPublisher publisher; @Autowired private SIPProcessorObserver sipProcessorObserver; @@ -86,7 +73,7 @@ ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); Response response = null; boolean passwordCorrect = false; - // 娉ㄥ唽鏍囧織 0锛氭湭鎼哄甫鎺堟潈澶存垨鑰呭瘑鐮侀敊璇� 1锛氭敞鍐屾垚鍔� 2锛氭敞閿�鎴愬姛 + // 娉ㄥ唽鏍囧織 boolean registerFlag = false; FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); AddressImpl address = (AddressImpl) fromHeader.getAddress(); @@ -105,7 +92,6 @@ // 鏍¢獙瀵嗙爜鏄惁姝g‘ passwordCorrect = StringUtils.isEmpty(sipConfig.getPassword()) || new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, sipConfig.getPassword()); - // 鏈惡甯︽巿鏉冨ご鎴栬�呭瘑鐮侀敊璇� 鍥炲401 if (!passwordCorrect) { // 娉ㄥ唽澶辫触 @@ -154,6 +140,7 @@ device = new Device(); device.setStreamMode("UDP"); device.setCharset("GB2312"); + device.setGeoCoordSys("WGS84"); device.setDeviceId(deviceId); } device.setIp(received); 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 548dbde..d9d9479 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 @@ -82,7 +82,6 @@ @Override public void process(RequestEvent evt) { Request request = evt.getRequest(); - try { Element rootElement = getRootElement(evt); String cmd = XmlUtil.getText(rootElement, "CmdType"); @@ -176,6 +175,8 @@ } private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException { + + System.out.println(evt.getRequest().toString()); String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); String deviceId = XmlUtil.getText(rootElement, "DeviceID"); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); 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 new file mode 100644 index 0000000..a1e98f9 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java @@ -0,0 +1,143 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info; + +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.*; +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.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import gov.nist.javax.sip.message.SIPRequest; +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.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.SipException; +import javax.sip.header.*; +import javax.sip.message.Response; +import java.text.ParseException; + +@Component +public class InfoRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { + + private final static Logger logger = LoggerFactory.getLogger(InfoRequestProcessor.class); + + private final String method = "INFO"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Autowired + private IVideoManagerStorage storage; + + @Autowired + private SipSubscribe sipSubscribe; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IVideoManagerStorage storager; + + @Autowired + private SIPCommander cmder; + + @Autowired + private VideoStreamSessionManager sessionManager; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + @Override + public void process(RequestEvent evt) { + logger.debug("鎺ユ敹鍒版秷鎭細" + evt.getRequest()); + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); + // 鍏堜粠浼氳瘽鍐呮煡鎵� + SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); + if (ssrcTransaction != null) { // 鍏煎娴峰悍 濯掍綋閫氱煡 娑堟伅from瀛楁涓嶆槸璁惧ID鐨勯棶棰� + deviceId = ssrcTransaction.getDeviceId(); + } + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = redisCatchStorage.getDevice(deviceId); + // 鏌ヨ涓婄骇骞冲彴鏄惁瀛樺湪 + ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); + try { + if (device != null && parentPlatform != null) { + logger.warn("[閲嶅]骞冲彴涓庤澶囩紪鍙烽噸澶嶏細{}", deviceId); + SIPRequest request = (SIPRequest) evt.getRequest(); + String hostAddress = request.getRemoteAddress().getHostAddress(); + int remotePort = request.getRemotePort(); + if (device.getHostAddress().equals(hostAddress + ":" + remotePort)) { + parentPlatform = null; + }else { + device = null; + } + } + if (device == null && parentPlatform == null) { + // 涓嶅瓨鍦ㄥ垯鍥炲404 + responseAck(evt, 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())); + sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult); + }; + }else { + ContentTypeHeader header = (ContentTypeHeader)evt.getRequest().getHeader(ContentTypeHeader.NAME); + String contentType = header.getContentType(); + String contentSubType = header.getContentSubType(); + if ("Application".equals(contentType) && "MANSRTSP".equals(contentSubType)) { + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); + String streamId = sendRtpItem.getStreamId(); + StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); + if (null == streamInfo) { + responseAck(evt, 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); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + }, eventResult -> { + // 鎴愬姛鐨勫洖澶� + try { + responseAck(evt, eventResult.statusCode); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + }); + } + } + } catch (SipException e) { + logger.warn("SIP 鍥炲閿欒", e); + } catch (InvalidArgumentException e) { + logger.warn("鍙傛暟鏃犳晥", e); + } catch (ParseException e) { + logger.warn("SIP鍥炲鏃惰В鏋愬紓甯�", 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 136b912..cd85889 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 @@ -72,7 +72,7 @@ String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); // 鍏堜粠浼氳瘽鍐呮煡鎵� - SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, null, callIdHeader.getCallId()); + SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); if (ssrcTransaction != null) { // 鍏煎娴峰悍 濯掍綋閫氱煡 娑堟伅from瀛楁涓嶆槸璁惧ID鐨勯棶棰� deviceId = ssrcTransaction.getDeviceId(); } 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 b7e222d..6a23dfa 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 @@ -9,9 +9,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.service.IDeviceAlarmService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,7 +86,11 @@ deviceAlarm.setChannelId(channelId); deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority")); deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod")); - deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime")); + 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(""); @@ -175,7 +181,11 @@ deviceAlarm.setChannelId(channelId); deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority")); deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod")); - deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime")); + 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(""); 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 cf07250..c429457 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 @@ -64,16 +64,14 @@ device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); } device.setKeepaliveTime(DateUtil.getNow()); + // 鍥炲200 OK + responseAck(evt, Response.OK); if (device.getOnline() == 1) { - // 鍥炲200 OK - responseAck(evt, Response.OK); deviceService.updateDevice(device); }else { // 瀵逛簬宸茬粡绂荤嚎鐨勮澶囧垽鏂粬鐨勬敞鍐屾槸鍚﹀凡缁忚繃鏈� if (!deviceService.expire(device)){ deviceService.online(device); - // 鍥炲200 OK - responseAck(evt, Response.OK); } } } catch (SipException e) { 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 4cf9768..8a5ef79 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 @@ -3,11 +3,16 @@ import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 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.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +42,16 @@ private SIPCommander cmder; @Autowired + private SIPCommanderFroPlatform sipCommanderFroPlatform; + + @Autowired private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IVideoManagerStorage storage; + + @Autowired + private VideoStreamSessionManager sessionManager; @Override public void afterPropertiesSet() throws Exception { @@ -59,17 +73,32 @@ } CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); String NotifyType =getText(rootElement, "NotifyType"); - if (NotifyType.equals("121")){ + if ("121".equals(NotifyType)){ logger.info("[褰曞儚娴乚鎺ㄩ�佸畬姣曪紝鏀跺埌鍏虫祦閫氱煡"); - String channelId =getText(rootElement, "DeviceID"); // 鏌ヨ鏄澶� - StreamInfo streamInfo = redisCatchStorage.queryDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); - // 璁剧疆杩涘害100% - streamInfo.setProgress(1); - redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId()); - cmder.streamByeCmd(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); - // TODO 濡傛灉绾ц仈鎾斁锛岄渶瑕佺粰涓婄骇鍙戦�佹閫氱煡 + StreamInfo streamInfo = redisCatchStorage.queryDownload(null, null, null, callIdHeader.getCallId()); + if (streamInfo != null) { + // 璁剧疆杩涘害100% + streamInfo.setProgress(1); + redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId()); + } + // 鍏堜粠浼氳瘽鍐呮煡鎵� + SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); + if (ssrcTransaction != null) { // 鍏煎娴峰悍 濯掍綋閫氱煡 娑堟伅from瀛楁涓嶆槸璁惧ID鐨勯棶棰� + cmder.streamByeCmd(device.getDeviceId(), ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); + + // 濡傛灉绾ц仈鎾斁锛岄渶瑕佺粰涓婄骇鍙戦�佹閫氱煡 TODO 澶氫釜涓婄骇鍚屾椂瑙傜湅涓�涓笅绾� 鍙兘瀛樺湪鍋滈敊鐨勯棶棰橈紝闇�瑕佸皢鐐规挱CallId杩涜涓婁笅绾х粦瀹� + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null); + if (sendRtpItem != null) { + ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); + if (parentPlatform == null) { + logger.warn("[绾ц仈娑堟伅鍙戦�乚锛氬彂閫丮ediaStatus鍙戠幇涓婄骇骞冲彴{}涓嶅瓨鍦�", sendRtpItem.getPlatformId()); + return; + } + sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem); + } + } } } 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 891b21d..c4e88c5 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 @@ -20,6 +20,8 @@ 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.StringUtils; @@ -31,6 +33,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; @Component public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -38,8 +41,12 @@ private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class); private final String cmdType = "Catalog"; + private boolean taskQueueHandlerRun = false; + @Autowired private ResponseMessageHandler responseMessageHandler; + + private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); @Autowired private IVideoManagerStorage storager; @@ -63,6 +70,10 @@ @Autowired private IRedisCatchStorage redisCatchStorage; + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + @Override public void afterPropertiesSet() throws Exception { responseMessageHandler.addHandler(cmdType, this); @@ -70,68 +81,88 @@ @Override public void handForDevice(RequestEvent evt, Device device, Element element) { - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + device.getDeviceId(); - Element rootElement = null; + taskQueue.offer(new HandlerCatchData(evt, device, element)); + // 鍥炲200 OK try { - rootElement = getRootElement(evt, device.getCharset()); - Element deviceListElement = rootElement.element("DeviceList"); - Element sumNumElement = rootElement.element("SumNum"); - Element snElement = rootElement.element("SN"); - if (snElement == null || sumNumElement == null || deviceListElement == null) { - responseAck(evt, Response.BAD_REQUEST, "xml error"); - return; - } - int sumNum = Integer.parseInt(sumNumElement.getText()); - - if (sumNum == 0) { - // 鏁版嵁宸茬粡瀹屾暣鎺ユ敹 - storager.cleanChannelsForDevice(device.getDeviceId()); - catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null); - }else { - Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); - if (deviceListIterator != null) { - List<DeviceChannel> channelList = new ArrayList<>(); - // 閬嶅巻DeviceList - while (deviceListIterator.hasNext()) { - Element itemDevice = deviceListIterator.next(); - Element channelDeviceElement = itemDevice.element("DeviceID"); - if (channelDeviceElement == null) { - continue; + responseAck(evt, Response.OK); + } catch (SipException e) { + throw new RuntimeException(e); + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(()-> { + while (!taskQueue.isEmpty()) { + HandlerCatchData take = taskQueue.poll(); + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + take.getDevice().getDeviceId(); + Element rootElement = null; + try { + rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset()); + Element deviceListElement = rootElement.element("DeviceList"); + 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"); + return; } - //by brewswang -// if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//濡傛灉鍖呭惈浣嶇疆淇℃伅锛屽氨鏇存柊涓�涓嬩綅缃� -// processNotifyMobilePosition(evt, itemDevice); -// } - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice); - deviceChannel.setDeviceId(device.getDeviceId()); + int sumNum = Integer.parseInt(sumNumElement.getText()); - channelList.add(deviceChannel); - } - int sn = Integer.parseInt(snElement.getText()); - catalogDataCatch.put(device.getDeviceId(), sn, sumNum, device, channelList); - logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾: {}涓紝{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(device.getDeviceId()) == null ? 0 :catalogDataCatch.get(device.getDeviceId()).size(), sumNum); - if (catalogDataCatch.get(device.getDeviceId()).size() == sumNum) { - // 鏁版嵁宸茬粡瀹屾暣鎺ユ敹 - boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(device.getDeviceId())); - if (!resetChannelsResult) { - String errorMsg = "鎺ユ敹鎴愬姛锛屽啓鍏ュけ璐ワ紝鍏�" + sumNum + "鏉★紝宸叉帴鏀�" + catalogDataCatch.get(device.getDeviceId()).size() + "鏉�"; - catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), errorMsg); + if (sumNum == 0) { + // 鏁版嵁宸茬粡瀹屾暣鎺ユ敹 + storager.cleanChannelsForDevice(take.getDevice().getDeviceId()); + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null); }else { - catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null); + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); + if (deviceListIterator != null) { + List<DeviceChannel> channelList = new ArrayList<>(); + // 閬嶅巻DeviceList + while (deviceListIterator.hasNext()) { + Element itemDevice = deviceListIterator.next(); + Element channelDeviceElement = itemDevice.element("DeviceID"); + if (channelDeviceElement == null) { + continue; + } + //by brewswang + // if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//濡傛灉鍖呭惈浣嶇疆淇℃伅锛屽氨鏇存柊涓�涓嬩綅缃� + // processNotifyMobilePosition(evt, itemDevice); + // } + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device); + deviceChannel.setDeviceId(take.getDevice().getDeviceId()); + + channelList.add(deviceChannel); + } + int sn = Integer.parseInt(snElement.getText()); + catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList); + logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾: {}涓紝{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum); + if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) { + // 鏁版嵁宸茬粡瀹屾暣鎺ユ敹 + boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId())); + if (!resetChannelsResult) { + String errorMsg = "鎺ユ敹鎴愬姛锛屽啓鍏ュけ璐ワ紝鍏�" + sumNum + "鏉★紝宸叉帴鏀�" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "鏉�"; + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg); + }else { + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null); + } + } + } + } + } catch (DocumentException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } catch (SipException e) { + e.printStackTrace(); } } - // 鍥炲200 OK - responseAck(evt, Response.OK); - } - } catch (DocumentException e) { - e.printStackTrace(); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } catch (SipException e) { - e.printStackTrace(); + taskQueueHandlerRun = false; + }); + } } 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 1fed401..17738a5 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 @@ -82,7 +82,7 @@ deviceService.offline(device.getDeviceId()); } RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId() + channelId); + msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId()); msg.setData(json); deferredResultHolder.invokeAllResult(msg); } 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 4509e42..57e8045 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 @@ -1,9 +1,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; -import com.genersoft.iot.vmp.gb28181.bean.RecordItem; +import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.session.RecordDataCatch; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -19,6 +16,8 @@ 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.StringUtils; @@ -28,6 +27,9 @@ import javax.sip.message.Response; import java.text.ParseException; import java.util.*; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingQueue; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; @@ -38,10 +40,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { private Logger logger = LoggerFactory.getLogger(RecordInfoResponseMessageHandler.class); - public static volatile List<String> threadNameList = new ArrayList(); private final String cmdType = "RecordInfo"; - private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_"; + private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); + + private boolean taskQueueHandlerRun = false; @Autowired private ResponseMessageHandler responseMessageHandler; @@ -51,10 +54,12 @@ @Autowired private DeferredResultHolder deferredResultHolder; - - @Autowired private EventPublisher eventPublisher; + + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; @Override public void afterPropertiesSet() throws Exception { @@ -67,66 +72,88 @@ // 鍥炲200 OK try { responseAck(evt, Response.OK); + taskQueue.offer(new HandlerCatchData(evt, device, rootElement)); + if (!taskQueueHandlerRun) { + taskQueueHandlerRun = true; + taskExecutor.execute(()->{ + try { + while (!taskQueue.isEmpty()) { + HandlerCatchData take = taskQueue.poll(); + Element rootElementForCharset = getRootElement(take.getEvt(), take.getDevice().getCharset()); + String sn = getText(rootElementForCharset, "SN"); + String channelId = getText(rootElementForCharset, "DeviceID"); + RecordInfo recordInfo = new RecordInfo(); + recordInfo.setChannelId(channelId); + recordInfo.setDeviceId(take.getDevice().getDeviceId()); + recordInfo.setSn(sn); + recordInfo.setName(getText(rootElementForCharset, "Name")); + String sumNumStr = getText(rootElementForCharset, "SumNum"); + int sumNum = 0; + if (!StringUtils.isEmpty(sumNumStr)) { + sumNum = Integer.parseInt(sumNumStr); + } + recordInfo.setSumNum(sumNum); + Element recordListElement = rootElementForCharset.element("RecordList"); + if (recordListElement == null || sumNum == 0) { + logger.info("鏃犲綍鍍忔暟鎹�"); + eventPublisher.recordEndEventPush(recordInfo); + recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, new ArrayList<>()); + releaseRequest(take.getDevice().getDeviceId(), sn); + } else { + Iterator<Element> recordListIterator = recordListElement.elementIterator(); + if (recordListIterator != null) { + List<RecordItem> recordList = new ArrayList<>(); + // 閬嶅巻DeviceList + while (recordListIterator.hasNext()) { + Element itemRecord = recordListIterator.next(); + Element recordElement = itemRecord.element("DeviceID"); + if (recordElement == null) { + logger.info("璁板綍涓虹┖锛屼笅涓�涓�..."); + continue; + } + RecordItem record = new RecordItem(); + record.setDeviceId(getText(itemRecord, "DeviceID")); + record.setName(getText(itemRecord, "Name")); + record.setFilePath(getText(itemRecord, "FilePath")); + record.setFileSize(getText(itemRecord, "FileSize")); + record.setAddress(getText(itemRecord, "Address")); - rootElement = getRootElement(evt, device.getCharset()); - String sn = getText(rootElement, "SN"); + String startTimeStr = getText(itemRecord, "StartTime"); + record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr)); - String sumNumStr = getText(rootElement, "SumNum"); - int sumNum = 0; - if (!StringUtils.isEmpty(sumNumStr)) { - sumNum = Integer.parseInt(sumNumStr); - } - Element recordListElement = rootElement.element("RecordList"); - if (recordListElement == null || sumNum == 0) { - logger.info("鏃犲綍鍍忔暟鎹�"); - recordDataCatch.put(device.getDeviceId(), sn, sumNum, new ArrayList<>()); - releaseRequest(device.getDeviceId(), sn); - } else { - Iterator<Element> recordListIterator = recordListElement.elementIterator(); - if (recordListIterator != null) { - List<RecordItem> recordList = new ArrayList<>(); - // 閬嶅巻DeviceList - while (recordListIterator.hasNext()) { - Element itemRecord = recordListIterator.next(); - Element recordElement = itemRecord.element("DeviceID"); - if (recordElement == null) { - logger.info("璁板綍涓虹┖锛屼笅涓�涓�..."); - continue; + String endTimeStr = getText(itemRecord, "EndTime"); + record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr)); + + record.setSecrecy(itemRecord.element("Secrecy") == null ? 0 + : Integer.parseInt(getText(itemRecord, "Secrecy"))); + record.setType(getText(itemRecord, "Type")); + record.setRecorderId(getText(itemRecord, "RecorderID")); + recordList.add(record); + } + recordInfo.setRecordList(recordList); + // 鍙戦�佹秷鎭紝濡傛灉鏄笂绾ф煡璇㈡褰曞儚锛屽垯浼氶�氳繃杩欓噷閫氱煡缁欎笂绾� + eventPublisher.recordEndEventPush(recordInfo); + int count = recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, recordList); + logger.info("[鍥芥爣褰曞儚]锛� {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum); + } + + if (recordDataCatch.isComplete(take.getDevice().getDeviceId(), sn)){ + releaseRequest(take.getDevice().getDeviceId(), sn); + } + } } - RecordItem record = new RecordItem(); - record.setDeviceId(getText(itemRecord, "DeviceID")); - record.setName(getText(itemRecord, "Name")); - record.setFilePath(getText(itemRecord, "FilePath")); - record.setFileSize(getText(itemRecord, "FileSize")); - record.setAddress(getText(itemRecord, "Address")); - - String startTimeStr = getText(itemRecord, "StartTime"); - record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr)); - - String endTimeStr = getText(itemRecord, "EndTime"); - record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr)); - - record.setSecrecy(itemRecord.element("Secrecy") == null ? 0 - : Integer.parseInt(getText(itemRecord, "Secrecy"))); - record.setType(getText(itemRecord, "Type")); - record.setRecorderId(getText(itemRecord, "RecorderID")); - recordList.add(record); + taskQueueHandlerRun = false; + }catch (DocumentException e) { + throw new RuntimeException(e); } - int count = recordDataCatch.put(device.getDeviceId(), sn, sumNum, recordList); - logger.info("[鍥芥爣褰曞儚]锛� {}->{}: {}/{}", device.getDeviceId(), sn, count, sumNum); - } - - if (recordDataCatch.isComplete(device.getDeviceId(), sn)){ - releaseRequest(device.getDeviceId(), sn); - } + }); } + } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { e.printStackTrace(); } catch (ParseException e) { - e.printStackTrace(); - } catch (DocumentException e) { e.printStackTrace(); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java index 64933b8..ff63fad 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java @@ -17,7 +17,7 @@ @Component public class ByeResponseProcessor extends SIPResponseProcessorAbstract { - private String method = "BYE"; + private final String method = "BYE"; @Autowired private SipLayer sipLayer; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java index 80d7e2b..775beeb 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java @@ -17,7 +17,7 @@ @Component public class CancelResponseProcessor extends SIPResponseProcessorAbstract { - private String method = "CANCEL"; + private final String method = "CANCEL"; @Autowired private SipLayer sipLayer; 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 c81aabb..89958e9 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 @@ -31,7 +31,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class); - private String method = "INVITE"; + private final String method = "INVITE"; @Autowired private SipLayer sipLayer; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java index 02f5e1d..f3a9f65 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java @@ -27,7 +27,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class); - private String method = "REGISTER"; + private final String method = "REGISTER"; @Autowired private ISIPCommanderForPlatform sipCommanderForPlatform; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index 2caab0f..5ada1e4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import org.dom4j.Attribute; import org.dom4j.Document; @@ -180,7 +181,7 @@ return xml.getRootElement(); } - public static DeviceChannel channelContentHander(Element itemDevice){ + public static DeviceChannel channelContentHander(Element itemDevice, Device device){ Element channdelNameElement = itemDevice.element("Name"); String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; Element statusElement = itemDevice.element("Status"); @@ -254,6 +255,8 @@ }else if (deviceChannel.getChannelId().length() == 20) { if (Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216) { // 铏氭嫙缁勭粐 deviceChannel.setParentId(businessGroupID); + }else if (Integer.parseInt(device.getDeviceId().substring(10, 13) )== 118) {//NVR 濡傛灉涓婄骇璁惧缂栧彿鏄疦VR鍒欑洿鎺ュ皢NVR鐨勭紪鍙疯缃粰閫氶亾鐨勪笂绾х紪鍙� + deviceChannel.setParentId(device.getDeviceId()); }else if (deviceChannel.getCivilCode() != null) { // 璁惧锛� 鏃爌arentId鐨�20浣嶆槸浣跨敤CivilCode琛ㄧず涓婄骇鐨勮澶囷紝 // 娉細215 涓氬姟鍒嗙粍鏄渶瑕佹湁parentId鐨� @@ -308,6 +311,31 @@ } else { deviceChannel.setLatitude(0.00); } + if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) { + if ("WGS84".equals(device.getGeoCoordSys())) { + deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); + deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); + Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude()); + deviceChannel.setLongitudeGcj02(position[0]); + deviceChannel.setLatitudeGcj02(position[1]); + }else if ("GCJ02".equals(device.getGeoCoordSys())) { + deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude()); + deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude()); + Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude()); + deviceChannel.setLongitudeWgs84(position[0]); + deviceChannel.setLatitudeWgs84(position[1]); + }else { + deviceChannel.setLongitudeGcj02(0.00); + deviceChannel.setLatitudeGcj02(0.00); + deviceChannel.setLongitudeWgs84(0.00); + deviceChannel.setLatitudeWgs84(0.00); + } + }else { + deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude()); + deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude()); + deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); + deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); + } if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) { //鍏煎INFO涓殑淇℃伅 Element info = itemDevice.element("Info"); 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 7f62968..4ea9cf1 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 @@ -11,7 +11,6 @@ import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.media.zlm.dto.*; import com.genersoft.iot.vmp.service.*; @@ -92,10 +91,9 @@ public ResponseEntity<String> onServerKeepalive(@RequestBody JSONObject json){ if (logger.isDebugEnabled()) { - logger.debug("[ ZLM HOOK ]on_server_keepalive API璋冪敤锛屽弬鏁帮細" + json.toString()); + logger.debug("[ ZLM HOOK ] on_server_keepalive API璋冪敤锛屽弬鏁帮細" + json.toString()); } String mediaServerId = json.getString("mediaServerId"); - List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_keepalive); if (subscribes != null && subscribes.size() > 0) { for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { @@ -165,7 +163,6 @@ if (mediaInfo != null) { subscribe.response(mediaInfo, json); } - } JSONObject ret = new JSONObject(); ret.put("code", 0); @@ -241,6 +238,23 @@ if (logger.isDebugEnabled()) { logger.debug("[ ZLM HOOK ]on_record_mp4 API璋冪敤锛屽弬鏁帮細" + json.toString()); + } + String mediaServerId = json.getString("mediaServerId"); + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("msg", "success"); + return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); + } + /** + * 褰曞埗hls瀹屾垚鍚庨�氱煡浜嬩欢锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆� + * + */ + @ResponseBody + @PostMapping(value = "/on_record_ts", produces = "application/json;charset=UTF-8") + public ResponseEntity<String> onRecordTs(@RequestBody JSONObject json){ + + if (logger.isDebugEnabled()) { + logger.debug("[ ZLM HOOK ]on_record_ts API璋冪敤锛屽弬鏁帮細" + json.toString()); } String mediaServerId = json.getString("mediaServerId"); JSONObject ret = new JSONObject(); @@ -383,21 +397,22 @@ if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { - streamPushItem = zlmMediaListManager.addPush(item); + item.setSeverId(userSetting.getServerId()); + zlmMediaListManager.addPush(item); } - List<GbStream> gbStreams = new ArrayList<>(); - if (streamPushItem == null || streamPushItem.getGbId() == null) { - GbStream gbStream = storager.getGbStream(app, streamId); - gbStreams.add(gbStream); - }else { - if (streamPushItem.getGbId() != null) { - gbStreams.add(streamPushItem); - } - } - if (gbStreams.size() > 0) { +// List<GbStream> gbStreams = new ArrayList<>(); +// if (streamPushItem == null || streamPushItem.getGbId() == null) { +// GbStream gbStream = storager.getGbStream(app, streamId); +// gbStreams.add(gbStream); +// }else { +// if (streamPushItem.getGbId() != null) { +// gbStreams.add(streamPushItem); +// } +// } +// if (gbStreams.size() > 0) { // eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON); - } +// } }else { // 鍏煎娴佹敞閿�鏃剁被鍨嬩粠redis璁板綍鑾峰彇 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 9beac16..959c06e 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 @@ -24,6 +24,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * @author lin + */ @Component public class ZLMMediaListManager { @@ -147,7 +150,6 @@ } } } - // StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(transform.getApp(), transform.getStream()); List<GbStream> gbStreamList = gbStreamMapper.selectByGBId(transform.getGbId()); if (gbStreamList != null && gbStreamList.size() == 1) { transform.setGbStreamId(gbStreamList.get(0).getGbStreamId()); @@ -162,12 +164,11 @@ } if (transform != null) { if (channelOnlineEvents.get(transform.getGbId()) != null) { - channelOnlineEvents.get(transform.getGbId()).run(transform.getApp(), transform.getStream()); + channelOnlineEvents.get(transform.getGbId()).run(transform.getApp(), transform.getStream(), transform.getServerId()); channelOnlineEvents.remove(transform.getGbId()); } } } - storager.updateMedia(transform); return transform; diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index 75f55cf..54f148a 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -12,6 +12,7 @@ import java.io.*; import java.net.ConnectException; +import java.net.SocketTimeoutException; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -28,6 +29,9 @@ private OkHttpClient getClient(){ OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); + //todo 鏆傛椂鍐欐瓒呮椂鏃堕棿 鍧囦负5s + httpClientBuilder.connectTimeout(5,TimeUnit.SECONDS); //璁剧疆杩炴帴瓒呮椂鏃堕棿 + httpClientBuilder.readTimeout(5,TimeUnit.SECONDS); //璁剧疆璇诲彇瓒呮椂鏃堕棿 if (logger.isDebugEnabled()) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> { logger.debug("http璇锋眰鍙傛暟锛�" + message); @@ -47,7 +51,10 @@ return null; } String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); - JSONObject responseJSON = null; + JSONObject responseJSON = new JSONObject(); + //-2鑷畾涔夋祦濯掍綋 璋冪敤閿欒鐮� + responseJSON.put("code",-2); + responseJSON.put("msg","娴佸獟浣撹皟鐢ㄥけ璐�"); FormBody.Builder builder = new FormBody.Builder(); builder.add("secret",mediaServerItem.getSecret()); @@ -78,11 +85,20 @@ response.close(); Objects.requireNonNull(response.body()).close(); } - } catch (ConnectException e) { - logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", e.getCause().getMessage(), e.getMessage())); - logger.info("璇锋鏌edia閰嶇疆骞剁‘璁LM宸插惎鍔�..."); }catch (IOException e) { logger.error(String.format("[ %s ]璇锋眰澶辫触: %s", url, e.getMessage())); + + if(e instanceof SocketTimeoutException){ + //璇诲彇瓒呮椂瓒呮椂寮傚父 + logger.error(String.format("璇诲彇ZLM鏁版嵁澶辫触: %s, %s", url, e.getMessage())); + } + if(e instanceof ConnectException){ + //鍒ゆ柇杩炴帴寮傚父锛屾垜杩欓噷鏄姤Failed to connect to 10.7.5.144 + logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", url, e.getMessage())); + } + + }catch (Exception e){ + logger.error(String.format("璁块棶ZLM澶辫触: %s, %s", url, e.getMessage())); } }else { client.newCall(request).enqueue(new Callback(){ @@ -105,8 +121,16 @@ @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { - logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", e.getCause().getMessage(), e.getMessage())); - logger.info("璇锋鏌edia閰嶇疆骞剁‘璁LM宸插惎鍔�..."); + logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", call.request().toString(), e.getMessage())); + + if(e instanceof SocketTimeoutException){ + //璇诲彇瓒呮椂瓒呮椂寮傚父 + logger.error(String.format("璇诲彇ZLM鏁版嵁澶辫触: %s, %s", call.request().toString(), e.getMessage())); + } + if(e instanceof ConnectException){ + //鍒ゆ柇杩炴帴寮傚父锛屾垜杩欓噷鏄姤Failed to connect to 10.7.5.144 + logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", call.request().toString(), e.getMessage())); + } } }); } @@ -151,7 +175,7 @@ } } - File snapFile = new File(targetPath + "/" + fileName); + File snapFile = new File(targetPath + File.separator + fileName); FileOutputStream outStream = new FileOutputStream(snapFile); outStream.write(Objects.requireNonNull(response.body()).bytes()); 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 34918ae..4007a40 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 @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import org.slf4j.Logger; @@ -19,6 +20,9 @@ @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private UserSetting userSetting; private int[] portRangeArray = new int[2]; @@ -87,10 +91,15 @@ int result = -1; // 鏌ヨ姝tp server 鏄惁宸茬粡瀛樺湪 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); - if (rtpInfo != null && rtpInfo.getInteger("code") == 0 && rtpInfo.getBoolean("exist")) { - result = rtpInfo.getInteger("local_port"); + if(rtpInfo.getInteger("code") == 0){ + if (rtpInfo.getBoolean("exist")) { + result = rtpInfo.getInteger("local_port"); + return result; + } + }else if(rtpInfo.getInteger("code") == -2){ return result; } + Map<String, Object> param = new HashMap<>(); // 鎺ㄦ祦绔彛璁剧疆0鍒欎娇鐢ㄩ殢鏈虹鍙� param.put("enable_tcp", 1); @@ -197,6 +206,7 @@ sendRtpItem.setTcp(tcp); sendRtpItem.setApp("rtp"); sendRtpItem.setLocalPort(localPort); + sendRtpItem.setServerId(userSetting.getServerId()); sendRtpItem.setMediaServerId(serverItem.getId()); return sendRtpItem; } @@ -238,6 +248,7 @@ sendRtpItem.setChannelId(channelId); sendRtpItem.setTcp(tcp); sendRtpItem.setLocalPort(localPort); + sendRtpItem.setServerId(userSetting.getServerId()); sendRtpItem.setMediaServerId(serverItem.getId()); return sendRtpItem; } @@ -279,10 +290,10 @@ */ public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); - Integer code = mediaInfo.getInteger("code"); if (mediaInfo == null) { return 0; } + Integer code = mediaInfo.getInteger("code"); if ( code < 0) { logger.warn("鏌ヨ娴�({}/{})鏄惁鏈夊叾瀹冭鐪嬭�呮椂寰楀埌锛� {}", app, streamId, mediaInfo.getString("msg")); return -1; 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 ba7daec..21e6ca0 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,6 +1,9 @@ package com.genersoft.iot.vmp.media.zlm.dto; +/** + * @author lin + */ public interface ChannelOnlineEvent { - void run(String app, String stream); + void run(String app, String stream, String serverId); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java index ad158ec..8abac5b 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java @@ -61,9 +61,14 @@ private String originUrl; /** - * 鏈嶅姟鍣╥d + * 娴佸獟浣撴湇鍔″櫒id */ private String mediaServerId; + + /** + * 鏈嶅姟鍣╥d + */ + private String severId; /** * GMT unix绯荤粺鏃堕棿鎴筹紝鍗曚綅绉� @@ -414,4 +419,12 @@ public void setStreamInfo(StreamInfo streamInfo) { this.streamInfo = streamInfo; } + + public String getSeverId() { + return severId; + } + + public void setSeverId(String severId) { + this.severId = severId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java index 81c9c76..ceb48b3 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java @@ -81,6 +81,11 @@ */ private String mediaServerId; + /** + * 浣跨敤鐨勬湇鍔D + */ + private String serverId; + public String getVhost() { return vhost; } @@ -219,5 +224,13 @@ public void setMediaServerId(String mediaServerId) { this.mediaServerId = mediaServerId; } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java index dd1f69e..d3af23c 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java @@ -61,13 +61,12 @@ // 鍙戣捣http璇锋眰楠岃瘉zlm鏄惁纭疄鏃犳硶杩炴帴锛屽鏋滅‘瀹炴棤娉曡繛鎺ュ垯鍙戦�佺绾夸簨浠讹紝鍚﹀垯涓嶄綔澶勭悊 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); JSONObject mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); - if (mediaServerConfig == null) { - publisher.zlmOfflineEventPublish(mediaServerId); - }else { + if (mediaServerConfig != null && mediaServerConfig.getInteger("code") == 0) { logger.info("[zlm蹇冭烦鍒版湡]锛歿}楠岃瘉鍚巣lm浠嶅湪绾匡紝鎭㈠蹇冭烦淇℃伅", mediaServerId); // 娣诲姞zlm淇℃伅 mediaServerService.updateMediaServerKeepalive(mediaServerId, mediaServerConfig); + }else { + publisher.zlmOfflineEventPublish(mediaServerId); } - } } 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 f4a9feb..223ef13 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 @@ -42,7 +42,7 @@ logger.info("[ZLM] 涓婄嚎 ID锛�" + event.getMediaServerId()); streamPushService.zlmServerOnline(event.getMediaServerId()); streamProxyService.zlmServerOnline(event.getMediaServerId()); - + playService.zlmServerOnline(event.getMediaServerId()); } @Async diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java index 239d0c6..e87f53a 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -42,6 +42,8 @@ StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); + void zlmServerOnline(String mediaServerId); + void audioBroadcast(Device device, String channelId, int timeout, AudioBroadcastEvent event); void stopAudioBroadcast(String deviceId, String channelId); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java index 5bdd9f5..9d15c1f 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java +++ b/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java @@ -23,7 +23,6 @@ private IVideoManagerStorage storager; - @Scheduled(fixedRate = 30 * 1000) //姣�30绉掓墽琛屼竴娆� public void execute(){ List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo(); diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java b/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java index 3ab1b80..6dcc515 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java @@ -1,7 +1,10 @@ package com.genersoft.iot.vmp.service.bean; +import java.util.stream.Stream; + /** * 褰撲笂绾у钩鍙� + * @author lin */ public class MessageForPushChannel { /** @@ -45,6 +48,20 @@ */ private String mediaServerId; + public static MessageForPushChannel getInstance(int type, String app, String stream, String gbId, + String platFormId, String platFormName, String serverId, + String mediaServerId){ + MessageForPushChannel messageForPushChannel = new MessageForPushChannel(); + messageForPushChannel.setType(type); + messageForPushChannel.setGbId(gbId); + messageForPushChannel.setApp(app); + messageForPushChannel.setStream(stream); + messageForPushChannel.setMediaServerId(mediaServerId); + messageForPushChannel.setPlatFormId(platFormId); + messageForPushChannel.setPlatFormName(platFormName); + return messageForPushChannel; + } + public int getType() { return type; diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/RequestPushStreamMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestPushStreamMsg.java new file mode 100644 index 0000000..5827d01 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestPushStreamMsg.java @@ -0,0 +1,170 @@ +package com.genersoft.iot.vmp.service.bean; + +/** + * redis娑堟伅锛氳姹備笅绾ф帹閫佹祦淇℃伅 + * @author lin + */ +public class RequestPushStreamMsg { + + + /** + * 涓嬬骇鏈嶅姟ID + */ + private String mediaServerId; + + /** + * 娴両D + */ + private String app; + + /** + * 搴旂敤鍚� + */ + private String stream; + + /** + * 鐩爣IP + */ + private String ip; + + /** + * 鐩爣绔彛 + */ + private int port; + + /** + * ssrc + */ + private String ssrc; + + /** + * 鏄惁浣跨敤TCP鏂瑰紡 + */ + private boolean tcp; + + /** + * 鏈湴浣跨敤鐨勭鍙� + */ + private int srcPort; + + /** + * 鍙戦�佹椂锛宺tp鐨刾t锛坲int8_t锛�,涓嶄紶鏃堕粯璁や负96 + */ + private int pt; + + /** + * 鍙戦�佹椂锛宺tp鐨勮礋杞界被鍨嬨�備负true鏃讹紝璐熻浇涓簆s锛涗负false鏃讹紝涓篹s锛� + */ + private boolean ps; + + /** + * 鏄惁鍙湁闊抽 + */ + private boolean onlyAudio; + + + public static RequestPushStreamMsg getInstance(String mediaServerId, String app, String stream, String ip, int port, String ssrc, + boolean tcp, int srcPort, int pt, boolean ps, boolean onlyAudio) { + RequestPushStreamMsg requestPushStreamMsg = new RequestPushStreamMsg(); + requestPushStreamMsg.setMediaServerId(mediaServerId); + requestPushStreamMsg.setApp(app); + requestPushStreamMsg.setStream(stream); + requestPushStreamMsg.setIp(ip); + requestPushStreamMsg.setPort(port); + requestPushStreamMsg.setSsrc(ssrc); + requestPushStreamMsg.setTcp(tcp); + requestPushStreamMsg.setSrcPort(srcPort); + requestPushStreamMsg.setPt(pt); + requestPushStreamMsg.setPs(ps); + requestPushStreamMsg.setOnlyAudio(onlyAudio); + return requestPushStreamMsg; + } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getSsrc() { + return ssrc; + } + + public void setSsrc(String ssrc) { + this.ssrc = ssrc; + } + + public boolean isTcp() { + return tcp; + } + + public void setTcp(boolean tcp) { + this.tcp = tcp; + } + + public int getSrcPort() { + return srcPort; + } + + public void setSrcPort(int srcPort) { + this.srcPort = srcPort; + } + + public int getPt() { + return pt; + } + + public void setPt(int pt) { + this.pt = pt; + } + + public boolean isPs() { + return ps; + } + + public void setPs(boolean ps) { + this.ps = ps; + } + + public boolean isOnlyAudio() { + return onlyAudio; + } + + public void setOnlyAudio(boolean onlyAudio) { + this.onlyAudio = onlyAudio; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java new file mode 100644 index 0000000..66689fa --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java @@ -0,0 +1,173 @@ +package com.genersoft.iot.vmp.service.bean; + +/** + * redis娑堟伅锛氳姹備笅绾у洖澶嶆帹閫佷俊鎭� + * @author lin + */ +public class RequestSendItemMsg { + + /** + * 涓嬬骇鏈嶅姟ID + */ + private String serverId; + + /** + * 涓嬬骇鏈嶅姟ID + */ + private String mediaServerId; + + /** + * 娴両D + */ + private String app; + + /** + * 搴旂敤鍚� + */ + private String stream; + + /** + * 鐩爣IP + */ + private String ip; + + /** + * 鐩爣绔彛 + */ + private int port; + + /** + * ssrc + */ + private String ssrc; + + /** + * 骞冲彴鍥芥爣缂栧彿 + */ + private String platformId; + + /** + * 骞冲彴鍚嶇О + */ + private String platformName; + + /** + * 閫氶亾ID + */ + private String channelId; + + + /** + * 鏄惁浣跨敤TCP + */ + private Boolean isTcp; + + + + + public static RequestSendItemMsg getInstance(String serverId, String mediaServerId, String app, String stream, String ip, int port, + String ssrc, String platformId, String channelId, Boolean isTcp, String platformName) { + RequestSendItemMsg requestSendItemMsg = new RequestSendItemMsg(); + requestSendItemMsg.setServerId(serverId); + requestSendItemMsg.setMediaServerId(mediaServerId); + requestSendItemMsg.setApp(app); + requestSendItemMsg.setStream(stream); + requestSendItemMsg.setIp(ip); + requestSendItemMsg.setPort(port); + requestSendItemMsg.setSsrc(ssrc); + requestSendItemMsg.setPlatformId(platformId); + requestSendItemMsg.setPlatformName(platformName); + requestSendItemMsg.setChannelId(channelId); + requestSendItemMsg.setTcp(isTcp); + + return requestSendItemMsg; + } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getSsrc() { + return ssrc; + } + + public void setSsrc(String ssrc) { + this.ssrc = ssrc; + } + + public String getPlatformId() { + return platformId; + } + + public void setPlatformId(String platformId) { + this.platformId = platformId; + } + + public String getPlatformName() { + return platformName; + } + + public void setPlatformName(String platformName) { + this.platformName = platformName; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + public Boolean getTcp() { + return isTcp; + } + + public void setTcp(Boolean tcp) { + isTcp = tcp; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java new file mode 100644 index 0000000..501621b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java @@ -0,0 +1,31 @@ +package com.genersoft.iot.vmp.service.bean; + +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; + +/** + * redis娑堟伅锛氫笅绾у洖澶嶆帹閫佷俊鎭� + * @author lin + */ +public class ResponseSendItemMsg { + + private SendRtpItem sendRtpItem; + + private MediaServerItem mediaServerItem; + + public SendRtpItem getSendRtpItem() { + return sendRtpItem; + } + + public void setSendRtpItem(SendRtpItem sendRtpItem) { + this.sendRtpItem = sendRtpItem; + } + + public MediaServerItem getMediaServerItem() { + return mediaServerItem; + } + + public void setMediaServerItem(MediaServerItem mediaServerItem) { + this.mediaServerItem = mediaServerItem; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java new file mode 100644 index 0000000..12d79cb --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java @@ -0,0 +1,116 @@ +package com.genersoft.iot.vmp.service.bean; + +/** + * @author lin + */ +public class WvpRedisMsg { + + public static WvpRedisMsg getInstance(String fromId, String toId, String type, String cmd, String serial, String content){ + WvpRedisMsg wvpRedisMsg = new WvpRedisMsg(); + wvpRedisMsg.setFromId(fromId); + wvpRedisMsg.setToId(toId); + wvpRedisMsg.setType(type); + wvpRedisMsg.setCmd(cmd); + wvpRedisMsg.setSerial(serial); + wvpRedisMsg.setContent(content); + return wvpRedisMsg; + } + + private String fromId; + + private String toId; + /** + * req 璇锋眰, res 鍥炲 + */ + private String type; + private String cmd; + + /** + * 娑堟伅鐨処D + */ + private String serial; + private Object content; + + private final static String requestTag = "req"; + private final static String responseTag = "res"; + + public static WvpRedisMsg getRequestInstance(String fromId, String toId, String cmd, String serial, Object content) { + WvpRedisMsg wvpRedisMsg = new WvpRedisMsg(); + wvpRedisMsg.setType(requestTag); + wvpRedisMsg.setFromId(fromId); + wvpRedisMsg.setToId(toId); + wvpRedisMsg.setCmd(cmd); + wvpRedisMsg.setSerial(serial); + wvpRedisMsg.setContent(content); + return wvpRedisMsg; + } + + public static WvpRedisMsg getResponseInstance() { + WvpRedisMsg wvpRedisMsg = new WvpRedisMsg(); + wvpRedisMsg.setType(responseTag); + return wvpRedisMsg; + } + + public static WvpRedisMsg getResponseInstance(String fromId, String toId, String cmd, String serial, Object content) { + WvpRedisMsg wvpRedisMsg = new WvpRedisMsg(); + wvpRedisMsg.setType(responseTag); + wvpRedisMsg.setFromId(fromId); + wvpRedisMsg.setToId(toId); + wvpRedisMsg.setCmd(cmd); + wvpRedisMsg.setSerial(serial); + wvpRedisMsg.setContent(content); + return wvpRedisMsg; + } + + public static boolean isRequest(WvpRedisMsg wvpRedisMsg) { + return requestTag.equals(wvpRedisMsg.getType()); + } + + public String getSerial() { + return serial; + } + + public void setSerial(String serial) { + this.serial = serial; + } + + public String getFromId() { + return fromId; + } + + public void setFromId(String fromId) { + this.fromId = fromId; + } + + public String getToId() { + return toId; + } + + public void setToId(String toId) { + this.toId = toId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getCmd() { + return cmd; + } + + public void setCmd(String cmd) { + this.cmd = cmd; + } + + public Object getContent() { + return content; + } + + public void setContent(Object content) { + this.content = content; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java new file mode 100644 index 0000000..cb11886 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java @@ -0,0 +1,12 @@ +package com.genersoft.iot.vmp.service.bean; + +/** + * @author lin + */ + +public class WvpRedisMsgCmd { + + public static final String GET_SEND_ITEM = "GetSendItem"; + public static final String REQUEST_PUSH_STREAM = "RequestPushStream"; + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java index 0144e83..ec30cd4 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -2,16 +2,21 @@ import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; +import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceMapper; import com.genersoft.iot.vmp.utils.DateUtil; import org.slf4j.Logger; @@ -50,6 +55,12 @@ private DeviceMapper deviceMapper; @Autowired + private DeviceChannelMapper deviceChannelMapper; + + @Autowired + private IVideoManagerStorage storage; + + @Autowired private ISIPCommander commander; @Autowired @@ -68,7 +79,6 @@ if (deviceInRedis != null && deviceInDb == null) { // redis 瀛樺湪鑴忔暟鎹� redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); - } device.setUpdateTime(now); device.setOnline(1); @@ -77,13 +87,15 @@ if (device.getCreateTime() == null) { device.setCreateTime(now); logger.info("[璁惧涓婄嚎,棣栨娉ㄥ唽]: {}锛屾煡璇㈣澶囦俊鎭互鍙婇�氶亾淇℃伅", device.getDeviceId()); + deviceMapper.add(device); + redisCatchStorage.updateDevice(device); commander.deviceInfoQuery(device); sync(device); - deviceMapper.add(device); }else { deviceMapper.update(device); + redisCatchStorage.updateDevice(device); } - redisCatchStorage.updateDevice(device); + // 涓婄嚎娣诲姞璁㈤槄 if (device.getSubscribeCycleForCatalog() > 0) { // 鏌ヨ鍦ㄧ嚎璁惧閭d簺寮�鍚簡璁㈤槄锛屼负璁惧寮�鍚畾鏃剁殑鐩綍璁㈤槄 @@ -94,7 +106,6 @@ } // 鍒锋柊杩囨湡浠诲姟 String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); - dynamicTask.stop(registerExpireTaskKey); dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); } @@ -143,8 +154,16 @@ if (device == null || device.getSubscribeCycleForCatalog() < 0) { return false; } - logger.info("绉婚櫎鐩綍璁㈤槄: {}", device.getDeviceId()); - dynamicTask.stop(device.getDeviceId() + "catalog"); + logger.info("[绉婚櫎鐩綍璁㈤槄]: {}", device.getDeviceId()); + String taskKey = device.getDeviceId() + "catalog"; + if (device.getOnline() == 1) { + Runnable runnable = dynamicTask.get(taskKey); + if (runnable instanceof ISubscribeTask) { + ISubscribeTask subscribeTask = (ISubscribeTask) runnable; + subscribeTask.stop(); + } + } + dynamicTask.stop(taskKey); return true; } @@ -168,8 +187,16 @@ if (device == null || device.getSubscribeCycleForCatalog() < 0) { return false; } - logger.info("绉婚櫎绉诲姩浣嶇疆璁㈤槄: {}", device.getDeviceId()); - dynamicTask.stop(device.getDeviceId() + "mobile_position"); + logger.info("[绉婚櫎绉诲姩浣嶇疆璁㈤槄]: {}", device.getDeviceId()); + String taskKey = device.getDeviceId() + "mobile_position"; + if (device.getOnline() == 1) { + Runnable runnable = dynamicTask.get(taskKey); + if (runnable instanceof ISubscribeTask) { + ISubscribeTask subscribeTask = (ISubscribeTask) runnable; + subscribeTask.stop(); + } + } + dynamicTask.stop(taskKey); return true; } @@ -275,6 +302,10 @@ removeMobilePositionSubscribe(deviceInStore); } } + // 鍧愭爣绯诲彉鍖栵紝闇�瑕侀噸鏂拌绠桮CJ02鍧愭爣鍜學GS84鍧愭爣 + if (!deviceInStore.getGeoCoordSys().equals(device.getGeoCoordSys())) { + updateDeviceChannelGeoCoordSys(device); + } String now = DateUtil.getNow(); device.setUpdateTime(now); @@ -282,6 +313,32 @@ device.setUpdateTime(DateUtil.getNow()); if (deviceMapper.update(device) > 0) { redisCatchStorage.updateDevice(device); + } } + + /** + * 鏇存柊閫氶亾鍧愭爣绯� + */ + private void updateDeviceChannelGeoCoordSys(Device device) { + List<DeviceChannel> deviceChannels = deviceChannelMapper.getAllChannelWithCoordinate(device.getDeviceId()); + if (deviceChannels.size() > 0) { + for (DeviceChannel deviceChannel : deviceChannels) { + if ("WGS84".equals(device.getGeoCoordSys())) { + deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); + deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); + Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude()); + deviceChannel.setLongitudeGcj02(position[0]); + deviceChannel.setLatitudeGcj02(position[1]); + }else if ("GCJ02".equals(device.getGeoCoordSys())) { + deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude()); + deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude()); + Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude()); + deviceChannel.setLongitudeWgs84(position[0]); + deviceChannel.setLatitudeWgs84(position[1]); + } + } + } + storage.updateChannels(device.getDeviceId(), deviceChannels); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java index a7a5528..c813b11 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java @@ -106,7 +106,8 @@ deviceChannel.setStatus(1); deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); deviceChannel.setRegisterWay(1); - if (catalogId.length() <= 10) { // 鐖惰妭鐐规槸琛屾斂鍖哄垝,鍒欒缃瓹ivilCode浣跨敤姝よ鏀垮尯鍒� + if (catalogId.length() > 0 && catalogId.length() <= 10) { + // 鐖惰妭鐐规槸琛屾斂鍖哄垝,鍒欒缃瓹ivilCode浣跨敤姝よ鏀垮尯鍒� deviceChannel.setCivilCode(catalogId); }else { deviceChannel.setCivilCode(platform.getAdministrativeDivision()); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index 5468fae..0c84b73 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; @@ -35,7 +36,9 @@ import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; /** * 濯掍綋鏈嶅姟鍣ㄨ妭鐐圭鐞� @@ -189,6 +192,7 @@ public void clearRTPServer(MediaServerItem mediaServerItem) { mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain())); redisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0); + } @@ -229,11 +233,10 @@ } result.sort((serverItem1, serverItem2)->{ int sortResult = 0; - try { - sortResult = DateUtil.format.parse(serverItem1.getCreateTime()).compareTo(DateUtil.format.parse(serverItem2.getCreateTime())); - } catch (ParseException e) { - e.printStackTrace(); - } + LocalDateTime localDateTime1 = LocalDateTime.parse(serverItem1.getCreateTime(), DateUtil.formatter); + LocalDateTime localDateTime2 = LocalDateTime.parse(serverItem2.getCreateTime(), DateUtil.formatter); + + sortResult = localDateTime1.compareTo(localDateTime2); return sortResult; }); return result; @@ -495,14 +498,14 @@ param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"); param.put("hook.enable","1"); - param.put("hook.on_flow_report",""); + param.put("hook.on_flow_report",String.format("%s/on_flow_report", hookPrex)); param.put("hook.on_play",String.format("%s/on_play", hookPrex)); - param.put("hook.on_http_access",""); + param.put("hook.on_http_access",String.format("%s/on_http_access", hookPrex)); param.put("hook.on_publish", String.format("%s/on_publish", hookPrex)); param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): ""); - param.put("hook.on_record_ts",""); - param.put("hook.on_rtsp_auth",""); - param.put("hook.on_rtsp_realm",""); + param.put("hook.on_record_ts",String.format("%s/on_record_ts", hookPrex)); + param.put("hook.on_rtsp_auth",String.format("%s/on_rtsp_auth", hookPrex)); + param.put("hook.on_rtsp_realm",String.format("%s/on_rtsp_realm", hookPrex)); param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex)); param.put("hook.on_shell_login",String.format("%s/on_shell_login", hookPrex)); param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex)); 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 f0ffb84..6422cfc 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 @@ -21,6 +21,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.service.IMediaService; +import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; import com.genersoft.iot.vmp.service.bean.PlayBackCallback; import com.genersoft.iot.vmp.service.bean.PlayBackResult; @@ -32,8 +34,6 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; -import com.genersoft.iot.vmp.service.IMediaService; -import com.genersoft.iot.vmp.service.IPlayService; import gov.nist.javax.sip.stack.SIPDialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,6 +49,7 @@ import java.io.FileNotFoundException; import java.math.BigDecimal; import java.text.ParseException; +import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -73,9 +74,6 @@ @Autowired private IRedisCatchStorage redisCatchStorage; - - @Autowired - private RedisUtil redis; @Autowired private DeferredResultHolder resultHolder; @@ -140,36 +138,19 @@ result.onCompletion(()->{ // 鐐规挱缁撴潫鏃惰皟鐢ㄦ埅鍥炬帴鍙� // TODO 搴旇鍦ㄤ笂娴佹椂璋冪敤鏇村ソ锛岀粨鏉熶篃鍙兘鏄敊璇粨鏉� - try { - String classPath = ResourceUtils.getURL("classpath:").getPath(); - // 鍏煎鎵撳寘涓簀ar鐨刢lass璺緞 - if(classPath.contains("jar")) { - classPath = classPath.substring(0, classPath.lastIndexOf(".")); - classPath = classPath.substring(0, classPath.lastIndexOf("/") + 1); + String path = "static/static/snap/"; + String fileName = deviceId + "_" + channelId + ".jpg"; + ResponseEntity responseEntity = (ResponseEntity)result.getResult(); + if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { + WVPResult wvpResult = (WVPResult)responseEntity.getBody(); + 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 (classPath.startsWith("file:")) { - classPath = classPath.substring(classPath.indexOf(":") + 1); - } - String path = classPath + "static/static/snap/"; - // 鍏煎Windows绯荤粺璺緞锛堝幓闄ゅ墠闈㈢殑鈥�/鈥濓級 - if(System.getProperty("os.name").contains("indows")) { - path = path.substring(1); - } - String fileName = deviceId + "_" + channelId + ".jpg"; - ResponseEntity responseEntity = (ResponseEntity)result.getResult(); - if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { - WVPResult wvpResult = (WVPResult)responseEntity.getBody(); - 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); - } - } - } catch (FileNotFoundException e) { - e.printStackTrace(); } }); if (streamInfo != null) { @@ -186,23 +167,32 @@ MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); - if (rtpInfo != null && rtpInfo.getBoolean("exist")) { + if(rtpInfo.getInteger("code") == 0){ + if (rtpInfo.getBoolean("exist")) { - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(0); - wvpResult.setMsg("success"); - wvpResult.setData(streamInfo); - msg.setData(wvpResult); + WVPResult wvpResult = new WVPResult(); + wvpResult.setCode(0); + wvpResult.setMsg("success"); + wvpResult.setData(streamInfo); + msg.setData(wvpResult); - resultHolder.invokeAllResult(msg); - if (hookEvent != null) { - hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo))); + resultHolder.invokeAllResult(msg); + if (hookEvent != null) { + hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo))); + } + }else { + redisCatchStorage.stopPlay(streamInfo); + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + streamInfo = null; } }else { + //zlm杩炴帴澶辫触 redisCatchStorage.stopPlay(streamInfo); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); streamInfo = null; + } + } if (streamInfo == null) { @@ -256,33 +246,41 @@ if (ssrcInfo == null) { ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); } - + logger.info("[鐐规挱寮�濮媇 deviceId: {}, channelId: {}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getSsrc() ); // 瓒呮椂澶勭悊 String timeOutTaskKey = UUID.randomUUID().toString(); SSRCInfo finalSsrcInfo = ssrcInfo; dynamicTask.startDelay( timeOutTaskKey,()->{ - logger.warn(String.format("璁惧鐐规挱瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", device.getDeviceId(), channelId)); SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); if (dialog != null) { + logger.info("[鐐规挱瓒呮椂] 鏀舵祦瓒呮椂 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); timeoutCallback.run(1, "鏀舵祦瓒呮椂"); // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧� cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null); }else { + logger.info("[鐐规挱瓒呮椂] 娑堟伅鏈搷搴� deviceId: {}, channelId: {}", device.getDeviceId(), channelId); timeoutCallback.run(0, "鐐规挱瓒呮椂"); mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); } - }, userSetting.getPlayTimeout()*1000); + }, userSetting.getPlayTimeout()); final String ssrc = ssrcInfo.getSsrc(); final String stream = ssrcInfo.getStream(); + //绔彛鑾峰彇澶辫触鐨剆srcInfo 娌℃湁蹇呰鍙戦�佺偣鎾寚浠� + if(ssrcInfo.getPort() <= 0){ + logger.info("[鐐规挱绔彛鍒嗛厤寮傚父]锛宒eviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); + return; + } cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); dynamicTask.stop(timeOutTaskKey); // hook鍝嶅簲 onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid); hookEvent.response(mediaServerItemInuse, response); + logger.info("[鐐规挱鎴愬姛] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + }, (event) -> { ResponseEvent responseEvent = (ResponseEvent)event.event; String contentString = new String(responseEvent.getResponse().getRawContent()); @@ -296,8 +294,10 @@ if (ssrc.equals(ssrcInResponse)) { return; } - logger.info("[SIP 娑堟伅] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc 寮�鍚慨姝�"); + logger.info("[鐐规挱娑堟伅] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc: {}", ssrcInResponse ); if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { + logger.info("[SIP 娑堟伅] SSRC淇 {}->{}", ssrc, ssrcInResponse); + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { // ssrc 涓嶅彲鐢� // 閲婃斁ssrc @@ -450,7 +450,7 @@ cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰 playBackCallback.call(playBackResult); - }, userSetting.getPlayTimeout()*1000); + }, userSetting.getPlayTimeout()); cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, (InviteStreamInfo inviteStreamInfo) -> { @@ -539,7 +539,7 @@ cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰 hookCallBack.call(downloadResult); - }, userSetting.getPlayTimeout()*1000); + }, userSetting.getPlayTimeout()); cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, inviteStreamInfo -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + inviteStreamInfo.getResponse().toJSONString()); @@ -605,7 +605,7 @@ BigDecimal currentCount = new BigDecimal(duration/1000); BigDecimal totalCount = new BigDecimal(end-start); - BigDecimal divide = currentCount.divide(totalCount,2, BigDecimal.ROUND_HALF_UP); + BigDecimal divide = currentCount.divide(totalCount,2, RoundingMode.HALF_UP); double process = divide.doubleValue(); streamInfo.setProgress(process); } @@ -728,4 +728,9 @@ } + + @Override + public void zlmServerOnline(String mediaServerId) { + // 浼间箮娌″暐闇�瑕佸仛鐨� + } } 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 new file mode 100644 index 0000000..638ea41 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java @@ -0,0 +1,377 @@ +package com.genersoft.iot.vmp.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; +import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; +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.*; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; +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.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.stereotype.Component; + +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * 鐩戝惉涓嬬骇鍙戦�佹帹閫佷俊鎭紝骞跺彂閫佸浗鏍囨帹娴佹秷鎭笂绾� + * @author lin + */ +@Component +public class RedisGbPlayMsgListener implements MessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RedisGbPlayMsgListener.class); + + public static final String WVP_PUSH_STREAM_KEY = "WVP_PUSH_STREAM"; + + /** + * 娴佸獟浣撲笉瀛樺湪鐨勯敊璇帥 + */ + public static final int ERROR_CODE_MEDIA_SERVER_NOT_FOUND = -1; + + /** + * 绂荤嚎鐨勯敊璇帥 + */ + public static final int ERROR_CODE_OFFLINE = -2; + + /** + * 瓒呮椂鐨勯敊璇帥 + */ + public static final int ERROR_CODE_TIMEOUT = -3; + + private Map<String, PlayMsgCallback> callbacks = new ConcurrentHashMap<>(); + private Map<String, PlayMsgCallbackForStartSendRtpStream> callbacksForStartSendRtpStream = new ConcurrentHashMap<>(); + private Map<String, PlayMsgErrorCallback> callbacksForError = new ConcurrentHashMap<>(); + + @Autowired + private UserSetting userSetting; + + @Autowired + private RedisUtil redis; + + @Autowired + private ZLMMediaListManager zlmMediaListManager; + + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private IMediaServerService mediaServerService; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private DynamicTask dynamicTask; + + @Autowired + private ZLMMediaListManager mediaListManager; + + @Autowired + private ZLMHttpHookSubscribe subscribe; + + + public interface PlayMsgCallback{ + void handler(ResponseSendItemMsg responseSendItemMsg); + } + + public interface PlayMsgCallbackForStartSendRtpStream{ + void handler(JSONObject jsonObject); + } + + public interface PlayMsgErrorCallback{ + void handler(WVPResult wvpResult); + } + + @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; + } + + }else { + logger.info("[鏀跺埌REDIS閫氱煡] 鍥炲锛� {}", new String(message.getBody())); + switch (wvpRedisMsg.getCmd()){ + case WvpRedisMsgCmd.GET_SEND_ITEM: + + 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); + playMsgCallback.handler(responseSendItemMsg); + } + 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; + } + } + + + + + } + + /** + * 澶勭悊鏀跺埌鐨勮姹傛帹娴佺殑璇锋眰 + */ + private void requestPushStreamMsgHand(RequestPushStreamMsg requestPushStreamMsg, String fromId, String serial) { + MediaServerItem mediaInfo = mediaServerService.getOne(requestPushStreamMsg.getMediaServerId()); + if (mediaInfo == null) { + // TODO 鍥炲閿欒 + return; + } + String is_Udp = requestPushStreamMsg.isTcp() ? "0" : "1"; + Map<String, Object> param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",requestPushStreamMsg.getApp()); + param.put("stream",requestPushStreamMsg.getStream()); + param.put("ssrc", requestPushStreamMsg.getSsrc()); + param.put("dst_url",requestPushStreamMsg.getIp()); + param.put("dst_port", requestPushStreamMsg.getPort()); + param.put("is_udp", is_Udp); + param.put("src_port", requestPushStreamMsg.getSrcPort()); + param.put("pt", requestPushStreamMsg.getPt()); + param.put("use_ps", requestPushStreamMsg.isPs() ? "1" : "0"); + param.put("only_audio", requestPushStreamMsg.isOnlyAudio() ? "1" : "0"); + JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); + // 鍥炲娑堟伅 + responsePushStream(jsonObject, fromId, serial); + } + + private void responsePushStream(JSONObject content, String toId, String serial) { + + WVPResult<JSONObject> result = new WVPResult<>(); + result.setCode(0); + result.setData(content); + + WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId, + WvpRedisMsgCmd.REQUEST_PUSH_STREAM, serial, result); + JSONObject jsonObject = (JSONObject)JSON.toJSON(response); + redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + } + + /** + * 澶勭悊鏀跺埌鐨勮姹俿endItem鐨勮姹� + */ + private void requestSendItemMsgHand(RequestSendItemMsg content, String toId, String serial) { + MediaServerItem mediaServerItem = mediaServerService.getOne(content.getMediaServerId()); + if (mediaServerItem == null) { + logger.info("[鍥炲鎺ㄦ祦淇℃伅] 娴佸獟浣搟}涓嶅瓨鍦� ", content.getMediaServerId()); + + WVPResult<SendRtpItem> result = new WVPResult<>(); + result.setCode(ERROR_CODE_MEDIA_SERVER_NOT_FOUND); + result.setMsg("娴佸獟浣撲笉瀛樺湪"); + + WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId, + WvpRedisMsgCmd.GET_SEND_ITEM, serial, result); + + JSONObject jsonObject = (JSONObject)JSON.toJSON(response); + redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + return; + } + // 纭畾娴佹槸鍚﹀湪绾� + boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); + if (streamReady) { + logger.info("[鍥炲鎺ㄦ祦淇℃伅] {}/{}", content.getApp(), content.getStream()); + responseSendItem(mediaServerItem, content, toId, serial); + }else { + // 娴佸凡缁忕绾� + // 鍙戦�乺edis娑堟伅浠ヤ娇璁惧涓婄嚎 + logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽彂閫乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�",content.getApp(), content.getStream()); + + String taskKey = UUID.randomUUID().toString(); + // 璁剧疆瓒呮椂 + dynamicTask.startDelay(taskKey, ()->{ + logger.info("[ app={}, stream={} ] 绛夊緟璁惧寮�濮嬫帹娴佽秴鏃�", content.getApp(), content.getStream()); + WVPResult<SendRtpItem> result = new WVPResult<>(); + result.setCode(ERROR_CODE_TIMEOUT); + WvpRedisMsg response = WvpRedisMsg.getResponseInstance( + userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result + ); + JSONObject jsonObject = (JSONObject)JSON.toJSON(response); + redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + }, userSetting.getPlatformPlayTimeout()); + + // 娣诲姞璁㈤槄 + JSONObject subscribeKey = new JSONObject(); + subscribeKey.put("app", content.getApp()); + subscribeKey.put("stream", content.getStream()); + subscribeKey.put("regist", true); + subscribeKey.put("schema", "rtmp"); + subscribeKey.put("mediaServerId", mediaServerItem.getId()); + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, + (MediaServerItem mediaServerItemInUse, JSONObject json)->{ + dynamicTask.stop(taskKey); + responseSendItem(mediaServerItem, content, toId, serial); + }); + + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(1, content.getApp(), content.getStream(), + content.getChannelId(), content.getPlatformId(), content.getPlatformName(), content.getServerId(), + content.getMediaServerId()); + redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); + + } + } + + /** + * 灏嗚幏鍙栧埌鐨剆endItem鍙戦�佸嚭鍘� + */ + private void responseSendItem(MediaServerItem mediaServerItem, RequestSendItemMsg content, String toId, String serial) { + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), + content.getPort(), content.getSsrc(), content.getPlatformId(), + content.getApp(), content.getStream(), content.getChannelId(), + content.getTcp()); + + WVPResult<ResponseSendItemMsg> result = new WVPResult<>(); + result.setCode(0); + ResponseSendItemMsg responseSendItemMsg = new ResponseSendItemMsg(); + responseSendItemMsg.setSendRtpItem(sendRtpItem); + responseSendItemMsg.setMediaServerItem(mediaServerItem); + result.setData(responseSendItemMsg); + + WvpRedisMsg response = WvpRedisMsg.getResponseInstance( + userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result + ); + JSONObject jsonObject = (JSONObject)JSON.toJSON(response); + redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + } + + /** + * 鍙戦�佹秷鎭姹備笅绾х敓鎴愭帹娴佷俊鎭� + * @param serverId 涓嬬骇鏈嶅姟ID + * @param app 搴旂敤鍚� + * @param stream 娴両D + * @param ip 鐩爣IP + * @param port 鐩爣绔彛 + * @param ssrc ssrc + * @param platformId 骞冲彴鍥芥爣缂栧彿 + * @param channelId 閫氶亾ID + * @param isTcp 鏄惁浣跨敤TCP + * @param callback 寰楀埌淇℃伅鐨勫洖璋� + */ + public void sendMsg(String serverId, String mediaServerId, String app, String stream, String ip, int port, String ssrc, + String platformId, String channelId, boolean isTcp, String platformName, PlayMsgCallback callback, PlayMsgErrorCallback errorCallback) { + RequestSendItemMsg requestSendItemMsg = RequestSendItemMsg.getInstance( + serverId, mediaServerId, app, stream, ip, port, ssrc, platformId, channelId, isTcp, platformName); + requestSendItemMsg.setServerId(serverId); + String key = UUID.randomUUID().toString(); + WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, WvpRedisMsgCmd.GET_SEND_ITEM, + key, requestSendItemMsg); + + JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg); + logger.info("[璇锋眰鎺ㄦ祦SendItem] {}: {}", serverId, jsonObject); + callbacks.put(key, callback); + callbacksForError.put(key, errorCallback); + dynamicTask.startDelay(key, ()->{ + callbacks.remove(key); + callbacksForError.remove(key); + WVPResult<Object> wvpResult = new WVPResult<>(); + wvpResult.setCode(ERROR_CODE_TIMEOUT); + wvpResult.setMsg("timeout"); + errorCallback.handler(wvpResult); + }, userSetting.getPlatformPlayTimeout()); + redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + } + + /** + * 鍙戦�佽姹傛帹娴佺殑娑堟伅 + * @param param 鎺ㄦ祦鍙傛暟 + * @param callback 鍥炶皟 + */ + public void sendMsgForStartSendRtpStream(String serverId, RequestPushStreamMsg param, PlayMsgCallbackForStartSendRtpStream callback) { + String key = UUID.randomUUID().toString(); + WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, + WvpRedisMsgCmd.REQUEST_PUSH_STREAM, key, param); + + JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg); + logger.info("[REDIS 璇锋眰鍏朵粬骞冲彴鎺ㄦ祦] {}: {}", serverId, jsonObject); + dynamicTask.startDelay(key, ()->{ + callbacksForStartSendRtpStream.remove(key); + callbacksForError.remove(key); + }, userSetting.getPlatformPlayTimeout()); + callbacksForStartSendRtpStream.put(key, callback); + callbacksForError.put(key, (wvpResult)->{ + logger.info("[REDIS 璇锋眰鍏朵粬骞冲彴鎺ㄦ祦] 澶辫触: {}", wvpResult.getMsg()); + callbacksForStartSendRtpStream.remove(key); + callbacksForError.remove(key); + }); + redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java similarity index 66% rename from src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java rename to src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java index c688d13..238aafd 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -10,17 +11,23 @@ import org.springframework.data.redis.connection.MessageListener; import org.springframework.stereotype.Component; +/** + * 鎺ユ敹鏉ヨ嚜redis鐨凣PS鏇存柊閫氱煡 + * @author lin + */ @Component -public class RedisGPSMsgListener implements MessageListener { +public class RedisGpsMsgListener implements MessageListener { - private final static Logger logger = LoggerFactory.getLogger(RedisGPSMsgListener.class); + private final static Logger logger = LoggerFactory.getLogger(RedisGpsMsgListener.class); @Autowired private IRedisCatchStorage redisCatchStorage; @Override - public void onMessage(Message message, byte[] bytes) { - logger.info("鏀跺埌鏉ヨ嚜REDIS鐨凣PS閫氱煡锛� {}", new String(message.getBody())); + public void onMessage(@NotNull Message message, byte[] bytes) { + if (logger.isDebugEnabled()) { + logger.debug("鏀跺埌鏉ヨ嚜REDIS鐨凣PS閫氱煡锛� {}", new String(message.getBody())); + } GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class); redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); } 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 new file mode 100644 index 0000000..07fffdc --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java @@ -0,0 +1,83 @@ +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.bean.AlarmChannelMessage; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +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 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; + + +/** + * @author lin + */ +@Component +public class RedisStreamMsgListener implements MessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RedisStreamMsgListener.class); + + @Autowired + private ISIPCommander commander; + + @Autowired + private ISIPCommanderForPlatform commanderForPlatform; + + @Autowired + private IVideoManagerStorage storage; + + @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鐨凙LARM閫氱煡]娑堟伅瑙f瀽澶辫触"); + 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"); + + zlmMediaListManager.addPush(mediaItem); + + + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java index d710dad..1e00faa 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java @@ -107,6 +107,7 @@ streamPushItem.setStatus(true); streamPushItem.setStreamType("push"); streamPushItem.setVhost(item.getVhost()); + streamPushItem.setServerId(item.getSeverId()); return streamPushItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java index d94669b..6b86280 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java @@ -357,6 +357,15 @@ /** + * 鑾峰彇浣嗕釜鎺ㄦ祦 + * @param app + * @param stream + * @return + */ + StreamPushItem getMedia(String app, String stream); + + + /** * 娓呯┖鎺ㄦ祦鍒楄〃 */ void clearMediaList(); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java index c3b94f6..5c46fb9 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -17,10 +17,10 @@ @Insert("INSERT INTO device_channel (channelId, deviceId, name, manufacture, model, owner, civilCode, block, " + "address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + - "ipAddress, port, password, PTZType, status, streamId, longitude, latitude, createTime, updateTime) " + + "ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, longitudeWgs84, latitudeWgs84, createTime, updateTime) " + "VALUES ('${channelId}', '${deviceId}', '${name}', '${manufacture}', '${model}', '${owner}', '${civilCode}', '${block}'," + "'${address}', ${parental}, '${parentId}', ${safetyWay}, ${registerWay}, '${certNum}', ${certifiable}, ${errCode}, '${secrecy}', " + - "'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status}, '${streamId}', ${longitude}, ${latitude},'${createTime}', '${updateTime}')") + "'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status}, '${streamId}', ${longitude}, ${latitude}, ${longitudeGcj02}, ${latitudeGcj02}, ${longitudeWgs84}, ${latitudeWgs84},'${createTime}', '${updateTime}')") int add(DeviceChannel channel); @Update(value = {" <script>" + @@ -50,6 +50,10 @@ "<if test='hasAudio != null'>, hasAudio=${hasAudio}</if>" + "<if test='longitude != null'>, longitude=${longitude}</if>" + "<if test='latitude != null'>, latitude=${latitude}</if>" + + "<if test='longitudeGcj02 != null'>, longitudeGcj02=${longitudeGcj02}</if>" + + "<if test='latitudeGcj02 != null'>, latitudeGcj02=${latitudeGcj02}</if>" + + "<if test='longitudeWgs84 != null'>, longitudeWgs84=${longitudeWgs84}</if>" + + "<if test='latitudeWgs84 != null'>, latitudeWgs84=${latitudeWgs84}</if>" + "WHERE deviceId='${deviceId}' AND channelId='${channelId}'"+ " </script>"}) int update(DeviceChannel channel); @@ -67,7 +71,7 @@ " <if test='online == false' > AND dc.status=0</if>" + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" + - "GROUP BY dc.channelId " + + "ORDER BY dc.channelId " + " </script>"}) List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online); @@ -138,7 +142,8 @@ "insert into device_channel " + "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + - " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, createTime, updateTime) " + + " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + + " longitudeWgs84, latitudeWgs84, createTime, updateTime) " + "values " + "<foreach collection='addChannels' index='index' item='item' separator=','> " + "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " + @@ -146,7 +151,8 @@ "'${item.address}', ${item.parental}, '${item.parentId}', ${item.safetyWay}, ${item.registerWay}, " + "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " + "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " + - "'${item.streamId}', ${item.longitude}, ${item.latitude},'${item.createTime}', '${item.updateTime}')" + + "'${item.streamId}', ${item.longitude}, ${item.latitude},${item.longitudeGcj02}, " + + "${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84},'${item.createTime}', '${item.updateTime}')" + "</foreach> " + "ON DUPLICATE KEY UPDATE " + "updateTime=VALUES(updateTime), " + @@ -173,7 +179,11 @@ "status=VALUES(status), " + "streamId=VALUES(streamId), " + "longitude=VALUES(longitude), " + - "latitude=VALUES(latitude)" + + "latitude=VALUES(latitude), " + + "longitudeGcj02=VALUES(longitudeGcj02), " + + "latitudeGcj02=VALUES(latitudeGcj02), " + + "longitudeWgs84=VALUES(longitudeWgs84), " + + "latitudeWgs84=VALUES(latitudeWgs84) " + "</script>") int batchAdd(List<DeviceChannel> addChannels); @@ -207,7 +217,11 @@ "<if test='item.hasAudio != null'>, hasAudio=${item.hasAudio}</if>" + "<if test='item.longitude != null'>, longitude=${item.longitude}</if>" + "<if test='item.latitude != null'>, latitude=${item.latitude}</if>" + - "WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}"+ + "<if test='item.longitudeGcj02 != null'>, longitudeGcj02=${item.longitudeGcj02}</if>" + + "<if test='item.latitudeGcj02 != null'>, latitudeGcj02=${item.latitudeGcj02}</if>" + + "<if test='item.longitudeWgs84 != null'>, longitudeWgs84=${item.longitudeWgs84}</if>" + + "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=${item.latitudeWgs84}</if>" + + "WHERE deviceId='${item.deviceId}' AND channelId='${item.channelId}'"+ "</foreach>" + "</script>"}) int batchUpdate(List<DeviceChannel> updateChannels); @@ -261,4 +275,6 @@ @Select("SELECT * FROM device_channel WHERE length(trim(streamId)) > 0") List<DeviceChannel> getAllChannelInPlay(); + @Select("select * from device_channel where longitude*latitude > 0 and deviceId = #{deviceId}") + List<DeviceChannel> getAllChannelWithCoordinate(String deviceId); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java index 37d951e..3e15b73 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java @@ -38,6 +38,7 @@ "mobilePositionSubmissionInterval," + "subscribeCycleForAlarm," + "ssrcCheck," + + "geoCoordSys," + "online" + ") VALUES (" + "#{deviceId}," + @@ -61,6 +62,7 @@ "#{mobilePositionSubmissionInterval}," + "#{subscribeCycleForAlarm}," + "#{ssrcCheck}," + + "#{geoCoordSys}," + "#{online}" + ")") int add(Device device); @@ -87,6 +89,7 @@ "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=${mobilePositionSubmissionInterval}</if>" + "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=${subscribeCycleForAlarm}</if>" + "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" + + "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" + "WHERE deviceId='${deviceId}'"+ " </script>"}) int update(Device device); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java index 909d3a8..ebd3478 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java @@ -14,9 +14,9 @@ public interface StreamPushMapper { @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + - "createStamp, aliveSecond, mediaServerId) VALUES" + + "createStamp, aliveSecond, mediaServerId, serverId) VALUES" + "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " + - "'${createStamp}', '${aliveSecond}', '${mediaServerId}' )") + "'${createStamp}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' )") int add(StreamPushItem streamPushItem); @Update("UPDATE stream_push " + 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 39daeda..5377e23 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 @@ -587,11 +587,11 @@ String scanKey = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_*"; List<GPSMsgInfo> result = new ArrayList<>(); List<Object> keys = redis.scan(scanKey); - for (int i = 0; i < keys.size(); i++) { - String key = (String) keys.get(i); + for (Object o : keys) { + String key = (String) o; GPSMsgInfo gpsMsgInfo = (GPSMsgInfo) redis.get(key); if (!gpsMsgInfo.isStored()) { // 鍙彇娌℃湁瀛樿繃寰� - result.add((GPSMsgInfo)redis.get(key)); + result.add((GPSMsgInfo) redis.get(key)); } } @@ -667,7 +667,7 @@ @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()); redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); } 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 1f35911..ac870f7 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 @@ -25,12 +25,13 @@ import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -/** +/** * 瑙嗛璁惧鏁版嵁瀛樺偍-jdbc瀹炵幇 * swwheihei * 2020骞�5鏈�6鏃� 涓嬪崍2:31:42 @@ -195,7 +196,7 @@ @Override public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) { - if (deviceChannelList == null) { + if (CollectionUtils.isEmpty(deviceChannelList)) { return false; } List<DeviceChannel> allChannelInPlay = deviceChannelMapper.getAllChannelInPlay(); @@ -245,6 +246,10 @@ } if (stringBuilder.length() > 0) { logger.info("[鐩綍鏌ヨ]鏀跺埌鐨勬暟鎹瓨鍦ㄩ噸澶嶏細 {}" , stringBuilder); + } + if(CollectionUtils.isEmpty(channels)){ + logger.info("閫氶亾閲嶈锛屾暟鎹负绌�={}" , deviceChannelList); + return false; } try { int cleanChannelsResult = deviceChannelMapper.cleanChannelsNotInList(deviceId, channels); @@ -315,6 +320,9 @@ List<DeviceChannel> all; if (catalogUnderDevice != null && catalogUnderDevice) { all = deviceChannelMapper.queryChannels(deviceId, deviceId, query, hasSubChannel, online); + // 娴峰悍璁惧鐨刾arentId鏄疭IP id + List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, sipConfig.getId(), query, hasSubChannel, online); + all.addAll(deviceChannels); }else { all = deviceChannelMapper.queryChannels(deviceId, null, query, hasSubChannel, online); } @@ -877,6 +885,11 @@ } @Override + public StreamPushItem getMedia(String app, String stream) { + return streamPushMapper.selectOne(app, stream); + } + + @Override public void clearMediaList() { streamPushMapper.clear(); } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java index 9d37dcd..494bcbb 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.utils; -import java.text.SimpleDateFormat; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; @@ -18,35 +17,63 @@ */ public class DateUtil { - private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss"; - public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; + /** + * 鍏煎涓嶈鑼冪殑iso8601鏃堕棿鏍煎紡 + */ + private static final String ISO8601_COMPATIBLE_PATTERN = "yyyy-M-d'T'H:m:s"; - public static final SimpleDateFormat formatISO8601 = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()); - public static final SimpleDateFormat format = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()); + /** + * 鐢ㄤ互杈撳嚭鏍囧噯鐨刬so8601鏃堕棿鏍煎紡 + */ + private static final String ISO8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ss"; - public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()).withZone(ZoneId.systemDefault()); - public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()).withZone(ZoneId.systemDefault()); + /** + * wvp鍐呴儴缁熶竴鏃堕棿鏍煎紡 + */ + public static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; + + public static final String zoneStr = "Asia/Shanghai"; + + public static final DateTimeFormatter formatterCompatibleISO8601 = DateTimeFormatter.ofPattern(ISO8601_COMPATIBLE_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); + public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(ISO8601_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); + public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { + return formatterISO8601.format(formatter.parse(formatTime)); } public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { - return formatter.format(formatterISO8601.parse(formatTime)); + return formatter.format(formatterCompatibleISO8601.parse(formatTime)); } - + + /** + * yyyy_MM_dd_HH_mm_ss 杞椂闂存埑 + * @param formatTime + * @return + */ public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) { TemporalAccessor temporalAccessor = formatter.parse(formatTime); Instant instant = Instant.from(temporalAccessor); return instant.getEpochSecond(); } + /** + * 鑾峰彇褰撳墠鏃堕棿 + * @return + */ public static String getNow() { LocalDateTime nowDateTime = LocalDateTime.now(); return formatter.format(nowDateTime); } + /** + * 鏍煎紡鏍¢獙 + * @param timeStr 鏃堕棿瀛楃涓� + * @param dateTimeFormatter 寰呮牎楠岀殑鏍煎紡 + * @return + */ public static boolean verification(String timeStr, DateTimeFormatter dateTimeFormatter) { try { LocalDate.parse(timeStr, dateTimeFormatter); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java index 56864db..509c988 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java @@ -24,6 +24,7 @@ import org.springframework.web.bind.annotation.*; import java.text.ParseException; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; @@ -68,8 +69,8 @@ @ApiImplicitParam(name="alarmMethod", value = "鏌ヨ鍐呭" ,dataTypeClass = String.class), @ApiImplicitParam(name="alarmMethod", value = "鏌ヨ鍐呭" ,dataTypeClass = String.class), @ApiImplicitParam(name="alarmType", value = "鏌ヨ鍐呭" ,dataTypeClass = String.class), - @ApiImplicitParam(name="startTime", value = "鏌ヨ鍐呭" ,dataTypeClass = String.class), - @ApiImplicitParam(name="endTime", value = "鏌ヨ鍐呭" ,dataTypeClass = String.class), + @ApiImplicitParam(name="startTime", value = "寮�濮嬫椂闂�" ,dataTypeClass = String.class), + @ApiImplicitParam(name="endTime", value = "缁撴潫鏃堕棿" ,dataTypeClass = String.class), }) public ResponseEntity<PageInfo<DeviceAlarm>> getAll( @RequestParam int page, @@ -98,14 +99,7 @@ } - try { - if (startTime != null) { - DateUtil.format.parse(startTime); - } - if (endTime != null) { - DateUtil.format.parse(endTime); - } - } catch (ParseException e) { + if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){ return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); } @@ -144,11 +138,7 @@ if (StringUtils.isEmpty(time)) { time = null; } - try { - if (time != null) { - DateUtil.format.parse(time); - } - } catch (ParseException e) { + if (!DateUtil.verification(time, DateUtil.formatter) ){ return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); } List<String> deviceIdList = null; @@ -189,7 +179,7 @@ deviceAlarm.setAlarmDescription("test"); deviceAlarm.setAlarmMethod("1"); deviceAlarm.setAlarmPriority("1"); - deviceAlarm.setAlarmTime(DateUtil.formatISO8601.format(System.currentTimeMillis())); + deviceAlarm.setAlarmTime(DateUtil.formatterISO8601.format(LocalDateTime.now())); deviceAlarm.setAlarmType("1"); deviceAlarm.setLongitude(115.33333); deviceAlarm.setLatitude(39.33333); 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 3e53848..5e1e40b 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 @@ -21,16 +21,22 @@ import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import org.apache.commons.compress.utils.IOUtils; +import org.apache.http.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; +import javax.servlet.http.HttpServletResponse; import javax.sip.DialogState; +import java.io.*; +import java.nio.file.Files; import java.util.*; @Api(tags = "鍥芥爣璁惧鏌ヨ", value = "鍥芥爣璁惧鏌ヨ") @@ -200,6 +206,11 @@ Set<String> allKeys = dynamicTask.getAllKeys(); for (String key : allKeys) { if (key.startsWith(deviceId)) { + Runnable runnable = dynamicTask.get(key); + if (runnable instanceof ISubscribeTask) { + ISubscribeTask subscribeTask = (ISubscribeTask) runnable; + subscribeTask.stop(); + } dynamicTask.stop(key); } } @@ -306,12 +317,7 @@ public ResponseEntity<WVPResult<String>> updateDevice(Device device){ if (device != null && device.getDeviceId() != null) { - - - // TODO 鎶ヨ璁㈤槄鐩稿叧鐨勪俊鎭� - deviceService.updateDevice(device); -// cmder.deviceInfoQuery(device); } WVPResult<String> result = new WVPResult<>(); result.setCode(0); @@ -336,6 +342,11 @@ Device device = storager.queryVideoDevice(deviceId); String uuid = UUID.randomUUID().toString(); String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId; + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2*1000L); + if(device == null) { + result.setResult(new ResponseEntity(String.format("璁惧%s涓嶅瓨鍦�", deviceId),HttpStatus.OK)); + return result; + } cmder.deviceStatusQuery(device, event -> { RequestMessage msg = new RequestMessage(); msg.setId(uuid); @@ -343,7 +354,6 @@ msg.setData(String.format("鑾峰彇璁惧鐘舵�佸け璐ワ紝閿欒鐮侊細 %s, %s", event.statusCode, event.msg)); resultHolder.invokeResult(msg); }); - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(2*1000L); result.onTimeout(()->{ logger.warn(String.format("鑾峰彇璁惧鐘舵�佽秴鏃�")); // 閲婃斁rtpserver @@ -456,4 +466,17 @@ wvpResult.setData(dialogStateMap); return wvpResult; } + + @GetMapping("/snap/{deviceId}/{channelId}") + @ApiOperation(value = "璇锋眰鎴浘", notes = "璇锋眰鎴浘") + public void getSnap(HttpServletResponse resp, @PathVariable String deviceId, @PathVariable String channelId) { + + try { + final InputStream in = Files.newInputStream(new File("snap" + File.separator + deviceId + "_" + channelId + ".jpg").toPath()); + resp.setContentType(MediaType.IMAGE_PNG_VALUE); + IOUtils.copy(in, resp.getOutputStream()); + } catch (IOException e) { + resp.setStatus(HttpServletResponse.SC_NOT_FOUND); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java index 8cb923a..f0f2eb2 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java @@ -72,7 +72,7 @@ if (!DateUtil.verification(startTime, DateUtil.formatter)){ WVPResult<RecordInfo> wvpResult = new WVPResult<>(); wvpResult.setCode(-1); - wvpResult.setMsg("startTime error, format is " + DateUtil.yyyy_MM_dd_HH_mm_ss); + wvpResult.setMsg("startTime error, format is " + DateUtil.PATTERN); ResponseEntity<WVPResult<RecordInfo>> resultResponseEntity = new ResponseEntity<>(wvpResult, HttpStatus.OK); result.setResult(resultResponseEntity); @@ -81,7 +81,7 @@ if (!DateUtil.verification(endTime, DateUtil.formatter)){ WVPResult<RecordInfo> wvpResult = new WVPResult<>(); wvpResult.setCode(-1); - wvpResult.setMsg("endTime error, format is " + DateUtil.yyyy_MM_dd_HH_mm_ss); + wvpResult.setMsg("endTime error, format is " + DateUtil.PATTERN); ResponseEntity<WVPResult<RecordInfo>> resultResponseEntity = new ResponseEntity<>(wvpResult, HttpStatus.OK); result.setResult(resultResponseEntity); return result; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java index 65f5f7c..a9b23ef 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java @@ -76,14 +76,7 @@ logger.warn("鑷姩璁板綍鏃ュ織鍔熻兘宸插叧闂紝鏌ヨ缁撴灉鍙兘涓嶅畬鏁淬��"); } - try { - if (startTime != null) { - DateUtil.format.parse(startTime); - } - if (endTime != null) { - DateUtil.format.parse(endTime); - } - } catch (ParseException e) { + if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){ return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); } diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java index d4928ec..3be4be3 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java @@ -146,8 +146,8 @@ // 2-鍩轰簬鍙d护鐨勫弻鍚戣璇�, // 3-鍩轰簬鏁板瓧璇佷功鐨勫弻鍚戣璇� deviceJOSNChannel.put("Status", deviceChannel.getStatus()); - deviceJOSNChannel.put("Longitude", deviceChannel.getLongitude()); - deviceJOSNChannel.put("Latitude", deviceChannel.getLatitude()); + deviceJOSNChannel.put("Longitude", deviceChannel.getLongitudeWgs84()); + deviceJOSNChannel.put("Latitude", deviceChannel.getLatitudeWgs84()); deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 浜戝彴绫诲瀷, 0 - 鏈煡, 1 - 鐞冩満, 2 - 鍗婄悆, // 3 - 鍥哄畾鏋満, 4 - 閬ユ帶鏋満 deviceJOSNChannel.put("CustomPTZType", ""); diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 1233a89..9dedcb1 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -32,7 +32,7 @@ datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false + url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true username: root password: root123 druid: diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 3531431..35ddc86 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -20,7 +20,7 @@ datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true username: root password: 123456 druid: diff --git a/src/main/resources/application-docker.yml b/src/main/resources/application-docker.yml index 1653a58..53a8635 100644 --- a/src/main/resources/application-docker.yml +++ b/src/main/resources/application-docker.yml @@ -20,7 +20,7 @@ datasource: # 浣跨敤mysql 鎵撳紑23-28琛屾敞閲婏紝 鍒犻櫎29-36琛� name: wvp - url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false&allowMultiQueries=true username: root password: root type: com.alibaba.druid.pool.DruidDataSource diff --git a/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java b/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java index 6d6ff37..c627511 100644 --- a/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java +++ b/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java @@ -8,6 +8,10 @@ import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.temporal.TemporalAccessor; import java.util.Date; @@ -64,8 +68,8 @@ * * 7鍏朵粬鎶ヨ;鍙互涓虹洿鎺ョ粍鍚堝12涓虹數璇濇姤璀︽垨 璁惧鎶ヨ- */ deviceAlarm.setAlarmMethod((int)(Math.random()*7 + 1) + ""); - Date date = randomDate("2021-01-01 00:00:00", "2021-06-01 00:00:00"); - deviceAlarm.setAlarmTime(DateUtil.format.format(date)); + Instant date = randomDate("2021-01-01 00:00:00", "2021-06-01 00:00:00"); + deviceAlarm.setAlarmTime(DateUtil.formatter.format(date)); /** * 鎶ヨ绾у埆, 1涓轰竴绾ц鎯�, 2涓轰簩绾ц鎯�, 3涓轰笁绾ц鎯�, 4涓哄洓绾� 璀︽儏- */ @@ -85,17 +89,20 @@ - private Date randomDate(String beginDate, String endDate) { + private Instant randomDate(String beginDate, String endDate) { try { - Date start = DateUtil.format.parse(beginDate);//鏋勯�犲紑濮嬫棩鏈� - Date end = DateUtil.format.parse(endDate);//鏋勯�犵粨鏉熸棩鏈� + //鏋勯�犲紑濮嬫棩鏈� + LocalDateTime start = LocalDateTime.parse(beginDate, DateUtil.formatter); + + //鏋勯�犵粨鏉熸棩鏈� + LocalDateTime end = LocalDateTime.parse(endDate, DateUtil.formatter); //getTime()琛ㄧず杩斿洖鑷� 1970 骞� 1 鏈� 1 鏃� 00:00:00 GMT 浠ユ潵姝� Date 瀵硅薄琛ㄧず鐨勬绉掓暟銆� - if (start.getTime() >= end.getTime()) { + if (start.isAfter(end)) { return null; } - long date = random(start.getTime(), end.getTime()); - return new Date(date); + long date = random(start.toInstant(ZoneOffset.of("+8")).toEpochMilli(), end.toInstant(ZoneOffset.of("+8")).toEpochMilli()); + return Instant.ofEpochMilli(date); } catch (Exception e) { e.printStackTrace(); } diff --git a/web_src/package.json b/web_src/package.json index 1e7f043..b825f84 100644 --- a/web_src/package.json +++ b/web_src/package.json @@ -52,7 +52,7 @@ "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "semver": "^5.3.0", - "shelljs": "^0.7.6", + "shelljs": "^0.8.5", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", "vue-loader": "^13.3.0", diff --git a/web_src/src/App.vue b/web_src/src/App.vue index 3590f73..4ae7ea8 100644 --- a/web_src/src/App.vue +++ b/web_src/src/App.vue @@ -76,7 +76,7 @@ line-height: 60px; } .el-main { - background-color: #e9eef3; + background-color: #f0f2f5; color: #333; text-align: center; padding-top: 0px !important; @@ -101,4 +101,8 @@ box-shadow: inset 0 0 6px rgba(0, 0, 0, .1); -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1); } +.table-header { + color: #727272; + font-weight: 600; +} </style> diff --git a/web_src/src/components/CloudRecord.vue b/web_src/src/components/CloudRecord.vue index 1d0819b..897e142 100644 --- a/web_src/src/components/CloudRecord.vue +++ b/web_src/src/components/CloudRecord.vue @@ -18,19 +18,17 @@ <div v-if="!recordDetail"> <!--璁惧鍒楄〃--> - <el-table :data="recordList" border style="width: 100%" :height="winHeight"> - <el-table-column prop="app" label="搴旂敤鍚�" align="center"> + <el-table :data="recordList" style="width: 100%" :height="winHeight"> + <el-table-column prop="app" label="搴旂敤鍚�" > </el-table-column> - <el-table-column prop="stream" label="娴両D" align="center"> + <el-table-column prop="stream" label="娴両D" > </el-table-column> - <el-table-column prop="time" label="鏃堕棿" align="center"> + <el-table-column prop="time" label="鏃堕棿" > </el-table-column> - <el-table-column label="鎿嶄綔" width="360" align="center" fixed="right"> + <el-table-column label="鎿嶄綔" width="360" fixed="right"> <template slot-scope="scope"> - <el-button-group> - <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">鏌ョ湅</el-button> - <!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">鍒犻櫎</el-button>--> - </el-button-group> + <el-button size="medium" icon="el-icon-folder-opened" type="text" @click="showRecordDetail(scope.row)">鏌ョ湅</el-button> + <!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">鍒犻櫎</el-button>--> </template> </el-table-column> </el-table> diff --git a/web_src/src/components/DeviceList.vue b/web_src/src/components/DeviceList.vue index 62cba31..1911d1d 100644 --- a/web_src/src/components/DeviceList.vue +++ b/web_src/src/components/DeviceList.vue @@ -7,34 +7,33 @@ @click="getDeviceList()"></el-button> </div> </div> - <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> <!--璁惧鍒楄〃--> - <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight"> - <el-table-column prop="name" label="鍚嶇О" align="center"> + <el-table :data="deviceList" style="width: 100%;font-size: 12px;" :height="winHeight" header-row-class-name="table-header"> + <el-table-column prop="name" label="鍚嶇О" min-width="160"> </el-table-column> - <el-table-column prop="deviceId" label="璁惧缂栧彿" width="180" align="center"> + <el-table-column prop="deviceId" label="璁惧缂栧彿" min-width="200" > </el-table-column> - <el-table-column label="鍦板潃" width="180" align="center"> + <el-table-column label="鍦板潃" min-width="160" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag> </div> </template> </el-table-column> - <el-table-column prop="manufacturer" label="鍘傚" align="center"> + <el-table-column prop="manufacturer" label="鍘傚" min-width="120" > </el-table-column> - <el-table-column label="娴佷紶杈撴ā寮�" align="center" width="120"> + <el-table-column label="娴佷紶杈撴ā寮�" min-width="160" > <template slot-scope="scope"> - <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="璇烽�夋嫨"> + <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="璇烽�夋嫨" style="width: 120px"> <el-option key="UDP" label="UDP" value="UDP"></el-option> <el-option key="TCP-ACTIVE" label="TCP涓诲姩妯″紡" :disabled="true" value="TCP-ACTIVE"></el-option> <el-option key="TCP-PASSIVE" label="TCP琚姩妯″紡" value="TCP-PASSIVE"></el-option> </el-select> </template> </el-table-column> - <el-table-column prop="channelCount" label="閫氶亾鏁�" align="center"> + <el-table-column prop="channelCount" label="閫氶亾鏁�" min-width="120" > </el-table-column> - <el-table-column label="鐘舵��" width="120" align="center"> + <el-table-column label="鐘舵��" min-width="120"> <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.online == 1">鍦ㄧ嚎</el-tag> @@ -42,30 +41,32 @@ </div> </template> </el-table-column> - <el-table-column prop="keepaliveTime" label="鏈�杩戝績璺�" align="center" width="140"> + <el-table-column prop="keepaliveTime" label="鏈�杩戝績璺�" min-width="160" > </el-table-column> - <el-table-column prop="registerTime" label="鏈�杩戞敞鍐�" align="center" width="140"> + <el-table-column prop="registerTime" label="鏈�杩戞敞鍐�" min-width="160"> </el-table-column> - <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" align="center" width="140"> - </el-table-column> - <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" align="center" width="140"> - </el-table-column> +<!-- <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" width="140">--> +<!-- </el-table-column>--> +<!-- <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="140">--> +<!-- </el-table-column>--> - <el-table-column label="鎿嶄綔" width="450" align="center" fixed="right"> + <el-table-column label="鎿嶄綔" min-width="450" fixed="right"> <template slot-scope="scope"> - <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)" + <el-button type="text" size="medium" v-bind:disabled="scope.row.online==0" icon="el-icon-refresh" @click="refDevice(scope.row)" @mouseover="getTooltipContent(scope.row.deviceId)">鍒锋柊 </el-button> - <el-button-group> - <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" - type="primary" @click="showChannelList(scope.row)">閫氶亾 - </el-button> - <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" - @click="showDevicePosition(scope.row)">瀹氫綅 - </el-button> - <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">缂栬緫</el-button> - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">鍒犻櫎</el-button> - </el-button-group> + <el-divider direction="vertical"></el-divider> + <el-button type="text" size="medium" icon="el-icon-video-camera" v-bind:disabled="scope.row.online==0" + @click="showChannelList(scope.row)">閫氶亾 + </el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="text" + @click="showDevicePosition(scope.row)">瀹氫綅 + </el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">缂栬緫</el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-delete" type="text" @click="deleteDevice(scope.row)" style="color: #f56c6c">鍒犻櫎</el-button> </template> </el-table-column> </el-table> @@ -347,4 +348,5 @@ padding: 0.3rem; width: 14.4rem; } + </style> diff --git a/web_src/src/components/MediaServerManger.vue b/web_src/src/components/MediaServerManger.vue index 2e3eeef..1d3c057 100644 --- a/web_src/src/components/MediaServerManger.vue +++ b/web_src/src/components/MediaServerManger.vue @@ -15,7 +15,7 @@ <span style="font-size: 16px">{{item.id}}</span> <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">缂栬緫</el-button> <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">鏌ョ湅</el-button> - <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">绉婚櫎</el-button> + <el-button v-if="!item.defaultServer" icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">绉婚櫎</el-button> <div style="margin-top: 13px; line-height: 12px; "> <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span> <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span> diff --git a/web_src/src/components/ParentPlatformList.vue b/web_src/src/components/ParentPlatformList.vue index 20a3e82..3ae0b65 100644 --- a/web_src/src/components/ParentPlatformList.vue +++ b/web_src/src/components/ParentPlatformList.vue @@ -4,14 +4,15 @@ <div class="page-title">涓婄骇骞冲彴鍒楄〃</div> <div class="page-header-btn"> <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">娣诲姞</el-button> + <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> </div> </div> <!--璁惧鍒楄〃--> - <el-table :data="platformList" border style="width: 100%" :height="winHeight"> - <el-table-column prop="name" label="鍚嶇О" align="center"></el-table-column> - <el-table-column prop="serverGBId" label="骞冲彴缂栧彿" align="center"></el-table-column> - <el-table-column label="鏄惁鍚敤" width="120" align="center"> + <el-table :data="platformList" style="width: 100%" :height="winHeight"> + <el-table-column prop="name" label="鍚嶇О" ></el-table-column> + <el-table-column prop="serverGBId" label="骞冲彴缂栧彿" min-width="200"></el-table-column> + <el-table-column label="鏄惁鍚敤" min-width="80" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.enable">宸插惎鐢�</el-tag> @@ -19,7 +20,7 @@ </div> </template> </el-table-column> - <el-table-column label="鐘舵��" width="120" align="center"> + <el-table-column label="鐘舵��" min-width="80" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.status">鍦ㄧ嚎</el-tag> @@ -27,17 +28,17 @@ </div> </template> </el-table-column> - <el-table-column label="鍦板潃" width="180" align="center"> + <el-table-column label="鍦板潃" min-width="160" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag> </div> </template> </el-table-column> - <el-table-column prop="deviceGBId" label="璁惧鍥芥爣缂栧彿" width="200" align="center"></el-table-column> - <el-table-column prop="transport" label="淇′护浼犺緭妯″紡" width="120" align="center"></el-table-column> - <el-table-column prop="channelCount" label="閫氶亾鏁�" width="120" align="center"></el-table-column> - <el-table-column label="璁㈤槄淇℃伅" width="240" align="center" fixed="right"> + <el-table-column prop="deviceGBId" label="璁惧鍥芥爣缂栧彿" min-width="200" ></el-table-column> + <el-table-column prop="transport" label="淇′护浼犺緭妯″紡" min-width="120" ></el-table-column> + <el-table-column prop="channelCount" label="閫氶亾鏁�" min-width="120" ></el-table-column> + <el-table-column label="璁㈤槄淇℃伅" min-width="120" fixed="right"> <template slot-scope="scope"> <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="鎶ヨ璁㈤槄" class="iconfont icon-gbaojings subscribe-on " ></i> <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="鎶ヨ璁㈤槄" class="iconfont icon-gbaojings subscribe-off " ></i> @@ -48,11 +49,11 @@ </template> </el-table-column> - <el-table-column label="鎿嶄綔" width="300" align="center" fixed="right"> + <el-table-column label="鎿嶄綔" min-width="240" fixed="right"> <template slot-scope="scope"> - <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">缂栬緫</el-button> - <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">閫夋嫨閫氶亾</el-button> - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">鍒犻櫎</el-button> + <el-button size="medium" icon="el-icon-edit" type="text" @click="editPlatform(scope.row)">缂栬緫</el-button> + <el-button size="medium" icon="el-icon-share" type="text" @click="chooseChannel(scope.row)">閫夋嫨閫氶亾</el-button> + <el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c" @click="deletePlatform(scope.row)">鍒犻櫎</el-button> </template> </el-table-column> </el-table> @@ -168,6 +169,9 @@ console.log(error); }); + }, + refresh: function (){ + this.initData(); } } diff --git a/web_src/src/components/PushVideoList.vue b/web_src/src/components/PushVideoList.vue index 7b5a406..678d13f 100644 --- a/web_src/src/components/PushVideoList.vue +++ b/web_src/src/components/PushVideoList.vue @@ -34,52 +34,54 @@ <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">鎵归噺绉婚櫎 </el-button> + <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> </div> </div> <devicePlayer ref="devicePlayer"></devicePlayer> <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB> - <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight" + <el-table ref="pushListTable" :data="pushList" style="width: 100%" :height="winHeight" @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream"> - <el-table-column align="center" type="selection" :reserve-selection="true" width="55"> + <el-table-column type="selection" :reserve-selection="true" min-width="55"> </el-table-column> - <el-table-column prop="name" label="鍚嶇О" align="center"> + <el-table-column prop="name" label="鍚嶇О" min-width="200"> </el-table-column> - <el-table-column prop="app" label="APP" align="center"> + <el-table-column prop="app" label="APP" min-width="200"> </el-table-column> - <el-table-column prop="stream" label="娴両D" align="center"> + <el-table-column prop="stream" label="娴両D" min-width="200"> </el-table-column> - <el-table-column prop="gbId" label="鍥芥爣缂栫爜" width="200" align="center"> + <el-table-column prop="gbId" label="鍥芥爣缂栫爜" min-width="200" > </el-table-column> - <el-table-column prop="mediaServerId" label="娴佸獟浣�" width="200" align="center"> + <el-table-column prop="mediaServerId" label="娴佸獟浣�" min-width="200" > </el-table-column> - <el-table-column label="寮�濮嬫椂闂�" align="center" width="200"> + <el-table-column label="寮�濮嬫椂闂�" min-width="200"> <template slot-scope="scope"> <el-button-group> {{ dateFormat(parseInt(scope.row.createStamp)) }} </el-button-group> </template> </el-table-column> - <el-table-column label="姝e湪鎺ㄦ祦" align="center" width="100"> + <el-table-column label="姝e湪鎺ㄦ祦" min-width="100"> <template slot-scope="scope"> {{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '鏄�' : '鍚�' }} </template> </el-table-column> - <el-table-column label="鎿嶄綔" width="360" align="center" fixed="right"> + <el-table-column label="鎿嶄綔" min-width="360" fixed="right"> <template slot-scope="scope"> - <el-button-group> - <el-button size="mini" icon="el-icon-video-play" - v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status" - @click="playPush(scope.row)">鎾斁 - </el-button> - <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">绉婚櫎</el-button> - <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId" - @click="addToGB(scope.row)">鍔犲叆鍥芥爣 - </el-button> - <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId" - @click="removeFromGB(scope.row)">绉诲嚭鍥芥爣 - </el-button> - </el-button-group> + <el-button size="medium" icon="el-icon-video-play" + v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status" + @click="playPush(scope.row)" type="text">鎾斁 + </el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-delete" type="text" @click="stopPush(scope.row)" style="color: #f56c6c" >绉婚櫎</el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-position" type="text" v-if="!!!scope.row.gbId" + @click="addToGB(scope.row)">鍔犲叆鍥芥爣 + </el-button> + <el-divider v-if="!!!scope.row.gbId" direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-position" type="text" v-if="!!scope.row.gbId" + @click="removeFromGB(scope.row)">绉诲嚭鍥芥爣 + </el-button> </template> </el-table-column> </el-table> @@ -284,6 +286,9 @@ handleSelectionChange: function (val) { this.multipleSelection = val; }, + refresh: function () { + this.initData(); + }, } }; </script> diff --git a/web_src/src/components/StreamProxyList.vue b/web_src/src/components/StreamProxyList.vue index d553392..9f7ed61 100644 --- a/web_src/src/components/StreamProxyList.vue +++ b/web_src/src/components/StreamProxyList.vue @@ -5,14 +5,15 @@ <div class="page-header-btn"> <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">娣诲姞浠g悊</el-button> <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">鎼滅储ONVIF</el-button> + <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> </div> </div> <devicePlayer ref="devicePlayer"></devicePlayer> - <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight"> - <el-table-column prop="name" label="鍚嶇О" align="center" show-overflow-tooltip/> - <el-table-column prop="app" label="娴佸簲鐢ㄥ悕" align="center" show-overflow-tooltip/> - <el-table-column prop="stream" label="娴両D" align="center" show-overflow-tooltip/> - <el-table-column label="娴佸湴鍧�" width="400" align="center" show-overflow-tooltip > + <el-table :data="streamProxyList" style="width: 100%" :height="winHeight"> + <el-table-column prop="name" label="鍚嶇О" min-width="120" show-overflow-tooltip/> + <el-table-column prop="app" label="娴佸簲鐢ㄥ悕" min-width="120" show-overflow-tooltip/> + <el-table-column prop="stream" label="娴両D" min-width="120" show-overflow-tooltip/> + <el-table-column label="娴佸湴鍧�" min-width="400" show-overflow-tooltip > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> @@ -27,8 +28,8 @@ </div> </template> </el-table-column> - <el-table-column prop="mediaServerId" label="娴佸獟浣�" width="150" align="center"></el-table-column> - <el-table-column label="绫诲瀷" width="100" align="center"> + <el-table-column prop="mediaServerId" label="娴佸獟浣�" min-width="180" ></el-table-column> + <el-table-column label="绫诲瀷" width="100" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{scope.row.type}}</el-tag> @@ -36,8 +37,8 @@ </template> </el-table-column> - <el-table-column prop="gbId" label="鍥芥爣缂栫爜" width="180" align="center" show-overflow-tooltip/> - <el-table-column label="鐘舵��" width="120" align="center"> + <el-table-column prop="gbId" label="鍥芥爣缂栫爜" min-width="180" show-overflow-tooltip/> + <el-table-column label="鐘舵��" min-width="120" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.status">鍦ㄧ嚎</el-tag> @@ -45,7 +46,7 @@ </div> </template> </el-table-column> - <el-table-column label="鍚敤" width="120" align="center"> + <el-table-column label="鍚敤" min-width="120" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.enable">宸插惎鐢�</el-tag> @@ -53,8 +54,8 @@ </div> </template> </el-table-column> - <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" align="center" width="150" show-overflow-tooltip/> - <el-table-column label="杞琀LS" width="120" align="center"> + <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" min-width="150" show-overflow-tooltip/> + <el-table-column label="杞琀LS" min-width="120" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.enable_hls">宸插惎鐢�</el-tag> @@ -62,7 +63,7 @@ </div> </template> </el-table-column> - <el-table-column label="MP4褰曞埗" width="120" align="center"> + <el-table-column label="MP4褰曞埗" min-width="120" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.enable_mp4">宸插惎鐢�</el-tag> @@ -70,7 +71,7 @@ </div> </template> </el-table-column> - <el-table-column label="鏃犱汉瑙傜湅鑷姩鍒犻櫎" width="160" align="center"> + <el-table-column label="鏃犱汉瑙傜湅鑷姩鍒犻櫎" min-width="160" > <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">宸插惎鐢�</el-tag> @@ -80,14 +81,15 @@ </el-table-column> - <el-table-column label="鎿嶄綔" width="360" align="center" fixed="right"> + <el-table-column label="鎿嶄綔" width="360" fixed="right"> <template slot-scope="scope"> - <el-button-group> - <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">鎾斁</el-button> - <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">鍋滅敤</el-button> - <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">鍚敤</el-button> - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">鍒犻櫎</el-button> - </el-button-group> + <el-button size="medium" icon="el-icon-video-play" type="text" v-if="scope.row.enable" @click="play(scope.row)">鎾斁</el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-switch-button" type="text" v-if="scope.row.enable" @click="stop(scope.row)">鍋滅敤</el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-check" type="text" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">鍚敤</el-button> + <el-divider v-if="!scope.row.enable" direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c" @click="deleteStreamProxy(scope.row)">鍒犻櫎</el-button> </template> </el-table-column> </el-table> @@ -305,8 +307,10 @@ console.log(error); that.getListLoading = false; }); - } - + }, + refresh: function (){ + this.initData(); + } } }; </script> diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 2d62e29..d27e62b 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -2,10 +2,10 @@ <div id="channelList" style="width: 100%"> <div class="page-header"> <div class="page-title"> - <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice"> - 杩斿洖 - </el-button> - 閫氶亾鍒楄〃({{ parentChannelId == 0 ? deviceId : parentChannelId }})</div> + <el-button icon="el-icon-back" size="mini" style="font-size: 20px; color: #000;" type="text" @click="showDevice" ></el-button> + <el-divider direction="vertical"></el-divider> + 閫氶亾鍒楄〃 + </div> <div class="page-header-btn"> 鎼滅储: <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="鍏抽敭瀛�" @@ -25,84 +25,85 @@ <el-option label="鍦ㄧ嚎" value="true"></el-option> <el-option label="绂荤嚎" value="false"></el-option> </el-select> - <el-checkbox size="mini" v-model="autoList" @change="autoListChange"> - 鑷姩鍒锋柊 - </el-checkbox> + <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> </div> </div> <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> <!--璁惧鍒楄〃--> - <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%"> - <el-table-column prop="channelId" label="閫氶亾缂栧彿" width="200"> + <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%" header-row-class-name="table-header"> + <el-table-column prop="channelId" label="閫氶亾缂栧彿" min-width="200"> </el-table-column> - <el-table-column prop="name" label="閫氶亾鍚嶇О"> + <el-table-column prop="deviceId" label="璁惧缂栧彿" min-width="200"> </el-table-column> - <el-table-column label="蹇収" width="80" align="center"> - <template slot-scope="scope"> - <img style="max-height: 3rem;max-width: 4rem;" - v-if="scope.row.subCount === 0 && scope.row.parental === 0" - :id="scope.row.deviceId + '_' + scope.row.channelId" - :src="getSnap(scope.row)" - @error="getSnapErrorEvent($event.target.id)" - alt=""> - <!-- <el-image--> - <!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"--> - <!-- :src="getSnap(scope.row)"--> - <!-- @error="getSnapErrorEvent($event, scope.row)"--> - <!-- :fit="'contain'">--> - <!-- <div slot="error" class="image-slot">--> - <!-- <i class="el-icon-picture-outline"></i>--> - <!-- </div>--> - <!-- </el-image>--> + <el-table-column prop="name" label="閫氶亾鍚嶇О" min-width="200"> + </el-table-column> + <el-table-column label="蹇収" min-width="120"> + <template v-slot:default="scope"> + <el-image + :src="getSnap(scope.row)" + :preview-src-list="getBigSnap(scope.row)" + @error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)" + :fit="'contain'" + style="width: 60px"> + <div slot="error" class="image-slot"> + <i class="el-icon-picture-outline"></i> + </div> + </el-image> </template> </el-table-column> - <el-table-column prop="subCount" label="瀛愯妭鐐规暟"> + <el-table-column prop="subCount" label="瀛愯妭鐐规暟" min-width="120"> </el-table-column> - <el-table-column prop="manufacture" label="鍘傚"> + <el-table-column prop="manufacture" label="鍘傚" min-width="120"> </el-table-column> - <el-table-column label="浣嶇疆淇℃伅" align="center"> + <el-table-column label="浣嶇疆淇℃伅" min-width="200"> <template slot-scope="scope"> - <span>{{ scope.row.longitude }},{{ scope.row.latitude }}</span> + <span v-if="scope.row.longitude*scope.row.latitude > 0">{{ scope.row.longitude }},<br>{{ scope.row.latitude }}</span> + <span v-if="scope.row.longitude*scope.row.latitude === 0">鏃�</span> </template> </el-table-column> - <el-table-column prop="ptztypeText" label="浜戝彴绫诲瀷"/> - <el-table-column label="寮�鍚煶棰�" align="center"> + <el-table-column prop="ptztypeText" label="浜戝彴绫诲瀷" min-width="120"/> + <el-table-column label="寮�鍚煶棰�" min-width="120"> <template slot-scope="scope"> <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF"> </el-switch> </template> </el-table-column> - <el-table-column label="鐘舵��" width="180" align="center"> + <el-table-column label="鐘舵��" min-width="120"> <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> - <el-tag size="medium" v-if="scope.row.status == 1">寮�鍚�</el-tag> - <el-tag size="medium" type="info" v-if="scope.row.status == 0">鍏抽棴</el-tag> + <el-tag size="medium" v-if="scope.row.status === 1">鍦ㄧ嚎</el-tag> + <el-tag size="medium" type="info" v-if="scope.row.status === 0">绂荤嚎</el-tag> </div> </template> </el-table-column> - <el-table-column label="鎿嶄綔" width="280" align="center" fixed="right"> + <el-table-column label="鎿嶄綔" min-width="280" fixed="right"> <template slot-scope="scope"> - <el-button-group> - <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">鎾斁</el-button> --> - <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">鎾斁</el-button> - <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" - @click="stopDevicePush(scope.row)">鍋滄 - </el-button> - <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0 || scope.row.parental === 1" - @click="changeSubchannel(scope.row)">鏌ョ湅 - </el-button> - <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">璁惧褰曞儚 - </el-button> - <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">褰曞儚鏌ヨ</el-button> --> - </el-button-group> + <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">鎾斁</el-button> --> + <el-button size="medium" icon="el-icon-video-play" type="text" @click="sendDevicePush(scope.row)">鎾斁</el-button> + <el-button size="medium" icon="el-icon-switch-button" type="text" style="color: #f56c6c" v-if="!!scope.row.streamId" + @click="stopDevicePush(scope.row)">鍋滄 + </el-button> + <el-divider direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-s-open" type="text" v-if="scope.row.subCount > 0 || scope.row.parental === 1" + @click="changeSubchannel(scope.row)">鏌ョ湅 + </el-button> + <el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1" direction="vertical"></el-divider> + <el-button size="medium" icon="el-icon-video-camera" type="text" @click="queryRecords(scope.row)">璁惧褰曞儚 + </el-button> </template> </el-table-column> </el-table> - <el-pagination style="float: right" @size-change="handleSizeChange" @current-change="currentChange" - :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]" - layout="total, sizes, prev, pager, next" :total="total"> + <el-pagination + style="float: right" + @size-change="handleSizeChange" + @current-change="currentChange" + :current-page="currentPage" + :page-size="count" + :page-sizes="[15, 25, 35, 50]" + layout="total, sizes, prev, pager, next" + :total="total"> </el-pagination> </div> </template> @@ -111,6 +112,8 @@ import devicePlayer from './dialog/devicePlayer.vue' import uiHeader from '../layout/UiHeader.vue' import moment from "moment"; +import DviceService from "./service/DeviceService"; +import DeviceService from "./service/DeviceService"; export default { name: 'channelList', @@ -120,6 +123,8 @@ }, data() { return { + deviceService: new DeviceService(), + device: null, deviceId: this.$route.params.deviceId, parentChannelId: this.$route.params.parentChannelId, deviceChannelList: [], @@ -135,16 +140,21 @@ total: 0, beforeUrl: "/deviceList", isLoging: false, - autoList: true, loadSnap: {} }; }, mounted() { - this.initData(); - if (this.autoList) { - this.updateLooper = setInterval(this.initData, 5000); + if (this.deviceId) { + this.deviceService.getDevice(this.deviceId, (result)=>{ + this.device = result; + + }, (error)=>{ + console.log("鑾峰彇璁惧淇℃伅澶辫触") + console.error(error) + }) } + this.initData(); }, destroyed() { @@ -177,12 +187,8 @@ }) }, handleSizeChange: function (val) { - var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1` - this.$router.push(url).then(() => { - this.initParam(); - this.initData(); - }) - + this.count = val; + this.getDeviceChannelList(); }, getDeviceChannelList: function () { let that = this; @@ -227,7 +233,7 @@ setTimeout(() => { let snapId = deviceId + "_" + channelId; - that.loadSnap[snapId] = 0; + that.loadSnap[deviceId + channelId] = 0; that.getSnapErrorEvent(snapId) }, 5000) that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { @@ -269,19 +275,24 @@ }); }, getSnap: function (row) { - return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg' + let url = (process.env.NODE_ENV === 'development'? "debug": "") + '/api/device/query/snap/' + row.deviceId + '/' + row.channelId + return url }, - getSnapErrorEvent: function (id) { + getBigSnap: function (row) { + return [this.getSnap(row)] + }, + getSnapErrorEvent: function (deviceId, channelId) { - if (typeof (this.loadSnap[id]) != "undefined") { - console.log("涓嬭浇鎴浘" + this.loadSnap[id]) - if (this.loadSnap[id] > 5) { - delete this.loadSnap[id]; + if (typeof (this.loadSnap[deviceId + channelId]) != "undefined") { + console.log("涓嬭浇鎴浘" + this.loadSnap[deviceId + channelId]) + if (this.loadSnap[deviceId + channelId] > 5) { + delete this.loadSnap[deviceId + channelId]; return; } setTimeout(() => { - this.loadSnap[id]++ - document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime()) + let url = (process.env.NODE_ENV === 'development'? "debug": "") + '/api/device/query/snap/' + deviceId + '/' + channelId + this.loadSnap[deviceId + channelId]++ + document.getElementById(deviceId + channelId).setAttribute("src", url + '?' + new Date().getTime()) }, 1000) } @@ -342,12 +353,8 @@ console.log(JSON.stringify(res)); }); }, - autoListChange: function () { - if (this.autoList) { - this.updateLooper = setInterval(this.initData, 1500); - } else { - window.clearInterval(this.updateLooper); - } + refresh: function () { + this.initData(); } } diff --git a/web_src/src/components/common/DeviceTree.vue b/web_src/src/components/common/DeviceTree.vue index 066c344..73618cc 100644 --- a/web_src/src/components/common/DeviceTree.vue +++ b/web_src/src/components/common/DeviceTree.vue @@ -84,22 +84,34 @@ }else { resolve([]) } + }, (list)=>{ + console.log("璁惧鍔犺浇瀹屾垚") }, (error)=>{ }) } if (node.level === 1) { - this.deviceService.getAllChannel(true, true, node.data.id, (catalogData) => { - this.deviceService.getAllChannel(false, true, node.data.id, (channelData) => { - let data = catalogData.concat(channelData) - this.channelDataHandler(data, resolve) + let channelArray = [] + this.deviceService.getAllChannel(true, true, node.data.id, catalogData =>{ + channelArray = channelArray.concat(catalogData) + this.channelDataHandler(channelArray, resolve) + },(endCatalogData) => { + this.deviceService.getAllChannel(false, true, node.data.id, channelData => { + channelArray = channelArray.concat(channelData) + this.channelDataHandler(channelArray, resolve) + }, endChannelList => { + }) }) }else if (node.level > 1){ + let channelArray = [] this.deviceService.getAllSubChannel(true, node.data.deviceId, node.data.id, (catalogData)=>{ + channelArray = channelArray.concat(catalogData) + this.channelDataHandler(channelArray, resolve) + }, (endCatalogData)=>{ this.deviceService.getAllSubChannel(false, node.data.deviceId, node.data.id, (channelData)=>{ - let data = catalogData.concat(channelData) - this.channelDataHandler(data, resolve) + channelArray = channelArray.concat(channelData) + this.channelDataHandler(channelArray, resolve) }) }) } diff --git a/web_src/src/components/common/jessibuca.vue b/web_src/src/components/common/jessibuca.vue index 2eda2dc..7ab0b93 100644 --- a/web_src/src/components/common/jessibuca.vue +++ b/web_src/src/components/common/jessibuca.vue @@ -23,11 +23,11 @@ </template> <script> +let jessibucaPlayer = {}; export default { name: 'jessibuca', data() { return { - jessibuca: null, playing: false, isNotMute: false, quieting: false, @@ -49,6 +49,7 @@ window.onerror = (msg) => { // console.error(msg) }; + console.log(this._uid) let paramUrl = decodeURIComponent(this.$route.params.url) this.$nextTick(() => { this.updatePlayerDomSize() @@ -88,7 +89,7 @@ let options = {}; console.log("hasAudio " + this.hasAudio) - this.jessibuca = new window.Jessibuca(Object.assign( + jessibucaPlayer[this._uid] = new window.Jessibuca(Object.assign( { container: this.$refs.container, videoBuffer: 0.2, // 鏈�澶х紦鍐叉椂闀匡紝鍗曚綅绉� @@ -117,70 +118,70 @@ }, options )); - + let jessibuca = jessibucaPlayer[this._uid]; let _this = this; - this.jessibuca.on("load", function () { + jessibuca.on("load", function () { console.log("on load init"); }); - this.jessibuca.on("log", function (msg) { + jessibuca.on("log", function (msg) { console.log("on log", msg); }); - this.jessibuca.on("record", function (msg) { + jessibuca.on("record", function (msg) { console.log("on record:", msg); }); - this.jessibuca.on("pause", function () { + jessibuca.on("pause", function () { _this.playing = false; }); - this.jessibuca.on("play", function () { + jessibuca.on("play", function () { _this.playing = true; }); - this.jessibuca.on("fullscreen", function (msg) { + jessibuca.on("fullscreen", function (msg) { console.log("on fullscreen", msg); _this.fullscreen = msg }); - this.jessibuca.on("mute", function (msg) { + jessibuca.on("mute", function (msg) { console.log("on mute", msg); _this.isNotMute = !msg; }); - this.jessibuca.on("audioInfo", function (msg) { + jessibuca.on("audioInfo", function (msg) { // console.log("audioInfo", msg); }); - this.jessibuca.on("videoInfo", function (msg) { + jessibuca.on("videoInfo", function (msg) { // this.videoInfo = msg; console.log("videoInfo", msg); }); - this.jessibuca.on("bps", function (bps) { + jessibuca.on("bps", function (bps) { // console.log('bps', bps); }); let _ts = 0; - this.jessibuca.on("timeUpdate", function (ts) { + jessibuca.on("timeUpdate", function (ts) { // console.log('timeUpdate,old,new,timestamp', _ts, ts, ts - _ts); _ts = ts; }); - this.jessibuca.on("videoInfo", function (info) { + jessibuca.on("videoInfo", function (info) { console.log("videoInfo", info); }); - this.jessibuca.on("error", function (error) { + jessibuca.on("error", function (error) { console.log("error", error); }); - this.jessibuca.on("timeout", function () { + jessibuca.on("timeout", function () { console.log("timeout"); }); - this.jessibuca.on('start', function () { + jessibuca.on('start', function () { console.log('start'); }) - this.jessibuca.on("performance", function (performance) { + jessibuca.on("performance", function (performance) { let show = "鍗¢】"; if (performance === 2) { show = "闈炲父娴佺晠"; @@ -189,25 +190,25 @@ } _this.performance = show; }); - this.jessibuca.on('buffer', function (buffer) { + jessibuca.on('buffer', function (buffer) { // console.log('buffer', buffer); }) - this.jessibuca.on('stats', function (stats) { + jessibuca.on('stats', function (stats) { // console.log('stats', stats); }) - this.jessibuca.on('kBps', function (kBps) { + jessibuca.on('kBps', function (kBps) { _this.kBps = Math.round(kBps); }); // 鏄剧ず鏃堕棿鎴� PTS - this.jessibuca.on('videoFrame', function () { + jessibuca.on('videoFrame', function () { }) // - this.jessibuca.on('metadata', function () { + jessibuca.on('metadata', function () { }); }, @@ -216,40 +217,40 @@ }, play: function (url) { console.log(url) - if (this.jessibuca) { + if (jessibucaPlayer[this._uid]) { this.destroy(); } this.create(); - this.jessibuca.on("play", () => { + jessibucaPlayer[this._uid].on("play", () => { this.playing = true; this.loaded = true; - this.quieting = this.jessibuca.quieting; + this.quieting = jessibuca.quieting; }); - if (this.jessibuca.hasLoaded()) { - this.jessibuca.play(url); + if (jessibucaPlayer[this._uid].hasLoaded()) { + jessibucaPlayer[this._uid].play(url); } else { - this.jessibuca.on("load", () => { + jessibucaPlayer[this._uid].on("load", () => { console.log("load 鎾斁") - this.jessibuca.play(url); + jessibucaPlayer[this._uid].play(url); }); } }, pause: function () { - if (this.jessibuca) { - this.jessibuca.pause(); + if (jessibucaPlayer[this._uid]) { + jessibucaPlayer[this._uid].pause(); } this.playing = false; this.err = ""; this.performance = ""; }, destroy: function () { - if (this.jessibuca) { - this.jessibuca.destroy(); + if (jessibucaPlayer[this._uid]) { + jessibucaPlayer[this._uid].destroy(); } if (document.getElementById("buttonsBox") == null) { this.$refs.container.appendChild(this.btnDom) } - this.jessibuca = null; + jessibucaPlayer[this._uid] = null; this.playing = false; this.err = ""; this.performance = ""; @@ -262,7 +263,7 @@ }, fullscreenSwich: function () { let isFull = this.isFullscreen() - this.jessibuca.setFullscreen(!isFull) + jessibucaPlayer[this._uid].setFullscreen(!isFull) this.fullscreen = !isFull; }, isFullscreen: function () { @@ -273,8 +274,8 @@ } }, destroyed() { - if (this.jessibuca) { - this.jessibuca.destroy(); + if (jessibucaPlayer[this._uid]) { + jessibucaPlayer[this._uid].destroy(); } this.playing = false; this.loaded = false; diff --git a/web_src/src/components/control.vue b/web_src/src/components/control.vue index b8b3e34..507cc0d 100644 --- a/web_src/src/components/control.vue +++ b/web_src/src/components/control.vue @@ -235,10 +235,8 @@ <el-table-column prop="local_ip" label="鏈湴"></el-table-column> <el-table-column prop="typeid" label="绫诲瀷"></el-table-column> <el-table-column align="right"> - <template slot="header" slot-scope="scope"> - <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button> - </template> - <template slot-scope="scope"> + <template v-slot:default="scope"> + <el-button size="mini" icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button> <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">绉婚櫎 </el-button> </template> diff --git a/web_src/src/components/dialog/deviceEdit.vue b/web_src/src/components/dialog/deviceEdit.vue index 7e4b3b2..a04f021 100644 --- a/web_src/src/components/dialog/deviceEdit.vue +++ b/web_src/src/components/dialog/deviceEdit.vue @@ -39,6 +39,12 @@ <el-form-item label="璇煶鍙戦�侀�氶亾" prop="name"> <el-input v-model="form.audioChannelForReceive" clearable></el-input> </el-form-item> + <el-form-item label="鍦扮悊鍧愭爣绯�" prop="geoCoordSys" > + <el-select v-model="form.geoCoordSys" style="float: left; width: 100%" > + <el-option key="WGS84" label="WGS84" value="WGS84"></el-option> + <el-option key="GCJ02" label="GCJ02" value="GCJ02"></el-option> + </el-select> + </el-form-item> <el-form-item label="鐩綍璁㈤槄" title="0涓哄彇娑堣闃�" prop="subscribeCycleForCatalog" > <el-input v-model="form.subscribeCycleForCatalog" clearable ></el-input> </el-form-item> diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index a98656a..9c254c9 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -3,9 +3,23 @@ <el-dialog title="瑙嗛鎾斁" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()"> <!-- <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer> --> - <player ref="videoPlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :height="false" :hasAudio="hasAudio" fluent autoplay live ></player> + <div style="width: 100%; height: 100%"> + <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer" v-if="Object.keys(this.player).length > 1"> + <el-tab-pane label="Jessibuca" name="jessibuca"> + <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> + </el-tab-pane> + <el-tab-pane label="WebRTC" name="webRTC"> + <rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> + </el-tab-pane> + <el-tab-pane label="h265web">h265web鏁鏈熷緟</el-tab-pane> + <el-tab-pane label="wsPlayer">wsPlayer 鏁鏈熷緟</el-tab-pane> + </el-tabs> + <jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> + <rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> + + </div> <div id="shared" style="text-align: right; margin-top: 1rem;"> - <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick"> + <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick" > <el-tab-pane label="瀹炴椂瑙嗛" name="media"> <div style="margin-bottom: 0.5rem;"> <!-- <el-button type="primary" size="small" @click="playRecord(true, '')">鎾斁</el-button>--> @@ -31,10 +45,100 @@ <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> <span style="width: 5rem; line-height: 2.5rem; text-align: right;">璧勬簮鍦板潃锛�</span> <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" > - <template slot="append"> - <i class="cpoy-btn el-icon-document-copy" title="鐐瑰嚮鎷疯礉" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'鎴愬姛鎷疯礉鍒扮矘璐存澘'})"></i> - </template> + <el-button slot="append" icon="el-icon-document-copy" title="鐐瑰嚮鎷疯礉" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'鎴愬姛鎷疯礉鍒扮矘璐存澘'})"></el-button> + <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl"> + <el-button > + 鏇村鍦板潃<i class="el-icon-arrow-down el-icon--right"></i> + </el-button> + <el-dropdown-menu slot="dropdown" > + <el-dropdown-item :command="streamInfo.flv"> + <el-tag >FLV:</el-tag> + <span>{{ streamInfo.flv }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.https_flv"> + <el-tag >FLV(https):</el-tag> + <span>{{ streamInfo.https_flv }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.ws_flv"> + <el-tag >FLV(ws):</el-tag> + <span >{{ streamInfo.ws_flv }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.wss_flv"> + <el-tag >FLV(wss):</el-tag> + <span>{{ streamInfo.wss_flv }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.fmp4"> + <el-tag >FMP4:</el-tag> + <span>{{ streamInfo.fmp4 }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.https_fmp4"> + <el-tag >FMP4(https):</el-tag> + <span>{{ streamInfo.https_fmp4 }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.ws_fmp4"> + <el-tag >FMP4(ws):</el-tag> + <span>{{ streamInfo.ws_fmp4 }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.wss_fmp4"> + <el-tag >FMP4(wss):</el-tag> + <span>{{ streamInfo.wss_fmp4 }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.hls"> + <el-tag>HLS:</el-tag> + <span>{{ streamInfo.hls }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.https_hls"> + <el-tag >HLS(https):</el-tag> + <span>{{ streamInfo.https_hls }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.ws_hls"> + <el-tag >HLS(ws):</el-tag> + <span>{{ streamInfo.ws_hls }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.wss_hls"> + <el-tag >HLS(wss):</el-tag> + <span>{{ streamInfo.wss_hls }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.ts"> + <el-tag>TS:</el-tag> + <span>{{ streamInfo.ts }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.https_ts"> + <el-tag>TS(https):</el-tag> + <span>{{ streamInfo.https_ts }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.ws_ts"> + <el-tag>TS(ws):</el-tag> + <span>{{ streamInfo.ws_ts }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.wss_ts"> + <el-tag>TS(wss):</el-tag> + <span>{{ streamInfo.wss_ts }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.rtc"> + <el-tag >RTC:</el-tag> + <span>{{ streamInfo.rtc }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.rtmp"> + <el-tag >RTMP:</el-tag> + <span>{{ streamInfo.rtmp }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.rtmps"> + <el-tag >RTMPS:</el-tag> + <span>{{ streamInfo.rtmps }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.rtsp"> + <el-tag >RTSP:</el-tag> + <span>{{ streamInfo.rtsp }}</span> + </el-dropdown-item> + <el-dropdown-item :command="streamInfo.rtsps"> + <el-tag >RTSPS:</el-tag> + <span>{{ streamInfo.rtsps }}</span> + </el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> </el-input> + </div> </el-tab-pane> <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> @@ -115,27 +219,27 @@ <div class="control-panel"> <el-button-group> - <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium" type="info">棰勭疆浣嶇紪鍙�</el-tag> + <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">棰勭疆浣嶇紪鍙�</el-tag> <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">璁剧疆</el-button> <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">璋冪敤</el-button> <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">鍒犻櫎</el-button> - <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium" type="info">宸¤埅閫熷害</el-tag> + <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">宸¤埅閫熷害</el-tag> <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">璁剧疆</el-button> - <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium" type="info">鍋滅暀鏃堕棿</el-tag> + <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">鍋滅暀鏃堕棿</el-tag> <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">璁剧疆</el-button> - <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium" type="info">宸¤埅缁勭紪鍙�</el-tag> + <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">宸¤埅缁勭紪鍙�</el-tag> <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">娣诲姞鐐�</el-button> <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">鍒犻櫎鐐�</el-button> <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">鍒犻櫎缁�</el-button> <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">宸¤埅</el-button> - <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium" type="info">鎵弿閫熷害</el-tag> + <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">鎵弿閫熷害</el-tag> <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">璁剧疆</el-button> - <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium" type="info">鎵弿缁勭紪鍙�</el-tag> + <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">鎵弿缁勭紪鍙�</el-tag> <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">宸﹁竟鐣�</el-button> <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">鍙宠竟鐣�</el-button> @@ -172,26 +276,28 @@ </div> </el-tab-pane> + </el-tabs> </div> </el-dialog> + <recordDownload ref="recordDownload"></recordDownload> </div> </template> <script> -import player from '../dialog/rtcPlayer.vue' +import rtcPlayer from '../dialog/rtcPlayer.vue' // import LivePlayer from '@liveqing/liveplayer' // import player from '../dialog/easyPlayer.vue' -// import player from '../dialog/jessibuca.vue' +import jessibucaPlayer from '../common/jessibuca.vue' +import recordDownload from '../dialog/recordDownload.vue' export default { name: 'devicePlayer', props: {}, components: { - player, + jessibucaPlayer, rtcPlayer, recordDownload, }, computed: { getPlayerShared: function () { - return { sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl), sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>', @@ -199,11 +305,22 @@ }; } }, - created() {}, + created() { + console.log(this.player) + if (Object.keys(this.player).length === 1) { + this.activePlayer = Object.keys(this.player)[0] + } + }, data() { return { video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4', videoUrl: '', + activePlayer: "jessibuca", + // 濡備綍浣犲彧鏄敤涓�绉嶆挱鏀惧櫒锛岀洿鎺ユ敞閲婃帀涓嶇敤鐨勯儴鍒嗗嵆鍙� + player: { + jessibuca : ["ws_flv", "wss_flv"], + webRTC: ["rtc", "rtc"], + }, videoHistory: { date: '', searchHistoryResult: [] //濯掍綋娴佸巻鍙茶褰曟悳绱㈢粨鏋� @@ -241,6 +358,7 @@ seekTime: 0, recordStartTime: 0, showTimeText: "00:00:00", + streamInfo: null, }; }, methods: { @@ -250,7 +368,7 @@ that.tracks = []; that.tracksLoading = true; that.tracksNotLoaded = false; - if (tab.name == "codec") { + if (tab.name === "codec") { this.$axios({ method: 'get', url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId @@ -269,6 +387,12 @@ }).catch(function (e) {}); } }, + changePlayer: function (tab) { + console.log(this.player[tab.name][0]) + this.activePlayer = tab.name; + this.videoUrl = this.streamInfo[this.player[tab.name][0]] + console.log(this.videoUrl) + }, openDialog: function (tab, deviceId, channelId, param) { this.tabActiveName = tab; this.channelId = channelId; @@ -277,8 +401,8 @@ this.mediaServerId = ""; this.app = ""; this.videoUrl = "" - if (!!this.$refs.videoPlayer) { - this.$refs.videoPlayer.pause(); + if (!!this.$refs[this.activePlayer]) { + this.$refs[this.activePlayer].pause(); } switch (tab) { case "media": @@ -303,44 +427,32 @@ console.log(val) }, play: function (streamInfo, hasAudio) { + this.streamInfo = streamInfo; this.hasAudio = hasAudio; this.isLoging = false; - this.videoUrl = streamInfo.rtc; - // this.videoUrl = this.getUrlByStreamInfo(streamInfo); - this.streamId = streamInfo.streamId; + // this.videoUrl = streamInfo.rtc; + this.videoUrl = this.getUrlByStreamInfo(); + this.streamId = streamInfo.stream; this.app = streamInfo.app; this.mediaServerId = streamInfo.mediaServerId; this.playFromStreamInfo(false, streamInfo) }, - getUrlByStreamInfo(streamInfo){ - let baseZlmApi = process.env.NODE_ENV === 'development'?`${location.host}/debug/zlm`:`${location.host}/zlm` - // return `${baseZlmApi}/${streamInfo.app}/${streamInfo.streamId}.flv`; - // return `http://${baseZlmApi}/${streamInfo.app}/${streamInfo.streamId}.flv`; + getUrlByStreamInfo(){ if (location.protocol === "https:") { - if (streamInfo.wss_flv === null) { - console.error("濯掍綋鏈嶅姟鍣ㄦ湭閰嶇疆ssl绔彛, 浣跨敤http绔彛") - // this.$message({ - // showClose: true, - // message: '濯掍綋鏈嶅姟鍣ㄦ湭閰嶇疆ssl绔彛, ', - // type: 'error' - // }); - return streamInfo.ws_flv - }else { - return streamInfo.wss_flv; - } - + this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]] }else { - return streamInfo.ws_flv; + this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]] } + return this.videoUrl; }, coverPlay: function () { var that = this; this.coverPlaying = true; - this.$refs.videoPlayer.pause() + this.$refs[this.activePlayer].pause() that.$axios({ method: 'post', - url: '/api/play/convert/' + that.streamId + url: '/api/gb_record/convert/' + that.streamId }).then(function (res) { if (res.data.code == 0) { that.convertKey = res.data.key; @@ -369,7 +481,7 @@ }, convertStopClick: function() { this.convertStop(()=>{ - this.$refs.videoPlayer.play(this.videoUrl) + this.$refs[this.activePlayer].play(this.videoUrl) }); }, convertStop: function(callback) { @@ -394,12 +506,12 @@ playFromStreamInfo: function (realHasAudio, streamInfo) { this.showVideoDialog = true; this.hasaudio = realHasAudio && this.hasaudio; - this.$refs.videoPlayer.play(this.getUrlByStreamInfo(streamInfo)) + this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo)) }, close: function () { console.log('鍏抽棴瑙嗛'); - if (!!this.$refs.videoPlayer){ - this.$refs.videoPlayer.pause(); + if (!!this.$refs[this.activePlayer]){ + this.$refs[this.activePlayer].pause(); } this.videoUrl = ''; this.coverPlaying = false; @@ -450,9 +562,19 @@ method: 'get', url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime }).then(function (res) { - // 澶勭悊鏃堕棿淇℃伅 - that.videoHistory.searchHistoryResult = res.data.recordList; - that.recordsLoading = false; + console.log(res) + if(res.data.code === 0) { + // 澶勭悊鏃堕棿淇℃伅 + that.videoHistory.searchHistoryResult = res.data.data.recordList; + that.recordsLoading = false; + }else { + this.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } + }).catch(function (e) { console.log(e.message); // that.videoHistory.searchHistoryResult = falsificationData.recordData; @@ -474,8 +596,8 @@ console.log(this.seekTime) if (that.streamId != "") { that.stopPlayRecord(function () { - that.streamId = "", - that.playRecord(row); + that.streamId = ""; + that.playRecord(row); }) } else { this.$axios({ @@ -483,21 +605,22 @@ url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + row.endTime }).then(function (res) { - var streamInfo = res.data; - that.app = streamInfo.app; - that.streamId = streamInfo.streamId; - that.mediaServerId = streamInfo.mediaServerId; - that.videoUrl = that.getUrlByStreamInfo(streamInfo); + that.streamInfo = res.data; + that.app = that.streamInfo.app; + that.streamId = that.streamInfo.stream; + that.mediaServerId = that.streamInfo.mediaServerId; + that.ssrc = that.streamInfo.ssrc; + that.videoUrl = that.getUrlByStreamInfo(); that.recordPlay = true; }); } }, stopPlayRecord: function (callback) { - this.$refs.videoPlayer.pause(); + this.$refs[this.activePlayer].pause(); this.videoUrl = ''; this.$axios({ method: 'get', - url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId }).then(function (res) { if (callback) callback() }); @@ -505,33 +628,47 @@ downloadRecord: function (row) { let that = this; if (that.streamId != "") { - that.stopDownloadRecord(function () { - that.streamId = "", - that.downloadRecord(row); + that.stopDownloadRecord(function (res) { + if (res.code == 0) { + that.streamId = ""; + that.downloadRecord(row); + }else { + this.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } + }) } else { this.$axios({ method: 'get', - url: '/api/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + + url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + row.endTime + '&downloadSpeed=4' }).then(function (res) { - var streamInfo = res.data; - that.app = streamInfo.app; - that.streamId = streamInfo.streamId; - that.mediaServerId = streamInfo.mediaServerId; - that.videoUrl = that.getUrlByStreamInfo(streamInfo); - that.recordPlay = true; + if (res.data.code == 0) { + let streamInfo = res.data.data; + that.recordPlay = false; + that.$refs.recordDownload.openDialog(that.deviceId, that.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId); + }else { + that.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } }); } }, stopDownloadRecord: function (callback) { - this.$refs.videoPlayer.pause(); + this.$refs[this.activePlayer].pause(); this.videoUrl = ''; this.$axios({ method: 'get', - url: '/api/download/stop/' + this.deviceId + "/" + this.channelId - }).then(function (res) { - if (callback) callback() + url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId + }).then((res)=> { + if (callback) callback(res) }); }, ptzCamera: function (command) { @@ -539,8 +676,6 @@ let that = this; this.$axios({ method: 'post', - // url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown + - // '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50' url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed }).then(function (res) {}); }, @@ -620,13 +755,21 @@ console.log(resultArray) return resultArray; }, + copyUrl: function (dropdownItem){ + console.log(dropdownItem) + this.$copyText(dropdownItem).then((e)=> { + this.$message.success("鎴愬姛鎷疯礉鍒扮矘璐存澘"); + }, (e)=> { + + }) + }, gbPlay(){ console.log('鍓嶇鎺у埗锛氭挱鏀�'); this.$axios({ method: 'get', url: '/api/playback/resume/' + this.streamId }).then((res)=> { - this.$refs.videoPlayer.play(this.videoUrl) + this.$refs[this.activePlayer].play(this.videoUrl) }); }, gbPause(){ @@ -655,8 +798,13 @@ this.$axios({ method: 'get', url: `/api/playback/seek/${this.streamId }/` + Math.floor(this.seekTime * val / 100000) - }).then(function (res) {}); - } + }).then( (res)=> { + setTimeout(()=>{ + this.$refs[this.activePlayer].play(this.videoUrl) + }, 600) + }); + }, + } }; diff --git a/web_src/src/components/dialog/rtcPlayer.vue b/web_src/src/components/dialog/rtcPlayer.vue index 75c18f3..4737849 100644 --- a/web_src/src/components/dialog/rtcPlayer.vue +++ b/web_src/src/components/dialog/rtcPlayer.vue @@ -7,11 +7,11 @@ </template> <script> +let webrtcPlayer = null; export default { name: 'rtcPlayer', data() { return { - webrtcPlayer: null, timer: null }; }, @@ -35,7 +35,7 @@ }, methods: { play: function (url) { - this.webrtcPlayer = new ZLMRTCClient.Endpoint({ + webrtcPlayer = new ZLMRTCClient.Endpoint({ element: document.getElementById('webRtcPlayerBox'),// video 鏍囩 debug: true,// 鏄惁鎵撳嵃鏃ュ織 zlmsdpUrl: url,//娴佸湴鍧� @@ -45,17 +45,17 @@ videoEnable: false, recvOnly: true, }) - this.webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE 鍗忓晢鍑洪敊 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE 鍗忓晢鍑洪敊 console.error('ICE 鍗忓晢鍑洪敊') this.eventcallbacK("ICE ERROR", "ICE 鍗忓晢鍑洪敊") }); - this.webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,(e)=>{//鑾峰彇鍒颁簡杩滅娴侊紝鍙互鎾斁 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,(e)=>{//鑾峰彇鍒颁簡杩滅娴侊紝鍙互鎾斁 console.error('鎾斁鎴愬姛',e.streams) this.eventcallbacK("playing", "鎾斁鎴愬姛") }); - this.webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,(e)=>{// offer anwser 浜ゆ崲澶辫触 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,(e)=>{// offer anwser 浜ゆ崲澶辫触 console.error('offer anwser 浜ゆ崲澶辫触',e) this.eventcallbacK("OFFER ANSWER ERROR ", "offer anwser 浜ゆ崲澶辫触") if (e.code ==-400 && e.msg=="娴佷笉瀛樺湪"){ @@ -68,7 +68,7 @@ } }); - this.webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,(s)=>{// 鑾峰彇鍒颁簡鏈湴娴� + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,(s)=>{// 鑾峰彇鍒颁簡鏈湴娴� // document.getElementById('selfVideo').srcObject=s; this.eventcallbacK("LOCAL STREAM", "鑾峰彇鍒颁簡鏈湴娴�") @@ -76,9 +76,9 @@ }, pause: function () { - if (this.webrtcPlayer != null) { - this.webrtcPlayer.close(); - this.webrtcPlayer = null; + if (webrtcPlayer != null) { + webrtcPlayer.close(); + webrtcPlayer = null; } }, diff --git a/web_src/src/components/devicePosition.vue b/web_src/src/components/map.vue similarity index 89% rename from web_src/src/components/devicePosition.vue rename to web_src/src/components/map.vue index db19677..e9e8628 100644 --- a/web_src/src/components/devicePosition.vue +++ b/web_src/src/components/map.vue @@ -49,7 +49,7 @@ import queryTrace from './dialog/queryTrace.vue' export default { - name: "devicePosition", + name: "map", components: { MapComponent, DeviceTree, @@ -183,12 +183,27 @@ this.clean() this.closeInfoBox() let params = []; + let longitudeStr; + let latitudeStr; + if (window.mapParam.coordinateSystem == "GCJ-02") { + longitudeStr = "longitudeGcj02"; + latitudeStr = "latitudeGcj02"; + }else if (window.mapParam.coordinateSystem == "WGS84") { + longitudeStr = "longitudeWgs84"; + latitudeStr = "latitudeWgs84"; + }else { + longitudeStr = "longitude"; + latitudeStr = "latitude"; + } + for (let i = 0; i < channels.length; i++) { - if (channels[i].longitude * channels[i].latitude === 0) { + let longitude = channels[i][longitudeStr]; + let latitude = channels[i][latitudeStr]; + if (longitude * latitude === 0) { continue; } let item = { - position: [channels[i].longitude, channels[i].latitude], + position: [longitude, latitude], image: { src: this.getImageByChannel(channels[i]), anchor: [0.5, 1] @@ -202,7 +217,7 @@ this.layer = this.$refs.map.addLayer(params, this.featureClickEvent) console.log(4) if (params.length === 1) { - this.$refs.map.panTo([channels[0].longitude, channels[0].latitude], mapParam.maxZoom) + this.$refs.map.panTo([channels[0][longitudeStr], channels[0][latitudeStr]], mapParam.maxZoom) } else if (params.length > 1) { this.$refs.map.fit(this.layer) } else { @@ -251,7 +266,20 @@ this.channel = channels[0] } this.$nextTick(() => { - this.infoBoxId = this.$refs.map.openInfoBox([this.channel.longitude, this.channel.latitude], this.$refs.infobox, [0, -50]) + let longitudeStr; + let latitudeStr; + if (window.mapParam.coordinateSystem == "GCJ-02") { + longitudeStr = "longitudeGcj02"; + latitudeStr = "latitudeGcj02"; + }else if (window.mapParam.coordinateSystem == "WGS84") { + longitudeStr = "longitudeWgs84"; + latitudeStr = "latitudeWgs84"; + }else { + longitudeStr = "longitude"; + latitudeStr = "latitude"; + } + let position = [this.channel[longitudeStr], this.channel[latitudeStr]]; + this.infoBoxId = this.$refs.map.openInfoBox(position, this.$refs.infobox, [0, -50]) }) }, closeInfoBox: function () { diff --git a/web_src/src/components/service/DeviceService.js b/web_src/src/components/service/DeviceService.js index dbe10d1..fb66374 100644 --- a/web_src/src/components/service/DeviceService.js +++ b/web_src/src/components/service/DeviceService.js @@ -21,47 +21,60 @@ if (typeof (errorCallback) == "function") errorCallback(error) }); } - getAllDeviceList(callback, errorCallback) { + + getDevice(deviceId, callback, errorCallback){ + this.$axios({ + method: 'get', + url:`/api/device/query/devices/${deviceId}`, + }).then((res) => { + if (typeof (callback) == "function") callback(res.data) + }).catch((error) => { + console.log(error); + if (typeof (errorCallback) == "function") errorCallback(error) + }); + } + + getAllDeviceList(callback,endCallback, errorCallback) { let currentPage = 1; let count = 100; let deviceList = [] - this.getAllDeviceListIteration(deviceList, currentPage, count, (data) => { - if (typeof (callback) == "function") callback(data) - }, errorCallback) + this.getAllDeviceListIteration(deviceList, currentPage, count, callback, endCallback, errorCallback) } - getAllDeviceListIteration(deviceList, currentPage, count, callback, errorCallback) { + getAllDeviceListIteration(deviceList, currentPage, count, callback, endCallback, errorCallback) { this.getDeviceList(currentPage, count, (data) => { if (data.list) { + if (typeof (callback) == "function") callback(data.list) deviceList = deviceList.concat(data.list); if (deviceList.length < data.total) { currentPage ++ - this.getAllDeviceListIteration(deviceList, currentPage, count, callback, errorCallback) + this.getAllDeviceListIteration(deviceList, currentPage, count, callback, endCallback, errorCallback) }else { - if (typeof (callback) == "function") callback(deviceList) + if (typeof (endCallback) == "function") endCallback(deviceList) } } }, errorCallback) } - getAllChannel(isCatalog, catalogUnderDevice, deviceId, callback, errorCallback) { + getAllChannel(isCatalog, catalogUnderDevice, deviceId, callback, endCallback, errorCallback) { let currentPage = 1; let count = 100; let catalogList = [] - this.getAllChannelIteration(isCatalog, catalogUnderDevice, deviceId, catalogList, currentPage, count, callback, errorCallback) + this.getAllChannelIteration(isCatalog, catalogUnderDevice, deviceId, catalogList, currentPage, count, callback, endCallback, errorCallback) } - getAllChannelIteration(isCatalog, catalogUnderDevice, deviceId, catalogList, currentPage, count, callback, errorCallback) { + getAllChannelIteration(isCatalog, catalogUnderDevice, deviceId, catalogList, currentPage, count, callback, endCallback, errorCallback) { this.getChanel(isCatalog, catalogUnderDevice, deviceId, currentPage, count, (data) => { if (data.list) { + if (typeof (callback) == "function") callback(data.list) catalogList = catalogList.concat(data.list); if (catalogList.length < data.total) { currentPage ++ this.getAllChannelIteration(isCatalog,catalogUnderDevice, deviceId, catalogList, currentPage, count, callback, errorCallback) }else { console.log(1) - if (typeof (callback) == "function") callback(catalogList) + if (typeof (endCallback) == "function") endCallback(catalogList) } } }, errorCallback) @@ -84,22 +97,23 @@ } - getAllSubChannel(isCatalog, deviceId, channelId, callback, errorCallback) { + getAllSubChannel(isCatalog, deviceId, channelId, callback, endCallback, errorCallback) { let currentPage = 1; let count = 100; let catalogList = [] - this.getAllSubChannelIteration(isCatalog, deviceId, channelId, catalogList, currentPage, count, callback, errorCallback) + this.getAllSubChannelIteration(isCatalog, deviceId, channelId, catalogList, currentPage, count, callback, endCallback, errorCallback) } - getAllSubChannelIteration(isCatalog, deviceId,channelId, catalogList, currentPage, count, callback, errorCallback) { + getAllSubChannelIteration(isCatalog, deviceId,channelId, catalogList, currentPage, count, callback, endCallback, errorCallback) { this.getSubChannel(isCatalog, deviceId, channelId, currentPage, count, (data) => { if (data.list) { + if (typeof (callback) == "function") callback(data.list) catalogList = catalogList.concat(data.list); if (catalogList.length < data.total) { currentPage ++ - this.getAllSubChannelIteration(isCatalog, deviceId, channelId, catalogList, currentPage, count, callback, errorCallback) + this.getAllSubChannelIteration(isCatalog, deviceId, channelId, catalogList, currentPage, count, callback, endCallback, errorCallback) }else { - if (typeof (callback) == "function") callback(catalogList) + if (typeof (endCallback) == "function") endCallback(catalogList) } } }, errorCallback) diff --git a/web_src/src/layout/UiHeader.vue b/web_src/src/layout/UiHeader.vue index a0a252c..0550593 100644 --- a/web_src/src/layout/UiHeader.vue +++ b/web_src/src/layout/UiHeader.vue @@ -1,9 +1,11 @@ <template> <div id="UiHeader"> - <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff" - active-text-color="#ffd04b" mode="horizontal"> + + <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#001529" text-color="#fff" + active-text-color="#1890ff" mode="horizontal"> + <el-menu-item index="/control">鎺у埗鍙�</el-menu-item> - <el-menu-item index="/live">瀹炴椂鐩戞帶</el-menu-item> + <el-menu-item index="/live">鍒嗗睆鐩戞帶</el-menu-item> <el-menu-item index="/deviceList">鍥芥爣璁惧</el-menu-item> <el-menu-item index="/map">鐢靛瓙鍦板浘</el-menu-item> <el-menu-item index="/pushVideoList">鎺ㄦ祦鍒楄〃</el-menu-item> @@ -148,4 +150,8 @@ #UiHeader .el-switch__label.is-active{ color: #409EFF; } +#UiHeader .el-menu-item.is-active { + color: #fff!important; + background-color: #1890ff!important; +} </style> diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js index 8844862..2f44fd8 100644 --- a/web_src/src/router/index.js +++ b/web_src/src/router/index.js @@ -7,7 +7,7 @@ import channelList from '../components/channelList.vue' import pushVideoList from '../components/PushVideoList.vue' import streamProxyList from '../components/StreamProxyList.vue' -import devicePosition from '../components/devicePosition.vue' +import map from '../components/map.vue' import login from '../components/Login.vue' import parentPlatformList from '../components/ParentPlatformList.vue' import cloudRecord from '../components/CloudRecord.vue' @@ -69,9 +69,9 @@ component: parentPlatformList, }, { - path: '/devicePosition/:deviceId/:parentChannelId/:count/:page', - name: 'devicePosition', - component: devicePosition, + path: '/map/:deviceId/:parentChannelId/:count/:page', + name: 'map', + component: map, }, { path: '/cloudRecord', @@ -100,8 +100,8 @@ }, { path: '/map', - name: 'devicePosition', - component: devicePosition, + name: 'map', + component: map, }, ] }, -- Gitblit v1.8.0