diff --git a/.gitignore b/.gitignore index 51ebf9e9..21f40064 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # Log file *.log - +logs/* # BlueJ files *.ctxt diff --git a/README.md b/README.md index cc295d5a..93b3ffba 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,10 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 # docker快速体验 +目前作者的docker-compose因为时间有限维护不及时,这里提供第三方提供的供大家使用,维护不易,大家记得给这位小伙伴点个star。 +https://github.com/SaltFish001/wvp_pro_compose +[https://github.com/SaltFish001/wvp_pro_compose](https://github.com/SaltFish001/wvp_pro_compose) +这是作者维护的一个镜像,可能存在不及时的问题。 ```shell docker pull 648540858/wvp_pro diff --git a/pom.xml b/pom.xml index f1ac4581..9d31f729 100644 --- a/pom.xml +++ b/pom.xml @@ -90,8 +90,8 @@ com.alibaba - druid - 1.2.3 + druid-spring-boot-starter + 1.1.22 @@ -183,6 +183,15 @@ 4.9.0 + + + com.squareup.okhttp3 + logging-interceptor + 4.9.0 + + + + com.burgstaller diff --git a/sql/mysql.sql b/sql/mysql.sql index 3734db27..e71adf30 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -44,7 +44,7 @@ CREATE TABLE `device` ( `charset` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `device_deviceId_uindex` (`deviceId`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -95,39 +95,41 @@ DROP TABLE IF EXISTS `device_channel`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `device_channel` ( - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `id` int NOT NULL AUTO_INCREMENT, + `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, + `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL, + `manufacture` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `model` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `owner` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `block` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `address` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `parentId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, `safetyWay` int DEFAULT NULL, `registerWay` int DEFAULT NULL, - `certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `certNum` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, `certifiable` int DEFAULT NULL, `errCode` int DEFAULT NULL, - `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `endTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `secrecy` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `ipAddress` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, `port` int DEFAULT NULL, - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL, `PTZType` int DEFAULT NULL, `status` int DEFAULT NULL, `longitude` double DEFAULT NULL, `latitude` double DEFAULT NULL, - `streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `streamId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, + `parental` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, `hasAudio` bit(1) DEFAULT NULL, - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, + `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, `subCount` int DEFAULT '0', - PRIMARY KEY (`channelId`,`deviceId`) USING BTREE, + PRIMARY KEY (`id`), + UNIQUE KEY `device_channel_id_uindex` (`id`), UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -196,7 +198,7 @@ CREATE TABLE `gb_stream` ( PRIMARY KEY (`gbStreamId`) USING BTREE, UNIQUE KEY `app` (`app`,`stream`) USING BTREE, UNIQUE KEY `gbId` (`gbId`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=291 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=375 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -226,7 +228,7 @@ CREATE TABLE `log` ( `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=245 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=313 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -315,7 +317,7 @@ CREATE TABLE `parent_platform` ( PRIMARY KEY (`id`), UNIQUE KEY `parent_platform_id_uindex` (`id`), UNIQUE KEY `parent_platform_pk` (`serverGBId`) -) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -361,13 +363,11 @@ DROP TABLE IF EXISTS `platform_gb_channel`; /*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `platform_gb_channel` ( `id` int NOT NULL AUTO_INCREMENT, - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `deviceAndChannelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `platformId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, + `catalogId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, + `deviceChannelId` int NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -393,7 +393,7 @@ CREATE TABLE `platform_gb_stream` ( `id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`), UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) -) ENGINE=InnoDB AUTO_INCREMENT=256 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=406 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -415,6 +415,7 @@ DROP TABLE IF EXISTS `stream_proxy`; CREATE TABLE `stream_proxy` ( `id` int NOT NULL AUTO_INCREMENT, `type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, + `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL, `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL, `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL, `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL, @@ -464,7 +465,7 @@ CREATE TABLE `stream_push` ( `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `stream_push_pk` (`app`,`stream`) -) ENGINE=InnoDB AUTO_INCREMENT=310 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=394 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -541,4 +542,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2022-02-24 16:52:12 +-- Dump completed on 2022-02-25 20:32:21 diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java index bfe58419..9dacbade 100644 --- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java +++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp; import java.util.logging.LogManager; +import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @@ -17,6 +18,7 @@ import springfox.documentation.oas.annotations.EnableOpenApi; @SpringBootApplication @EnableScheduling @EnableOpenApi +@EnableDruidSupport public class VManageBootstrap extends LogManager { private static String[] args; private static ConfigurableApplicationContext context; diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java index e16c1add..06263840 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; public class StreamInfo { private String app; - private String streamId; + private String stream; private String deviceID; private String channelId; private String flv; @@ -153,12 +153,12 @@ public class StreamInfo { this.ws_ts = ws_ts; } - public String getStreamId() { - return streamId; + public String getStream() { + return stream; } - public void setStreamId(String streamId) { - this.streamId = streamId; + public void setStream(String stream) { + this.stream = stream; } public String getRtc() { 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 923e411e..0d638435 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -29,6 +29,7 @@ public class VideoManagerConstants { // 此处多了一个_,暂不修改 public static final String PLAYER_PREFIX = "VMP_PLAYER_"; public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_"; + public static final String PLAY_INFO_PREFIX = "VMP_PLAY_INFO_"; public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_"; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java index 41b68cc0..b69bf68e 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.conf; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @@ -30,7 +31,7 @@ public class SipPlatformRunner implements CommandLineRunner { private EventPublisher publisher; @Autowired - private ZLMRTPServerFactory zlmrtpServerFactory; + private ISIPCommanderForPlatform sipCommanderForPlatform; @Override @@ -57,6 +58,9 @@ public class SipPlatformRunner implements CommandLineRunner { parentPlatformCatch.setId(parentPlatform.getServerGBId()); redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); + // 取消订阅 + sipCommanderForPlatform.unregister(parentPlatform, null, null); + Thread.sleep(500); // 发送平台未注册消息 publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId()); } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java b/src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java index 2f0faba7..7ee13f84 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java @@ -14,7 +14,7 @@ import springfox.documentation.spring.web.plugins.Docket; @Configuration public class Swagger3Config { - @Value("${swagger-ui.enabled}") + @Value("${swagger-ui.enabled: true}") private boolean enable; @Bean diff --git a/src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java b/src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java new file mode 100644 index 00000000..12f6e636 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java @@ -0,0 +1,64 @@ +package com.genersoft.iot.vmp.conf.druid; + +import com.alibaba.druid.support.http.StatViewServlet; +import com.alibaba.druid.support.http.WebStatFilter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; + +import javax.servlet.Filter; +import javax.servlet.Servlet; + +/** + * druid监控配置 + * @author + */ +public class DruidConfiguration { + + @Value("${rj-druid-manage.allow:127.0.0.1}") + private String allow; + + @Value("${rj-druid-manage.deny:}") + private String deny; + + @Value("${rj-druid-manage.loginUsername:admin}") + private String loginUsername; + + @Value("${rj-druid-manage.loginPassword:admin}") + private String loginPassword; + + @Value("${rj-druid-manage.resetEnable:false}") + private String resetEnable; + + /** + * druid监控页面开启 + */ + @Bean + public ServletRegistrationBean druidServlet() { + ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); + // IP白名单 + servletRegistrationBean.addInitParameter("allow", allow); + // IP黑名单(共同存在时,deny优先于allow) + servletRegistrationBean.addInitParameter("deny", deny); + //控制台管理用户 + servletRegistrationBean.addInitParameter("loginUsername", loginUsername); + servletRegistrationBean.addInitParameter("loginPassword", loginPassword); + //是否能够重置数据 禁用HTML页面上的“Reset All”功能 + servletRegistrationBean.addInitParameter("resetEnable", resetEnable); + return servletRegistrationBean; + } + + /** + * druid url监控配置 + */ + @Bean + public FilterRegistrationBean filterRegistrationBean() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(new WebStatFilter()); + filterRegistrationBean.addUrlPatterns("/*"); + filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); + return filterRegistrationBean; + } + + +} \ No newline at end of file diff --git a/src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java b/src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java new file mode 100644 index 00000000..5fd710be --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java @@ -0,0 +1,24 @@ +package com.genersoft.iot.vmp.conf.druid; + +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +/** + * druid监控支持注解 + * + * @author + * {@link DruidConfiguration} druid监控页面安全配置支持 + * {@link ServletComponentScan} druid监控页面需要扫描servlet + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Import({ + DruidConfiguration.class, +}) +@ServletComponentScan +public @interface EnableDruidSupport { +} 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 6d40e360..36337895 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 @@ -3,6 +3,10 @@ package com.genersoft.iot.vmp.gb28181.bean; public class DeviceChannel { + /** + * 数据库自赠ID + */ + private int id; /** * 通道id @@ -165,6 +169,14 @@ public class DeviceChannel { */ private boolean hasAudio; + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + public String getDeviceId() { return deviceId; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java index 9700f8a5..c2dedec1 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java @@ -4,11 +4,12 @@ public class SsrcTransaction { private String deviceId; private String channelId; - private String ssrc; - private String streamId; + private String callId; + private String stream; private byte[] transaction; private byte[] dialog; private String mediaServerId; + private String ssrc; public String getDeviceId() { return deviceId; @@ -26,20 +27,20 @@ public class SsrcTransaction { this.channelId = channelId; } - public String getSsrc() { - return ssrc; + public String getCallId() { + return callId; } - public void setSsrc(String ssrc) { - this.ssrc = ssrc; + public void setCallId(String callId) { + this.callId = callId; } - public String getStreamId() { - return streamId; + public String getStream() { + return stream; } - public void setStreamId(String streamId) { - this.streamId = streamId; + public void setStream(String stream) { + this.stream = stream; } public byte[] getTransaction() { @@ -65,4 +66,12 @@ public class SsrcTransaction { public void setMediaServerId(String mediaServerId) { this.mediaServerId = mediaServerId; } + + public String getSsrc() { + return ssrc; + } + + public void setSsrc(String ssrc) { + this.ssrc = ssrc; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java index 60418f2c..e9d41678 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java @@ -18,15 +18,21 @@ public class SubscribeInfo { this.fromTag = fromHeader.getTag(); ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME); this.expires = expiresHeader.getExpires(); - this.event = ((EventHeader)request.getHeader(EventHeader.NAME)).getName(); + EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME); + this.eventId = eventHeader.getEventId(); + this.eventType = eventHeader.getEventType(); + ViaHeader viaHeader = (ViaHeader)request.getHeader(ViaHeader.NAME); + this.branch = viaHeader.getBranch(); } private String id; private int expires; private String callId; - private String event; + private String eventId; + private String eventType; private String fromTag; private String toTag; + private String branch; public String getId() { return id; @@ -68,11 +74,27 @@ public class SubscribeInfo { this.fromTag = fromTag; } - public String getEvent() { - return event; + public String getEventId() { + return eventId; } - public void setEvent(String event) { - this.event = event; + public void setEventId(String eventId) { + this.eventId = eventId; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public String getBranch() { + return branch; + } + + public void setBranch(String branch) { + this.branch = branch; } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java index 8c8565be..746467d6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java @@ -101,14 +101,14 @@ public class EventPublisher { applicationEventPublisher.publishEvent(outEvent); } - @Async + public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) { List deviceChannelList = new ArrayList<>(); deviceChannelList.add(deviceChannel); catalogEventPublish(platformId, deviceChannelList, type); } - @Async + public void catalogEventPublish(String platformId, List deviceChannels, String type) { CatalogEvent outEvent = new CatalogEvent(this); List channels = new ArrayList<>(); @@ -130,8 +130,8 @@ public class EventPublisher { applicationEventPublisher.publishEvent(outEvent); } - @Async - public void catalogEventPublishForStream(String platformId, GbStream[] gbStreams, String type) { + + public void catalogEventPublishForStream(String platformId, List gbStreams, String type) { CatalogEvent outEvent = new CatalogEvent(this); outEvent.setGbStreams(gbStreams); outEvent.setType(type); @@ -139,9 +139,10 @@ public class EventPublisher { applicationEventPublisher.publishEvent(outEvent); } - @Async + public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) { - GbStream[] gbStreams = {gbStream}; - catalogEventPublishForStream(platformId, gbStreams, type); + List gbStreamList = new ArrayList<>(); + gbStreamList.add(gbStream); + catalogEventPublishForStream(platformId, gbStreamList, type); } } 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 a00ac630..49c52d5e 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 @@ -23,24 +23,36 @@ public class SipSubscribe { private Map okSubscribes = new ConcurrentHashMap<>(); - private Map timeSubscribes = new ConcurrentHashMap<>(); + private Map okTimeSubscribes = new ConcurrentHashMap<>(); + private Map errorTimeSubscribes = new ConcurrentHashMap<>(); -// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次 + // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次 // @Scheduled(fixedRate= 100 * 60 * 60 ) - @Scheduled(cron="0 0 * * * ?") //每小时执行一次, 每个整点 + @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 public void execute(){ logger.info("[定时任务] 清理过期的订阅信息"); Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); - calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) - 1); - for (String key : timeSubscribes.keySet()) { - if (timeSubscribes.get(key).before(calendar.getTime())){ - logger.info("[定时任务] 清理过期的订阅信息: {}", key); - errorSubscribes.remove(key); + calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 5); + + for (String key : okTimeSubscribes.keySet()) { + if (okTimeSubscribes.get(key).before(calendar.getTime())){ +// logger.info("[定时任务] 清理过期的订阅信息: {}", key); okSubscribes.remove(key); - timeSubscribes.remove(key); + okTimeSubscribes.remove(key); } } + for (String key : errorTimeSubscribes.keySet()) { + if (errorTimeSubscribes.get(key).before(calendar.getTime())){ +// logger.info("[定时任务] 清理过期的订阅信息: {}", key); + errorSubscribes.remove(key); + errorTimeSubscribes.remove(key); + } + } + logger.info("okTimeSubscribes.size:{}",okTimeSubscribes.size()); + logger.info("okSubscribes.size:{}",okSubscribes.size()); + logger.info("errorTimeSubscribes.size:{}",errorTimeSubscribes.size()); + logger.info("errorSubscribes.size:{}",errorSubscribes.size()); } public interface Event { @@ -105,12 +117,12 @@ public class SipSubscribe { public void addErrorSubscribe(String key, SipSubscribe.Event event) { errorSubscribes.put(key, event); - timeSubscribes.put(key, new Date()); + errorTimeSubscribes.put(key, new Date()); } public void addOkSubscribe(String key, SipSubscribe.Event event) { okSubscribes.put(key, event); - timeSubscribes.put(key, new Date()); + okTimeSubscribes.put(key, new Date()); } public SipSubscribe.Event getErrorSubscribe(String key) { @@ -119,7 +131,7 @@ public class SipSubscribe { public void removeErrorSubscribe(String key) { errorSubscribes.remove(key); - timeSubscribes.remove(key); + errorTimeSubscribes.remove(key); } public SipSubscribe.Event getOkSubscribe(String key) { @@ -128,7 +140,7 @@ public class SipSubscribe { public void removeOkSubscribe(String key) { okSubscribes.remove(key); - timeSubscribes.remove(key); + okTimeSubscribes.remove(key); } public int getErrorSubscribesSize(){ return errorSubscribes.size(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java index e343fec7..c035b808 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java @@ -20,7 +20,7 @@ public class CatalogEvent extends ApplicationEvent { public static final String UPDATE = "UPDATE"; // 更新 private List deviceChannels; - private GbStream[] gbStreams; + private List gbStreams; private String type; private String platformId; @@ -48,11 +48,11 @@ public class CatalogEvent extends ApplicationEvent { this.platformId = platformId; } - public GbStream[] getGbStreams() { + public List getGbStreams() { return gbStreams; } - public void setGbStreams(GbStream[] gbStreams) { + public void setGbStreams(List gbStreams) { this.gbStreams = gbStreams; } } 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 997031b6..f9593633 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 @@ -60,10 +60,14 @@ public class CatalogEventLister implements ApplicationListener { Map> parentPlatformMap = new HashMap<>(); if (event.getPlatformId() != null) { parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); - if (!parentPlatform.isStatus())return; + if (parentPlatform != null && !parentPlatform.isStatus())return; String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId(); subscribe = redisCatchStorage.getSubscribe(key); - if (subscribe == null) return; + + if (subscribe == null) { + logger.debug("发送订阅消息时发现订阅信息已经不存在"); + return; + } }else { // 获取所用订阅 List platforms = redisCatchStorage.getAllSubscribePlatform(); @@ -94,7 +98,7 @@ public class CatalogEventLister implements ApplicationListener { if (event.getDeviceChannels() != null) { deviceChannelList.addAll(event.getDeviceChannels()); } - if (event.getGbStreams() != null && event.getGbStreams().length > 0){ + if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ for (GbStream gbStream : event.getGbStreams()) { DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId()); deviceChannelList.add(deviceChannelByStream); @@ -102,7 +106,7 @@ public class CatalogEventLister implements ApplicationListener { } if (deviceChannelList.size() > 0) { logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe); + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null); } }else if (parentPlatformMap.keySet().size() > 0) { for (String gbId : parentPlatformMap.keySet()) { @@ -117,7 +121,7 @@ public class CatalogEventLister implements ApplicationListener { DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setChannelId(gbId); deviceChannelList.add(deviceChannel); - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo); + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null); } } } @@ -134,7 +138,7 @@ public class CatalogEventLister implements ApplicationListener { if (event.getDeviceChannels() != null) { deviceChannelList.addAll(event.getDeviceChannels()); } - if (event.getGbStreams() != null && event.getGbStreams().length > 0){ + if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ for (GbStream gbStream : event.getGbStreams()) { DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId()); deviceChannelList.add(deviceChannelByStream); @@ -142,7 +146,7 @@ public class CatalogEventLister implements ApplicationListener { } if (deviceChannelList.size() > 0) { logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); - sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe); + sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null); } }else if (parentPlatformMap.keySet().size() > 0) { for (String gbId : parentPlatformMap.keySet()) { @@ -159,7 +163,7 @@ public class CatalogEventLister implements ApplicationListener { GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId); DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform.getDeviceGBId()); deviceChannelList.add(deviceChannelByStream); - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo); + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null); } } } 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 d41b04da..3e9f28aa 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 @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; import gov.nist.javax.sip.stack.SIPDialog; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; /** * @description:视频流session管理器,管理视频预览、预览回放的通信句柄 @@ -29,39 +30,55 @@ public class VideoStreamSessionManager { @Autowired private UserSetup userSetup; - public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){ + /** + * 添加一个点播/回放的事务信息 + * 后续可以通过流Id/callID + * @param deviceId 设备ID + * @param channelId 通道ID + * @param callId 一次请求的CallID + * @param stream 流名称 + * @param mediaServerId 所使用的流媒体ID + * @param transaction 事务 + */ + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){ SsrcTransaction ssrcTransaction = new SsrcTransaction(); ssrcTransaction.setDeviceId(deviceId); ssrcTransaction.setChannelId(channelId); - ssrcTransaction.setStreamId(streamId); + ssrcTransaction.setStream(stream); byte[] transactionByteArray = SerializeUtils.serialize(transaction); ssrcTransaction.setTransaction(transactionByteArray); + ssrcTransaction.setCallId(callId); ssrcTransaction.setSsrc(ssrc); ssrcTransaction.setMediaServerId(mediaServerId); - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction); + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); } - public void put(String deviceId, String channelId , Dialog dialog){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); + public void put(String deviceId, String channelId, String callId, Dialog dialog){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null); if (ssrcTransaction != null) { byte[] dialogByteArray = SerializeUtils.serialize(dialog); ssrcTransaction.setDialog(dialogByteArray); } - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction); + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + + "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + + ssrcTransaction.getStream(), ssrcTransaction); } - public ClientTransaction getTransaction(String deviceId, String channelId){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); + public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); if (ssrcTransaction == null) return null; byte[] transactionByteArray = ssrcTransaction.getTransaction(); ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray); return clientTransaction; } - public SIPDialog getDialog(String deviceId, String channelId){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); + public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); if (ssrcTransaction == null) return null; byte[] dialogByteArray = ssrcTransaction.getDialog(); if (dialogByteArray == null) return null; @@ -69,36 +86,37 @@ public class VideoStreamSessionManager { return dialog; } - public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){ - SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId); - return ssrcTransaction; + public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){ + if (StringUtils.isEmpty(callId)) callId ="*"; + if (StringUtils.isEmpty(stream)) stream ="*"; + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; + List scanResult = redisUtil.scan(key); + if (scanResult.size() == 0) return null; + return (SsrcTransaction)redisUtil.get((String) scanResult.get(0)); } - public String getStreamId(String deviceId, String channelId){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); - if (ssrcTransaction == null) return null; - return ssrcTransaction.getStreamId(); - } - public String getMediaServerId(String deviceId, String channelId){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); + public String getMediaServerId(String deviceId, String channelId, String stream){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); if (ssrcTransaction == null) return null; return ssrcTransaction.getMediaServerId(); } - public String getSSRC(String deviceId, String channelId){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); + public String getSSRC(String deviceId, String channelId, String stream){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); if (ssrcTransaction == null) return null; return ssrcTransaction.getSsrc(); } - public void remove(String deviceId, String channelId) { - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); + public void remove(String deviceId, String channelId, String stream) { + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); if (ssrcTransaction == null) return; - redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId); + redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream()); } + public List getAllSsrc() { - List ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" )); + List ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" )); List 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/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java index 71025c00..4732cc1c 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 @@ -73,6 +73,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @Override @Async public void processRequest(RequestEvent requestEvent) { + logger.debug("\n收到请求:\n{}", requestEvent.getRequest()); String method = requestEvent.getRequest().getMethod(); ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); if (sipRequestProcessor == null) { @@ -90,9 +91,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @Override @Async public void processResponse(ResponseEvent responseEvent) { - logger.debug(responseEvent.getResponse().toString()); Response response = responseEvent.getResponse(); - logger.debug(responseEvent.getResponse().toString()); + logger.debug("\n收到响应:\n{}", responseEvent.getResponse()); int status = response.getStatusCode(); if (((status >= 200) && (status < 300)) || status == 401) { // Success! CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); @@ -107,8 +107,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); if (subscribe != null) { SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); - subscribe.response(eventResult); sipSubscribe.removeOkSubscribe(callIdHeader.getCallId()); + subscribe.response(eventResult); } } } 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 8be07ca1..5859d657 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 @@ -119,8 +119,8 @@ public interface ISIPCommander { /** * 视频流停止 */ - void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent); - void streamByeCmd(String deviceId, String channelId); + void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent); + void streamByeCmd(String deviceId, String channelId, String stream); /** * 回放暂停 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 7325889f..d6294fa7 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 @@ -17,7 +17,7 @@ public interface ISIPCommanderForPlatform { * @return */ boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); - boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); + boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain); /** * 向上级平台注销 @@ -78,13 +78,13 @@ public interface ISIPCommanderForPlatform { * @param parentPlatform * @param deviceChannels */ - boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo); + boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo, Integer index); /** * 回复catalog事件-删除 * @param parentPlatform * @param deviceChannels */ - boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo); + boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo, Integer index); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java index 27125e1e..c0e72817 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import gov.nist.javax.sip.message.MessageFactoryImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -127,7 +128,15 @@ public class SIPRequestHeaderPlarformProvider { Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader); - + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); + if (www == null) { + AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest"); + authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); + authorizationHeader.setURI(requestURI); + authorizationHeader.setAlgorithm("MD5"); + registerRequest.addHeader(authorizationHeader); + return registerRequest; + } String realm = www.getRealm(); String nonce = www.getNonce(); String scheme = www.getScheme(); @@ -138,7 +147,6 @@ public class SIPRequestHeaderPlarformProvider { callIdHeader.setCallId(callId); - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); String cNonce = null; String nc = "00000001"; if (qop != null) { @@ -223,30 +231,30 @@ public class SIPRequestHeaderPlarformProvider { UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); request.addHeader(userAgentHeader); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); request.setContent(content, contentTypeHeader); return request; } - public Request createNotifyRequest(ParentPlatform parentPlatform, String content, String fromTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException { + public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { Request request = null; // sipuri SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); // via ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), - parentPlatform.getTransport(), null); + parentPlatform.getTransport(), subscribeInfo.getBranch()); viaHeader.setRPort(); viaHeaders.add(viaHeader); // from SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getToTag()); // to SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag()); // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); @@ -262,7 +270,22 @@ public class SIPRequestHeaderPlarformProvider { UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); request.addHeader(userAgentHeader); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); + if (subscribeInfo.getEventId() != null) { + event.setEventId(subscribeInfo.getEventId()); + } + + request.addHeader(event); + + SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active"); + request.setHeader(active); + + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort(); + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() + .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); request.setContent(content, contentTypeHeader); return request; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index ee237c0c..f4a0ec40 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -67,7 +67,7 @@ public class SIPRequestHeaderProvider { request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); request.setContent(content, contentTypeHeader); return request; } @@ -217,7 +217,7 @@ public class SIPRequestHeaderProvider { EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); request.addHeader(eventHeader); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); request.setContent(content, contentTypeHeader); return request; } @@ -226,7 +226,7 @@ public class SIPRequestHeaderProvider { throws PeerUnavailableException, ParseException, InvalidArgumentException { Request request = null; if (streamInfo == null) return null; - Dialog dialog = streamSession.getDialog(streamInfo.getDeviceID(), streamInfo.getChannelId()); + Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream()); SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress()); 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 29f8c058..734fe23c 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 @@ -331,7 +331,7 @@ public class SIPCommander implements ISIPCommander { */ @Override public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { - String streamId = ssrcInfo.getStreamId(); + String streamId = ssrcInfo.getStream(); try { if (device == null) return; String streamMode = device.getStreamMode().toUpperCase(); @@ -404,6 +404,8 @@ public class SIPCommander implements ISIPCommander { } content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 +// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备 String tm = Long.toString(System.currentTimeMillis()); @@ -412,14 +414,14 @@ public class SIPCommander implements ISIPCommander { Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader); - String finalStreamId = streamId; transmitRequest(device, request, (e -> { - streamSession.remove(device.getDeviceId(), channelId); + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc()); errorEvent.response(e); }), e ->{ - streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction()); - streamSession.put(device.getDeviceId(), channelId , e.dialog); + // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 + streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction()); + streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog); }); @@ -441,12 +443,12 @@ public class SIPCommander implements ISIPCommander { , SipSubscribe.Event errorEvent) { try { - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); // 添加订阅 JSONObject subscribeKey = new JSONObject(); subscribeKey.put("app", "rtp"); - subscribeKey.put("stream", ssrcInfo.getStreamId()); + subscribeKey.put("stream", ssrcInfo.getStream()); subscribeKey.put("regist", true); subscribeKey.put("mediaServerId", mediaServerItem.getId()); logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); @@ -466,8 +468,6 @@ public class SIPCommander implements ISIPCommander { content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" " +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); - - String streamMode = device.getStreamMode().toUpperCase(); if (userSetup.isSeniorSdp()) { @@ -527,8 +527,8 @@ public class SIPCommander implements ISIPCommander { transmitRequest(device, request, errorEvent, okEvent -> { ResponseEvent responseEvent = (ResponseEvent) okEvent.event; - streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), responseEvent.getClientTransaction()); - streamSession.put(device.getDeviceId(), channelId, okEvent.dialog); + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction()); + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog); }); } catch ( SipException | ParseException | InvalidArgumentException e) { e.printStackTrace(); @@ -548,12 +548,12 @@ public class SIPCommander implements ISIPCommander { public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event , SipSubscribe.Event errorEvent) { try { - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); // 添加订阅 JSONObject subscribeKey = new JSONObject(); subscribeKey.put("app", "rtp"); - subscribeKey.put("stream", ssrcInfo.getStreamId()); + subscribeKey.put("stream", ssrcInfo.getStream()); subscribeKey.put("regist", true); subscribeKey.put("mediaServerId", mediaServerItem.getId()); logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); @@ -634,7 +634,8 @@ public class SIPCommander implements ISIPCommander { Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); ClientTransaction transaction = transmitRequest(device, request, errorEvent); - streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction); + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction); + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction); } catch ( SipException | ParseException | InvalidArgumentException e) { e.printStackTrace(); @@ -645,17 +646,17 @@ public class SIPCommander implements ISIPCommander { * 视频流停止, 不使用回调 */ @Override - public void streamByeCmd(String deviceId, String channelId) { - streamByeCmd(deviceId, channelId, null); + public void streamByeCmd(String deviceId, String channelId, String stream) { + streamByeCmd(deviceId, channelId, stream, null); } /** * 视频流停止 */ @Override - public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) { + public void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent) { try { - ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId); + ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream); if (transaction == null) { logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult<>(); @@ -664,7 +665,7 @@ public class SIPCommander implements ISIPCommander { } return; } - SIPDialog dialog = streamSession.getDialog(deviceId, channelId); + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, stream); if (dialog == null) { logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId); return; @@ -708,11 +709,11 @@ public class SIPCommander implements ISIPCommander { dialog.sendRequest(clientTransaction); - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId); + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callIdHeader.getCallId(), null); if (ssrcTransaction != null) { MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId()); mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc()); - streamSession.remove(deviceId, channelId); + streamSession.remove(deviceId, channelId, ssrcTransaction.getStream()); } } catch (SipException | ParseException e) { e.printStackTrace(); 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 a00da62f..5dcffe79 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 @@ -32,21 +32,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class); - // @Autowired - // private SipConfig sipConfig; - - // @Autowired - // private SIPRequestHeaderProvider headerProvider; - @Autowired private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider; - // @Autowired - // private VideoStreamSessionManager streamSession; - - // @Autowired - // private IVideoManagerStorager storager; - @Autowired private IRedisCatchStorage redisCatchStorage; @@ -65,7 +53,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @Override public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { - return register(parentPlatform, null, null, errorEvent, okEvent); + return register(parentPlatform, null, null, errorEvent, okEvent, false); } @Override @@ -77,15 +65,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); } - return register(parentPlatform, null, null, errorEvent, okEvent); + return register(parentPlatform, null, null, errorEvent, okEvent, false); } @Override - public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { + public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, + SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) { try { Request request = null; String tm = Long.toString(System.currentTimeMillis()); - if (www == null ) { + if (!registerAgain ) { // //callid CallIdHeader callIdHeader = null; if(parentPlatform.getTransport().equals("TCP")) { @@ -173,6 +162,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { } private void transmitRequest(ParentPlatform parentPlatform, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException { + logger.debug("\n发送消息:\n{}", request); if("TCP".equals(parentPlatform.getTransport())) { tcpSipProvider.sendRequest(request); @@ -223,7 +213,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { catalogXml.append("" + channel.getCivilCode() + "\r\n"); catalogXml.append("
" + channel.getAddress() + "
\r\n"); catalogXml.append("" + channel.getParental() + "\r\n"); - catalogXml.append("" + channel.getParentId() + "\r\n"); + if (channel.getParentId() != null) { + catalogXml.append("" + channel.getParentId() + "\r\n"); + } catalogXml.append("" + channel.getSecrecy() + "\r\n"); catalogXml.append("" + channel.getRegisterWay() + "\r\n"); catalogXml.append("" + (channel.getStatus() == 0?"OFF":"ON") + "\r\n"); @@ -358,7 +350,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { String tm = Long.toString(System.currentTimeMillis()); - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, deviceStatusXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader); + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, + deviceStatusXml.toString(),callIdHeader, + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); transmitRequest(parentPlatform, request); } catch (SipException | ParseException | InvalidArgumentException e) { @@ -369,65 +363,82 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { } @Override - public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo) { + public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo, Integer index) { if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { return false; } - for (DeviceChannel channel : deviceChannels) { - try { - StringBuffer catalogXml = new StringBuffer(600); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("Catalog\r\n"); - catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); - catalogXml.append("" + deviceChannels.size() + "\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("" + channel.getChannelId() + "\r\n"); - catalogXml.append("" + type + "\r\n"); - catalogXml.append("" + channel.getName() + "\r\n"); - catalogXml.append("" + channel.getManufacture() + "\r\n"); - catalogXml.append("" + channel.getModel() + "\r\n"); - catalogXml.append("" + channel.getOwner() + "\r\n"); - catalogXml.append("" + channel.getCivilCode() + "\r\n"); - catalogXml.append("
" + channel.getAddress() + "
\r\n"); - catalogXml.append("" + channel.getParental() + "\r\n"); - catalogXml.append("" + channel.getParentId() + "\r\n"); - catalogXml.append("" + channel.getSecrecy() + "\r\n"); - catalogXml.append("" + channel.getRegisterWay() + "\r\n"); - catalogXml.append("" + (channel.getStatus() == 0 ? "OFF" : "ON") + "\r\n"); - catalogXml.append("" + channel.getLongitude() + "\r\n"); - catalogXml.append("" + channel.getLatitude() + "\r\n"); - catalogXml.append("" + channel.getIpAddress() + "\r\n"); - catalogXml.append("" + channel.getPort() + "\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("" + channel.getPTZType() + "\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("
\r\n"); - catalogXml.append("
\r\n"); - catalogXml.append("
\r\n"); + if (index == null) { + index = 0; + } - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - callIdHeader.setCallId(subscribeInfo.getCallId()); - - String tm = Long.toString(System.currentTimeMillis()); - - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader); - transmitRequest(parentPlatform, request); - Thread.sleep(10); - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } catch (InterruptedException e) { - e.printStackTrace(); + try { + if (index > deviceChannels.size() - 1) { + return true; } + Request request = getCatalogNotifyRequestForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo); + index += 1; + Integer finalIndex = index; + transmitRequest(parentPlatform, request, null, (eventResult -> { + sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex); + })); + } catch (SipException | ParseException | InvalidArgumentException e) { + e.printStackTrace(); + return false; } return true; } + private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type, + SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException, + PeerUnavailableException { + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo); + + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + callIdHeader.setCallId(subscribeInfo.getCallId()); + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, + callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); + return request; + } + + private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) { + StringBuffer catalogXml = new StringBuffer(600); + if (parentPlatform.getServerGBId().equals(channel.getParentId())) { + channel.setParentId(parentPlatform.getDeviceGBId()); + } + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("Catalog\r\n"); + catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + parentPlatform.getDeviceGBId() + "\r\n"); + catalogXml.append("1\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("" + channel.getChannelId() + "\r\n"); + catalogXml.append("" + channel.getName() + "\r\n"); + catalogXml.append("" + channel.getManufacture() + "\r\n"); + catalogXml.append("" + channel.getModel() + "\r\n"); + catalogXml.append("0\r\n"); + catalogXml.append("CivilCode\r\n"); + catalogXml.append("
" + channel.getAddress() + "
\r\n"); + catalogXml.append("" + channel.getParental() + "\r\n"); + if (channel.getParentId() != null) { + catalogXml.append("" + channel.getParentId() + "\r\n"); + } + catalogXml.append("" + channel.getSecrecy() + "\r\n"); + catalogXml.append("" + channel.getRegisterWay() + "\r\n"); + catalogXml.append("" + (channel.getStatus() == 0 ? "OFF" : "ON") + "\r\n"); + if (!"presence".equals(subscribeInfo.getEventType())) { + catalogXml.append("" + type + "\r\n"); + } + catalogXml.append("
\r\n"); + catalogXml.append("
\r\n"); + catalogXml.append("
\r\n"); + return catalogXml.toString(); + } + @Override - public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo) { + public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List deviceChannels, SubscribeInfo subscribeInfo, Integer index) { if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 @@ -435,39 +446,55 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { return false; } - for (DeviceChannel channel : deviceChannels) { - try { - StringBuffer catalogXml = new StringBuffer(600); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("Catalog\r\n"); - catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); - catalogXml.append("" + deviceChannels.size() + "\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("" + channel.getChannelId() + "\r\n"); - catalogXml.append("" + type + "\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - catalogXml.append("\r\n"); - - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - callIdHeader.setCallId(subscribeInfo.getCallId()); - - String tm = Long.toString(System.currentTimeMillis()); - - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader); - transmitRequest(parentPlatform, request); - Thread.sleep(200); - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - return false; - } catch (InterruptedException e) { - e.printStackTrace(); - } + if (index == null) { + index = 0; } + + if (index > deviceChannels.size() - 1) { + return true; + } + try { + String catalogXml = getCatalogXmlContentForCatalogOther(deviceChannels.get(index), type, parentPlatform); + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() + : udpSipProvider.getNewCallId(); + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml, + callIdHeader, + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); + index += 1; + Integer finalIndex = index; + transmitRequest(parentPlatform, request, null, eventResult -> { + sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex); + }); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return true; } + private String getCatalogXmlContentForCatalogOther(DeviceChannel channel, String type, ParentPlatform parentPlatform) { + if (parentPlatform.getServerGBId().equals(channel.getParentId())) { + channel.setParentId(parentPlatform.getDeviceGBId()); + } + StringBuffer catalogXml = new StringBuffer(600); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("Catalog\r\n"); + catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n"); + catalogXml.append("" + parentPlatform.getDeviceGBId() + "\r\n"); + catalogXml.append("1\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("" + channel.getChannelId() + "\r\n"); + catalogXml.append("" + type + "\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + catalogXml.append("\r\n"); + return catalogXml.toString(); + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java index 390565c7..34d45368 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.message.SIPRequest; @@ -160,13 +161,18 @@ public abstract class SIPRequestProcessorParent { * @throws InvalidArgumentException * @throws ParseException */ - public void responseSdpAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { + public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); SipFactory sipFactory = SipFactory.getInstance(); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); response.setContent(sdp, contentTypeHeader); + // 兼容国标中的使用编码@域名作为RequestURI的情况 SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); + if (sipURI.getPort() == -1) { + sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); + } + logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); Address concatAddress = sipFactory.createAddressFactory().createAddress( sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() @@ -183,13 +189,18 @@ public abstract class SIPRequestProcessorParent { * @throws InvalidArgumentException * @throws ParseException */ - public Response responseXmlAck(RequestEvent evt, String xml) throws SipException, InvalidArgumentException, ParseException { + public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); SipFactory sipFactory = SipFactory.getInstance(); - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); response.setContent(xml, contentTypeHeader); + // 兼容国标中的使用编码@域名作为RequestURI的情况 SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); + if (sipURI.getPort() == -1) { + sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); + } + logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); Address concatAddress = sipFactory.createAddressFactory().createAddress( sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() 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 127ef29a..98ae86f4 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 @@ -72,10 +72,10 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In if (deviceId == null) { streamInfo = new StreamInfo(); streamInfo.setApp(sendRtpItem.getApp()); - streamInfo.setStreamId(sendRtpItem.getStreamId()); + streamInfo.setStream(sendRtpItem.getStreamId()); }else { streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); - sendRtpItem.setStreamId(streamInfo.getStreamId()); + sendRtpItem.setStreamId(streamInfo.getStream()); streamInfo.setApp("rtp"); } @@ -85,7 +85,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In Map param = new HashMap<>(); param.put("vhost","__defaultVhost__"); param.put("app",streamInfo.getApp()); - param.put("stream",streamInfo.getStreamId()); + param.put("stream",streamInfo.getStream()); param.put("ssrc", sendRtpItem.getSsrc()); param.put("dst_url",sendRtpItem.getIp()); param.put("dst_port", sendRtpItem.getPort()); @@ -98,21 +98,21 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In try { if (System.currentTimeMillis() - startTime < 30 * 1000) { MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { + if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStream())) { rtpPushed = true; logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", - streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); + streamInfo.getApp() ,streamInfo.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort()); zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); } else { logger.info("等待设备推流[{}/{}].......", - streamInfo.getApp() ,streamInfo.getStreamId()); + streamInfo.getApp() ,streamInfo.getStream()); Thread.sleep(1000); continue; } } else { rtpPushed = true; logger.info("设备推流[{}/{}]超时,终止向上级推流", - streamInfo.getApp() ,streamInfo.getStreamId()); + streamInfo.getApp() ,streamInfo.getStream()); } } catch (InterruptedException e) { e.printStackTrace(); 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 feb44c54..eb25cde6 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 @@ -89,18 +89,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { logger.info(streamId + "无其它观看者,通知设备停止推流"); - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId); } } // 可能是设备主动停止 Device device = storager.queryVideoDeviceByChannelId(platformGbId); if (device != null) { StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); + if (streamInfo != null) { redisCatchStorage.stopPlay(streamInfo); } storager.stopPlay(device.getDeviceId(), channelId); - mediaServerService.closeRTPServer(device, channelId); + mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream()); } } } catch (SipException e) { 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 ae2819ca..0c228c7f 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 @@ -252,7 +252,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements content.append("f=\r\n"); try { - responseSdpAck(evt, content.toString()); + responseSdpAck(evt, content.toString(), platform); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { @@ -309,7 +309,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements content.append("f=\r\n"); try { - responseSdpAck(evt, content.toString()); + responseSdpAck(evt, content.toString(), platform); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { 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 8d0bdd2f..a2c6cbfb 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 @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.gb28181.bean.CmdType; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; @@ -105,9 +106,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme logger.info("processRequest serverTransactionId is null."); } } - - - } catch (ParseException e) { e.printStackTrace(); } catch (SipException e) { @@ -155,7 +153,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme try { - Response response = responseXmlAck(evt, resultXml.toString()); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); + Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform); ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); subscribeInfo.setToTag(toHeader.getTag()); redisCatchStorage.updateSubscribe(key, subscribeInfo); @@ -196,7 +195,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme } try { - Response response = responseXmlAck(evt, resultXml.toString()); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); + Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform); ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); subscribeInfo.setToTag(toHeader.getTag()); redisCatchStorage.updateSubscribe(key, subscribeInfo); 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 a46b0034..8f412f7d 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 @@ -22,7 +22,7 @@ import org.springframework.util.StringUtils; import javax.sip.RequestEvent; -import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; +import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*; @Component public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -105,6 +105,11 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme storager.insertMobilePosition(mobilePosition); } } + if (!StringUtils.isEmpty(deviceAlarm.getDeviceId())) { + if (deviceAlarm.getAlarmMethod().equals("5")) { + deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType")); + } + } logger.debug("存储报警信息、报警分类"); // 存储报警信息、报警分类 deviceAlarmService.add(deviceAlarm); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java index 7ddcd824..21f36b3a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java @@ -72,6 +72,9 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple List catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId()); if (catalogs.size() > 0) { for (PlatformCatalog catalog : catalogs) { + if (catalog.getParentId().equals(catalog.getPlatformId())) { + catalog.setParentId(parentPlatform.getDeviceGBId()); + } DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setChannelId(catalog.getId()); deviceChannel.setName(catalog.getName()); @@ -83,30 +86,35 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple deviceChannel.setParental(1); deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain()); + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setSecrecy("0"); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 - Thread.sleep(50); + Thread.sleep(100); } } // 回复级联的通道 if (channelReduces.size() > 0) { for (ChannelReduce channelReduce : channelReduces) { + if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) { + channelReduce.setCatalogId(parentPlatform.getDeviceGBId()); + } DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); deviceChannel.setParental(0); deviceChannel.setParentId(channelReduce.getCatalogId()); - cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 - Thread.sleep(50); + Thread.sleep(100); } } // 回复直播的通道 if (gbStreams.size() > 0) { for (GbStream gbStream : gbStreams) { + if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) { + gbStream.setCatalogId(null); + } DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setChannelId(gbStream.getGbId()); deviceChannel.setName(gbStream.getName()); @@ -117,14 +125,14 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setParentId(gbStream.getCatalogId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain()); + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setParental(0); deviceChannel.setSecrecy("0"); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 - Thread.sleep(50); + Thread.sleep(100); } } if (size == 0) { 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 228ce10f..edd9fe86 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 @@ -68,6 +68,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp } if (device.getPort() != rPort) { device.setPort(rPort); + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); videoManagerStorager.updateDevice(device); redisCatchStorage.updateDevice(device); } 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 c61b7279..3c83ec29 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java @@ -62,7 +62,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*"); if (streamInfo != null) { redisCatchStorage.stopPlayback(streamInfo); - cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId()); + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream()); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java index c5c2961b..925a21e5 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java @@ -75,6 +75,9 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem int size = catalogs.size() + channelReduces.size() + gbStreams.size(); if (catalogs.size() > 0) { for (PlatformCatalog catalog : catalogs) { + if (catalog.getParentId().equals(parentPlatform.getServerGBId())) { + catalog.setParentId(parentPlatform.getDeviceGBId()); + } DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setChannelId(catalog.getId()); deviceChannel.setName(catalog.getName()); @@ -86,30 +89,35 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem deviceChannel.setParental(1); deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain()); + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setSecrecy("0"); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 - Thread.sleep(50); + Thread.sleep(100); } } // 回复级联的通道 if (channelReduces.size() > 0) { for (ChannelReduce channelReduce : channelReduces) { + if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) { + channelReduce.setCatalogId(parentPlatform.getDeviceGBId()); + } DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); - // TODO 目前暂时认为这里只用通道没有目录 deviceChannel.setParental(0); deviceChannel.setParentId(channelReduce.getCatalogId()); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 - Thread.sleep(50); + Thread.sleep(100); } } // 回复直播的通道 if (gbStreams.size() > 0) { for (GbStream gbStream : gbStreams) { + if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) { + gbStream.setCatalogId(parentPlatform.getDeviceGBId()); + } DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setChannelId(gbStream.getGbId()); deviceChannel.setName(gbStream.getName()); @@ -120,7 +128,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setParentId(gbStream.getCatalogId()); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(config.getDomain()); + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setParental(0); @@ -128,7 +136,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); // 防止发送过快 - Thread.sleep(50); + Thread.sleep(100); } } if (size == 0) { 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 a5dced37..b6040aad 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 @@ -78,7 +78,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { if (response.getStatusCode() == 401) { WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null); + sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true); }else if (response.getStatusCode() == 200){ // 注册/注销成功 logger.info(String.format("%s %s成功", platformGBId, action)); 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 94e0cd80..ba6eed5f 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 @@ -191,7 +191,7 @@ public class XmlUtil { String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : ""; deviceChannel.setChannelId(channelId); // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 - if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) { deviceChannel.setStatus(1); } if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { @@ -255,9 +255,14 @@ public class XmlUtil { } else { deviceChannel.setLatitude(0.00); } - if (XmlUtil.getText(itemDevice, "PTZType") == null - || XmlUtil.getText(itemDevice, "PTZType") == "") { - deviceChannel.setPTZType(0); + if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) { + //兼容INFO中的信息 + Element info = itemDevice.element("Info"); + if(XmlUtil.getText(info, "PTZType") == null || "".equals(XmlUtil.getText(info, "PTZType"))){ + deviceChannel.setPTZType(0); + }else{ + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(info, "PTZType"))); + } } else { deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); } 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 3789207e..75b0dea3 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 @@ -361,6 +361,9 @@ public class ZLMHttpHookListener { if (mediaServerItem != null){ if (regist) { StreamPushItem streamPushItem = null; + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks); + item.setStreamInfo(streamInfoByAppAndStream); + redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item); if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() @@ -378,7 +381,7 @@ public class ZLMHttpHookListener { } } if (gbStreams.size() > 0) { - eventPublisher.catalogEventPublishForStream(null, gbStreams.toArray(new GbStream[0]), CatalogEvent.ON); + eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON); } }else { @@ -439,14 +442,16 @@ public class ZLMHttpHookListener { if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) { ret.put("close", false); } else { - cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); + cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(), + streamInfoForPlayCatch.getStream()); redisCatchStorage.stopPlay(streamInfoForPlayCatch); storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); } }else{ StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId); if (streamInfoForPlayBackCatch != null) { - cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId()); + cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), + streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream()); redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch); }else { StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java index c8cca53e..ff8204c0 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java @@ -91,6 +91,7 @@ public class ZLMHttpHookSubscribe { } } if (null != result && result){ + // TODO 报错未处理 iterator.remove(); } } 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 a15e01a4..c8844959 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 @@ -122,7 +122,6 @@ public class ZLMMediaListManager { transform.setName(thirdPartyGB.getName()); } } - storager.updateMedia(transform); if (!StringUtils.isEmpty(transform.getGbId())) { // 如果这个国标ID已经给了其他推流且流已离线,则移除其他推流 List gbStreams = gbStreamMapper.selectByGBId(transform.getGbId()); @@ -135,13 +134,16 @@ public class ZLMMediaListManager { } } } - if (gbStreamMapper.selectOne(transform.getApp(), transform.getStream()) != null) { + StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(transform.getApp(), transform.getStream()); + if (streamProxyItem != null) { + transform.setGbStreamId(streamProxyItem.getGbStreamId()); gbStreamMapper.update(transform); }else { transform.setCreateStamp(System.currentTimeMillis()); gbStreamMapper.add(transform); } } + 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 8238a838..d0b1cb2d 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 @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import okhttp3.*; +import okhttp3.logging.HttpLoggingInterceptor; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,8 +26,23 @@ public class ZLMRESTfulUtils { void run(JSONObject response); } + private OkHttpClient getClient(){ + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); + if (logger.isDebugEnabled()) { + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> { + logger.debug("http请求参数:" + message); + }); + logging.setLevel(HttpLoggingInterceptor.Level.BASIC); + // OkHttp進行添加攔截器loggingInterceptor + httpClientBuilder.addInterceptor(logging); + } + return httpClientBuilder.build(); + } + + public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map param, RequestCallback callback) { - OkHttpClient client = new OkHttpClient(); + OkHttpClient client = getClient(); + if (mediaServerItem == null) { return null; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index de5d4832..9d0e354c 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -92,6 +92,7 @@ public class ZLMRunner implements CommandLineRunner { // 获取所有的zlm, 并开启主动连接 List all = mediaServerService.getAllFromDatabase(); + mediaServerService.updateVmServer(all); if (all.size() == 0) { all.add(mediaConfig.getMediaSerItem()); } 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 4685d1fd..ad158ec7 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 @@ -1,5 +1,7 @@ package com.genersoft.iot.vmp.media.zlm.dto; +import com.genersoft.iot.vmp.common.StreamInfo; + import java.util.List; public class MediaItem { @@ -281,6 +283,8 @@ public class MediaItem { } } + private StreamInfo streamInfo; + public String getApp() { return app; } @@ -402,4 +406,12 @@ public class MediaItem { public void setMediaServerId(String mediaServerId) { this.mediaServerId = mediaServerId; } + + public StreamInfo getStreamInfo() { + return streamInfo; + } + + public void setStreamInfo(StreamInfo streamInfo) { + this.streamInfo = streamInfo; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java index ec2714fd..2e8a68ee 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java @@ -42,11 +42,13 @@ public interface IMediaServerService { void setZLMConfig(MediaServerItem mediaServerItem, boolean restart); + void updateVmServer(List mediaServerItemList); + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId); SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback); - void closeRTPServer(Device device, String channelId); + void closeRTPServer(Device device, String channelId, String ssrc); void clearRTPServer(MediaServerItem mediaServerItem); @@ -74,6 +76,8 @@ public interface IMediaServerService { void delete(String id); + void deleteDb(String id); + MediaServerItem getDefaultMediaServer(); void updateMediaServerKeepalive(String mediaServerId, JSONObject data); 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 8a7437cd..12bb8fa9 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -5,14 +5,16 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.bean.PlayBackCallback; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; +import org.springframework.http.ResponseEntity; +import org.springframework.web.context.request.async.DeferredResult; /** * 点播处理 */ public interface IPlayService { - void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); @@ -20,4 +22,6 @@ public interface IPlayService { MediaServerItem getNewMediaServerItem(Device device); void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString); + + DeferredResult> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback errorCallBack); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java new file mode 100644 index 00000000..089523f9 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java @@ -0,0 +1,9 @@ +package com.genersoft.iot.vmp.service.bean; + +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; + +public interface PlayBackCallback { + + void call(RequestMessage msg); + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java b/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java index faab1c80..1723bc59 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java @@ -4,12 +4,12 @@ public class SSRCInfo { private int port; private String ssrc; - private String StreamId; + private String Stream; - public SSRCInfo(int port, String ssrc, String streamId) { + public SSRCInfo(int port, String ssrc, String stream) { this.port = port; this.ssrc = ssrc; - StreamId = streamId; + Stream = stream; } public int getPort() { @@ -28,11 +28,11 @@ public class SSRCInfo { this.ssrc = ssrc; } - public String getStreamId() { - return StreamId; + public String getStream() { + return Stream; } - public void setStreamId(String streamId) { - StreamId = streamId; + public void setStream(String stream) { + Stream = stream; } } 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 2b4515f7..32a1305d 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java @@ -103,7 +103,7 @@ public class GbStreamServiceImpl implements IGbStreamService { deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); deviceChannel.setRegisterWay(1); - deviceChannel.setCivilCode(sipConfig.getDomain()); + deviceChannel.setCivilCode(sipConfig.getDomain().substring(0, sipConfig.getDomain().length() - 2)); deviceChannel.setModel("live"); deviceChannel.setOwner("wvp-pro"); deviceChannel.setParental(0); 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 507d4e66..4f08c99d 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 @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -45,8 +46,7 @@ import java.util.*; * 媒体服务器节点管理 */ @Service -@Order(value=2) -public class MediaServerServiceImpl implements IMediaServerService, CommandLineRunner { +public class MediaServerServiceImpl implements IMediaServerService { private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); @@ -101,9 +101,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR * 初始化 */ @Override - public void run(String... args) throws Exception { + public void updateVmServer(List mediaServerItemList) { logger.info("[缓存初始化] Media Server "); - List mediaServerItemList = mediaServerMapper.queryAll(); for (MediaServerItem mediaServerItem : mediaServerItemList) { if (StringUtils.isEmpty(mediaServerItem.getId())) { continue; @@ -161,15 +160,16 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR } @Override - public void closeRTPServer(Device device, String channelId) { - String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId); + public void closeRTPServer(Device device, String channelId, String stream) { + String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId, stream); + String ssrc = streamSession.getSSRC(device.getDeviceId(), channelId, stream); MediaServerItem mediaServerItem = this.getOne(mediaServerId); if (mediaServerItem != null) { String streamId = String.format("%s_%s", device.getDeviceId(), channelId); zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId); - releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId)); + releaseSsrc(mediaServerItem, ssrc); } - streamSession.remove(device.getDeviceId(), channelId); + streamSession.remove(device.getDeviceId(), channelId, stream); } @Override @@ -223,7 +223,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR String key = (String) mediaServerKey; MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key); // 检查状态 - if (redisUtil.zScore(onlineKey, mediaServerItem.getId()) != null) { + Double aDouble = redisUtil.zScore(onlineKey, mediaServerItem.getId()); + if (aDouble != null) { mediaServerItem.setStatus(true); } result.add(mediaServerItem); @@ -278,6 +279,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @Override public MediaServerItem getDefaultMediaServer() { + return mediaServerMapper.queryDefault(); } @@ -607,6 +609,11 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + id; redisUtil.del(key); } + @Override + public void deleteDb(String id){ + //同步删除数据库中的数据 + mediaServerMapper.delOne(id); + } @Override public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java index fcb52070..3c776b49 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; @@ -26,6 +27,10 @@ public class MediaServiceImpl implements IMediaService { @Autowired private IMediaServerService mediaServerService; + + @Autowired + private MediaConfig mediaConfig; + @Autowired private ZLMRESTfulUtils zlmresTfulUtils; @@ -39,15 +44,12 @@ public class MediaServiceImpl implements IMediaService { @Override public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) { StreamInfo streamInfo = null; - - MediaServerItem mediaInfo; if (mediaServerId == null) { - mediaInfo = mediaServerService.getDefaultMediaServer(); - }else { - mediaInfo = mediaServerService.getOne(mediaServerId); + mediaServerId = mediaConfig.getId(); } + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);; if (mediaInfo == null) { - return streamInfo; + return null; } JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream); if (mediaList != null) { @@ -72,7 +74,7 @@ public class MediaServiceImpl implements IMediaService { @Override public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) { StreamInfo streamInfoResult = new StreamInfo(); - streamInfoResult.setStreamId(stream); + streamInfoResult.setStream(stream); streamInfoResult.setApp(app); if (addr == null) { addr = mediaInfo.getStreamIp(); 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 cf30a794..9c87a0a6 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 @@ -16,10 +16,10 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.service.bean.PlayBackCallback; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import com.genersoft.iot.vmp.service.IMediaService; @@ -53,9 +53,6 @@ public class PlayServiceImpl implements IPlayService { @Autowired private IRedisCatchStorage redisCatchStorage; - @Autowired - private RedisUtil redis; - @Autowired private DeferredResultHolder resultHolder; @@ -104,19 +101,21 @@ public class PlayServiceImpl implements IPlayService { logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); WVPResult wvpResult = new WVPResult(); wvpResult.setCode(-1); - SIPDialog dialog = streamSession.getDialog(deviceId, channelId); + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, streamInfo.getStream()); if (dialog != null) { wvpResult.setMsg("收流超时,请稍候重试"); }else { wvpResult.setMsg("点播超时,请稍候重试"); } + msg.setData(wvpResult); // 点播超时回复BYE - cmder.streamByeCmd(device.getDeviceId(), channelId); + cmder.streamByeCmd(device.getDeviceId(), channelId, streamInfo.getStream()); // 释放rtpserver - mediaServerService.closeRTPServer(playResult.getDevice(), channelId); + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, streamInfo.getStream()); // 回复之前所有的点播请求 resultHolder.invokeAllResult(msg); + // TODO 释放ssrc }); result.onCompletion(()->{ // 点播结束时调用截图接口 @@ -154,14 +153,12 @@ public class PlayServiceImpl implements IPlayService { } }); if (streamInfo == null) { - SSRCInfo ssrcInfo; String streamId = null; if (mediaServerItem.isRtpEnable()) { streamId = String.format("%s_%s", device.getDeviceId(), channelId); } - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId); - + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId); // 发送点播消息 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { logger.info("收到订阅消息: " + response.toJSONString()); @@ -173,7 +170,7 @@ public class PlayServiceImpl implements IPlayService { WVPResult wvpResult = new WVPResult(); wvpResult.setCode(-1); // 点播返回sip错误 - mediaServerService.closeRTPServer(playResult.getDevice(), channelId); + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream()); wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); msg.setData(wvpResult); resultHolder.invokeAllResult(msg); @@ -184,7 +181,7 @@ public class PlayServiceImpl implements IPlayService { }); } else { - String streamId = streamInfo.getStreamId(); + String streamId = streamInfo.getStream(); if (streamId == null) { WVPResult wvpResult = new WVPResult(); wvpResult.setCode(-1); @@ -213,18 +210,16 @@ public class PlayServiceImpl implements IPlayService { // TODO 点播前是否重置状态 redisCatchStorage.stopPlay(streamInfo); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - SSRCInfo ssrcInfo; String streamId2 = null; if (mediaServerItem.isRtpEnable()) { streamId2 = String.format("%s_%s", device.getDeviceId(), channelId); } - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2); - + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2); cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { logger.info("收到订阅消息: " + response.toJSONString()); onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid); }, (event) -> { - mediaServerService.closeRTPServer(playResult.getDevice(), channelId); + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream()); WVPResult wvpResult = new WVPResult(); wvpResult.setCode(-1); wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); @@ -242,12 +237,12 @@ public class PlayServiceImpl implements IPlayService { RequestMessage msg = new RequestMessage(); msg.setId(uuid); msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); + StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId); if (streamInfo != null) { DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (deviceChannel != null) { - deviceChannel.setStreamId(streamInfo.getStreamId()); - storager.startPlay(deviceId, channelId, streamInfo.getStreamId()); + deviceChannel.setStreamId(streamInfo.getStream()); + storager.startPlay(deviceId, channelId, streamInfo.getStream()); } redisCatchStorage.startPlay(streamInfo); msg.setData(JSON.toJSONString(streamInfo)); @@ -284,29 +279,53 @@ public class PlayServiceImpl implements IPlayService { @Override - public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { + public DeferredResult> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback callback) { + String uuid = UUID.randomUUID().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; + DeferredResult> result = new DeferredResult<>(30000L); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); + return result; + } + + MediaServerItem newMediaServerItem = getNewMediaServerItem(device); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result); RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId); msg.setId(uuid); - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); - if (streamInfo != null) { + msg.setKey(key); + result.onTimeout(()->{ + msg.setData("回放超时"); + callback.call(msg); + }); + cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> { + logger.info("收到订阅消息: " + response.toJSONString()); + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); + if (streamInfo == null) { + logger.warn("设备回放API调用失败!"); + msg.setData("设备回放API调用失败!"); + callback.call(msg); + return; + } redisCatchStorage.startPlayback(streamInfo); msg.setData(JSON.toJSONString(streamInfo)); - resultHolder.invokeResult(msg); - } else { - logger.warn("设备回放API调用失败!"); - msg.setData("设备回放API调用失败!"); - resultHolder.invokeResult(msg); - } + callback.call(msg); + }, event -> { + msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); + callback.call(msg); + }); + return result; } + @Override public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { RequestMessage msg = new RequestMessage(); msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId); msg.setId(uuid); - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid); + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); if (streamInfo != null) { redisCatchStorage.startDownload(streamInfo); msg.setData(JSON.toJSONString(streamInfo)); @@ -319,7 +338,7 @@ public class PlayServiceImpl implements IPlayService { } - public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { + public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) { String streamId = resonse.getString("stream"); JSONArray tracks = resonse.getJSONArray("tracks"); StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks); 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 index e3bfcde7..92bcd5e8 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,8 @@ package com.genersoft.iot.vmp.service.impl; import com.alibaba.fastjson.JSON; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +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; @@ -11,11 +13,14 @@ import org.springframework.stereotype.Component; @Component public class RedisGPSMsgListener implements MessageListener { + private final static Logger logger = LoggerFactory.getLogger(RedisGPSMsgListener.class); + @Autowired private IRedisCatchStorage redisCatchStorage; @Override public void onMessage(Message message, byte[] bytes) { + logger.debug("收到来自REDIS的GPS通知: {}", 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/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java index 1850cdfd..c1c7e24b 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -132,7 +132,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { }else { streamLive = true; StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( - mediaInfo, param.getApp(), param.getStream(), null); + mediaInfo, param.getApp(), param.getStream(), null, null); wvpResult.setData(streamInfo); } 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 8a015d9d..a13dc29d 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 @@ -377,7 +377,7 @@ public class StreamPushServiceImpl implements IStreamPushService { if (streamPushItemsForPlatform.size() > 0) { List streamPushItemListFroPlatform = new ArrayList<>(); - Map> platformForEvent = new HashMap<>(); + Map> platformForEvent = new HashMap<>(); // 遍历存储结果,查找app+Stream->platformId+catalogId的对应关系,然后执行批量写入 for (StreamPushItem streamPushItem : streamPushItemsForPlatform) { List platFormInfoList = streamPushItemsForAll.get(streamPushItem.getApp() + streamPushItem.getStream()); @@ -390,16 +390,17 @@ public class StreamPushServiceImpl implements IStreamPushService { // 数组 platFormInfoArray 0 为平台ID。 1为目录ID streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]); - List streamPushItemsInPlatform = platformForEvent.get(streamPushItem.getPlatformId()); - if (streamPushItemsInPlatform == null) { - streamPushItemsInPlatform = new ArrayList<>(); - platformForEvent.put(platFormInfoArray[0], streamPushItemsInPlatform); + List gbStreamList = platformForEvent.get(streamPushItem.getPlatformId()); + if (gbStreamList == null) { + gbStreamList = new ArrayList<>(); + platformForEvent.put(platFormInfoArray[0], gbStreamList); } // 为发送通知整理数据 + streamPushItemForPlatform.setName(streamPushItem.getName()); streamPushItemForPlatform.setApp(streamPushItem.getApp()); streamPushItemForPlatform.setStream(streamPushItem.getStream()); streamPushItemForPlatform.setGbId(streamPushItem.getGbId()); - streamPushItemsInPlatform.add(streamPushItemForPlatform); + gbStreamList.add(streamPushItemForPlatform); } if (platFormInfoArray.length > 1) { streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]); @@ -416,7 +417,7 @@ public class StreamPushServiceImpl implements IStreamPushService { // 发送通知 for (String platformId : platformForEvent.keySet()) { eventPublisher.catalogEventPublishForStream( - platformId, platformForEvent.get(platformId).toArray(new GbStream[0]), CatalogEvent.ADD); + platformId, platformForEvent.get(platformId), CatalogEvent.ADD); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index edd6cbc0..1a939020 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -7,6 +7,7 @@ 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.service.bean.GPSMsgInfo; +import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import java.util.List; @@ -220,4 +221,5 @@ public interface IRedisCatchStorage { void addMemInfo(double memInfo); void addNetInfo(Map networkInterfaces); + } 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 6d9cd002..d4cace44 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 @@ -87,26 +87,27 @@ public interface DeviceChannelMapper { void startPlay(String deviceId, String channelId, String streamId); @Select(value = {" "}) List queryChannelListInAll(String query, Boolean online, Boolean hasSubChannel, String platformId, String catalogId); @@ -196,8 +197,8 @@ public interface DeviceChannelMapper { List queryOnlineChannelsByDeviceId(String deviceId); @Select(" SELECT\n" + + " id,\n" + " channelId,\n" + - " channelId as id,\n" + " deviceId,\n" + " parentId,\n" + " status,\n" + 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 ed2d8c89..28f79f18 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 @@ -74,7 +74,7 @@ public interface DeviceMapper { ", keepaliveTime='${keepaliveTime}'" + ", expires=${expires}" + ", charset='${charset}'" + - ", subscribeCycleForCatalog=#{subscribeCycleForCatalog}" + + ", subscribeCycleForCatalog=${subscribeCycleForCatalog}" + "WHERE deviceId='${deviceId}'"+ " "}) int update(Device device); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java index 593b78a7..230b23b6 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java @@ -19,6 +19,7 @@ public interface GbStreamMapper { "('${app}', '${stream}', '${gbId}', '${name}', " + "'${longitude}', '${latitude}', '${streamType}', " + "'${mediaServerId}', ${status}, ${createStamp})") + @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId") int add(GbStream gbStream); @Update("UPDATE gb_stream " + diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java index 37c86a81..08360013 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java @@ -21,27 +21,31 @@ public interface PlatformChannelMapper { * 查询列表里已经关联的 */ @Select("") - List findChannelRelatedPlatform(String platformId, List deviceAndChannelIds); + List findChannelRelatedPlatform(String platformId, List channelReduces); @Insert("") int addChannels(String platformId, List channelReducesToAdd); @Delete("") int delChannelForGB(String platformId, List channelReducesToDel); @Delete("") int delChannelForDeviceId(String deviceId); @@ -50,16 +54,19 @@ public interface PlatformChannelMapper { "") int cleanChannelForGB(String platformId); - @Select("SELECT * FROM device_channel WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE " + - "platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'") + @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}' and pgc.platformId='${platformId}'") DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); - @Select("select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " + - "from device_channel dc left join platform_gb_channel pgc on dc.deviceId = pgc.deviceId and dc.channelId = pgc.channelId " + - "where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") + @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " + + " from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId " + + " where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") List queryChannelInParentPlatformAndCatalog(String platformId, String catalogId); - @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE platformId='${platformId}' AND channelId='${channelId}')") + @Select("select d.*\n" + + "from platform_gb_channel pgc\n" + + " left join device_channel dc on dc.id = pgc.deviceChannelId\n" + + " left join device d on dc.deviceId = d.deviceId\n" + + "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}") Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); @Delete(" ") diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java index 3f5c72bf..8ee3e384 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java @@ -19,6 +19,7 @@ public interface StreamProxyMapper { @Update("UPDATE stream_proxy " + "SET type=#{type}, " + + "name=#{name}," + "app=#{app}," + "name=#{name}," + "stream=#{stream}," + 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 594c319e..909d3a8b 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 @@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.storager.dao; import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import org.apache.ibatis.annotations.*; -import org.omg.PortableInterceptor.INACTIVE; +// import org.omg.PortableInterceptor.INACTIVE; import org.springframework.stereotype.Repository; import java.util.Collection; 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 92fdf6c5..0a78a537 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 @@ -10,6 +10,7 @@ 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.service.bean.GPSMsgInfo; +import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; @@ -91,7 +92,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { */ @Override public boolean startPlay(StreamInfo stream) { - return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()), + return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), + stream.getStream(), stream.getDeviceID(), stream.getChannelId()), stream); } @@ -105,7 +107,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { if (streamInfo == null) return false; return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), - streamInfo.getStreamId(), + streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId())); } @@ -119,7 +121,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), - streamInfo.getStreamId(), + streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId())); } @@ -165,14 +167,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public boolean startPlayback(StreamInfo stream) { - return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),stream.getStreamId(), - stream.getDeviceID(), stream.getChannelId()), stream); + return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, + userSetup.getServerId(), stream.getStream(), stream.getDeviceID(), stream.getChannelId()), stream); } @Override public boolean startDownload(StreamInfo streamInfo) { - return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),streamInfo.getStreamId(), - streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo); + return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(), + streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo); } @Override @@ -186,7 +188,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { } return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(), - streamInfo.getStreamId(), + streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId())); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index 77164c28..0e0a8e33 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.storager.impl; +import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; @@ -156,7 +157,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { public synchronized void updateChannel(String deviceId, DeviceChannel channel) { String channelId = channel.getChannelId(); channel.setDeviceId(deviceId); - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); + if (streamInfo != null) { + channel.setStreamId(streamInfo.getStream()); + } String now = this.format.format(System.currentTimeMillis()); channel.setUpdateTime(now); DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); @@ -178,7 +182,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { if (channelList.size() == 0) { for (DeviceChannel channel : channels) { channel.setDeviceId(deviceId); - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId()); + if (streamInfo != null) { + channel.setStreamId(streamInfo.getStream()); + } String now = this.format.format(System.currentTimeMillis()); channel.setUpdateTime(now); channel.setCreateTime(now); @@ -189,9 +196,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { channelsInStore.put(deviceChannel.getChannelId(), deviceChannel); } for (DeviceChannel channel : channels) { - String channelId = channel.getChannelId(); channel.setDeviceId(deviceId); - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId()); + if (streamInfo != null) { + channel.setStreamId(streamInfo.getStream()); + } String now = this.format.format(System.currentTimeMillis()); channel.setUpdateTime(now); if (channelsInStore.get(channel.getChannelId()) != null) { @@ -607,19 +616,19 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @Override public int updateChannelForGB(String platformId, List channelReduces, String catalogId) { - Map deviceAndChannels = new HashMap<>(); + Map deviceAndChannels = new HashMap<>(); for (ChannelReduce channelReduce : channelReduces) { channelReduce.setCatalogId(catalogId); - deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce); + deviceAndChannels.put(channelReduce.getId(), channelReduce); } - List deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet()); + List deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet()); // 查询当前已经存在的 - List relatedPlatformchannels = platformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList); - if (relatedPlatformchannels != null) { - deviceAndChannelList.removeAll(relatedPlatformchannels); + List channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces); + if (deviceAndChannelList != null) { + deviceAndChannelList.removeAll(channelIds); } - for (String relatedPlatformchannel : relatedPlatformchannels) { - deviceAndChannels.remove(relatedPlatformchannel); + for (Integer channelId : channelIds) { + deviceAndChannels.remove(channelId); } List channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); // 对剩下的数据进行存储 diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java index 0de21608..6b955081 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java @@ -18,7 +18,7 @@ public class BaseNode implements INode { /** * 主键ID */ - protected String id; + protected int id; /** * 父节点ID diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java index 0ba72072..d0500a1e 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java @@ -19,7 +19,7 @@ public class ForestNode extends BaseNode { */ private Object content; - public ForestNode(String id, String parentId, Object content) { + public ForestNode(int id, String parentId, Object content) { this.id = id; this.parentId = parentId; this.content = content; diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java index de98fdc7..895e6de0 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java @@ -17,12 +17,12 @@ public class ForestNodeManager> { /** * 森林的所有节点 */ - private final ImmutableMap nodeMap; + private final ImmutableMap nodeMap; /** * 森林的父节点ID */ - private final Map parentIdMap = Maps.newHashMap(); + private final Map parentIdMap = Maps.newHashMap(); public ForestNodeManager(List nodes) { nodeMap = Maps.uniqueIndex(nodes, INode::getId); @@ -46,7 +46,7 @@ public class ForestNodeManager> { * * @param parentId 父节点ID */ - public void addParentId(String parentId) { + public void addParentId(int parentId) { parentIdMap.put(parentId, ""); } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java index 4d6ebfcb..c82d6f76 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java @@ -14,7 +14,7 @@ public interface INode extends Serializable { * * @return String */ - String getId(); + int getId(); /** * 父主键 diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java index 773f2c13..4eaf5987 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java @@ -19,7 +19,7 @@ public class DeviceChannelTree extends DeviceChannel implements INode("不允许删除在线设备!", HttpStatus.NOT_ACCEPTABLE); - } + // 清除redis记录 boolean isSuccess = storager.delete(deviceId); if (isSuccess) { @@ -319,20 +316,20 @@ public class DeviceQuery { if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset()); if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId()); - if ((deviceInStore.getSubscribeCycleForCatalog() <=0 && device.getSubscribeCycleForCatalog() > 0) - || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); - // 开启订阅 - deviceService.addCatalogSubscribe(deviceInStore); - } - if (deviceInStore.getSubscribeCycleForCatalog() > 0 && device.getSubscribeCycleForCatalog() <= 0) { - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); - // 取消订阅 - deviceService.removeCatalogSubscribe(deviceInStore); + if (device.getSubscribeCycleForCatalog() > 0) { + if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { + // 开启订阅 + deviceService.addCatalogSubscribe(deviceInStore); + } + }else if (device.getSubscribeCycleForCatalog() == 0) { + if (deviceInStore.getSubscribeCycleForCatalog() != 0) { + // 取消订阅 + deviceService.removeCatalogSubscribe(deviceInStore); + } } - storager.updateDevice(deviceInStore); - cmder.deviceInfoQuery(deviceInStore); + storager.updateDevice(device); + cmder.deviceInfoQuery(device); } WVPResult result = new WVPResult<>(); result.setCode(0); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java index d5caab29..e07c81d8 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.media; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @@ -9,6 +10,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +35,9 @@ public class MediaController { @Autowired private IMediaService mediaService; + @Autowired + private IMediaServerService mediaServerService; + /** * 根据应用名和流id获取播放地址 diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java index b8507299..78b5d537 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java @@ -149,8 +149,16 @@ public class PlatformController { if (updateResult) { // 保存时启用就发送注册 if (parentPlatform.isEnable()) { - // 只要保存就发送注册 - commanderForPlatform.register(parentPlatform, null, null); + if (parentPlatformOld.isStatus()) { + commanderForPlatform.unregister(parentPlatformOld, null, eventResult -> { + // 只要保存就发送注册 + commanderForPlatform.register(parentPlatform, null, null); + }); + }else { + // 只要保存就发送注册 + commanderForPlatform.register(parentPlatform, null, null); + } + } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 commanderForPlatform.unregister(parentPlatform, null, null); } @@ -203,10 +211,21 @@ public class PlatformController { if (updateResult) { // 保存时启用就发送注册 if (parentPlatform.isEnable()) { - // 只要保存就发送注册 - commanderForPlatform.register(parentPlatform, null, null); + if (parentPlatformOld.isStatus()) { + commanderForPlatform.unregister(parentPlatformOld, null, null); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // 只要保存就发送注册 + commanderForPlatform.register(parentPlatform, null, null); + }else { + // 只要保存就发送注册 + commanderForPlatform.register(parentPlatform, null, null); + } } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 - commanderForPlatform.unregister(parentPlatform, null, null); + commanderForPlatform.unregister(parentPlatformOld, null, null); } wvpResult.setCode(0); wvpResult.setMsg("success"); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java index fc13e052..10015e4e 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java @@ -1,10 +1,17 @@ package com.genersoft.iot.vmp.vmanager.gb28181.platform.bean; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; + /** * 精简的channel信息展示,主要是选择通道的时候展示列表使用 */ public class ChannelReduce { + /** + * deviceChannel的数据库自增ID + */ + private int id; + /** * 通道id */ @@ -45,6 +52,13 @@ public class ChannelReduce { */ private String catalogId; + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } public String getChannelId() { return channelId; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java index c22a5584..8350d293 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -110,26 +110,26 @@ public class PlayController { String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; resultHolder.put(key, uuid, result); Device device = storager.queryVideoDevice(deviceId); - cmder.streamByeCmd(deviceId, channelId, (event) -> { - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); - if (streamInfo == null) { - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("点播未找到"); - resultHolder.invokeAllResult(msg); - storager.stopPlay(deviceId, channelId); - }else { - redisCatchStorage.stopPlay(streamInfo); - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - //Response response = event.getResponse(); - msg.setData(String.format("success")); - resultHolder.invokeAllResult(msg); - } - mediaServerService.closeRTPServer(device, channelId); + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); + if (streamInfo == null) { + RequestMessage msg = new RequestMessage(); + msg.setId(uuid); + msg.setKey(key); + msg.setData("点播未找到"); + resultHolder.invokeAllResult(msg); + storager.stopPlay(deviceId, channelId); + return result; + } + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), (event) -> { + redisCatchStorage.stopPlay(streamInfo); + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + RequestMessage msg = new RequestMessage(); + msg.setId(uuid); + msg.setKey(key); + //Response response = event.getResponse(); + msg.setData(String.format("success")); + resultHolder.invokeAllResult(msg); + mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream()); }); if (deviceId != null || channelId != null) { @@ -329,7 +329,7 @@ public class PlayController { jsonObject.put("deviceId", transaction.getDeviceId()); jsonObject.put("channelId", transaction.getChannelId()); jsonObject.put("ssrc", transaction.getSsrc()); - jsonObject.put("streamId", transaction.getStreamId()); + jsonObject.put("streamId", transaction.getStream()); objects.add(jsonObject); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java index 3f846c60..c2053e62 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java @@ -96,7 +96,7 @@ public class DownloadController { StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); if (streamInfo != null) { // 停止之前的下载 - cmder.streamByeCmd(deviceId, channelId); + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream()); } MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); @@ -114,7 +114,7 @@ public class DownloadController { cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> { logger.info("收到订阅消息: " + response.toJSONString()); - playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString()); + playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid); }, event -> { RequestMessage msg = new RequestMessage(); msg.setId(uuid); @@ -130,11 +130,12 @@ public class DownloadController { @ApiImplicitParams({ @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), }) - @GetMapping("/stop/{deviceId}/{channelId}") - public ResponseEntity playStop(@PathVariable String deviceId, @PathVariable String channelId) { + @GetMapping("/stop/{deviceId}/{channelId}/{stream}") + public ResponseEntity playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { - cmder.streamByeCmd(deviceId, channelId); + cmder.streamByeCmd(deviceId, channelId, stream); if (logger.isDebugEnabled()) { logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java index 8f83e7c4..3607a8d4 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java @@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -75,52 +76,8 @@ public class PlaybackController { if (logger.isDebugEnabled()) { logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); } - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; - DeferredResult> result = new DeferredResult>(30000L); - Device device = storager.queryVideoDevice(deviceId); - if (device == null) { - result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); - return result; - } - MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); - // 超时处理 - result.onTimeout(()->{ - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("Timeout"); - resultHolder.invokeResult(msg); - }); - - StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); - if (streamInfo != null) { - // 停止之前的回放 - cmder.streamByeCmd(deviceId, channelId); - } - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result); - - if (newMediaServerItem == null) { - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData("Timeout"); - resultHolder.invokeResult(msg); - return result; - } - - cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> { - logger.info("收到订阅消息: " + response.toJSONString()); - playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString()); - }, event -> { - RequestMessage msg = new RequestMessage(); - msg.setId(uuid); - msg.setKey(key); - msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); + DeferredResult> result = playService.playBack(deviceId, channelId, startTime, endTime, msg->{ resultHolder.invokeResult(msg); }); @@ -131,24 +88,31 @@ public class PlaybackController { @ApiImplicitParams({ @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), }) - @GetMapping("/stop/{deviceId}/{channelId}") - public ResponseEntity playStop(@PathVariable String deviceId, @PathVariable String channelId) { + @GetMapping("/stop/{deviceId}/{channelId}/{stream}") + public ResponseEntity playStop( + @PathVariable String deviceId, + @PathVariable String channelId, + @PathVariable String stream) { - cmder.streamByeCmd(deviceId, channelId); + cmder.streamByeCmd(deviceId, channelId, stream); if (logger.isDebugEnabled()) { logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId)); } + if (StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(channelId) || StringUtils.isEmpty(stream)) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } if (deviceId != null && channelId != null) { JSONObject json = new JSONObject(); json.put("deviceId", deviceId); json.put("channelId", channelId); - return new ResponseEntity(json.toString(), HttpStatus.OK); + return new ResponseEntity<>(json.toString(), HttpStatus.OK); } else { logger.warn("设备录像回放停止API调用失败!"); - return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java index c27fb0e1..1500f351 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java @@ -158,6 +158,7 @@ public class ServerController { public WVPResult deleteMediaServer(@RequestParam String id){ if (mediaServerService.getOne(id) != null) { mediaServerService.delete(id); + mediaServerService.deleteDb(id); }else { WVPResult result = new WVPResult<>(); result.setCode(-1); diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java index 70f98114..853ec562 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java @@ -103,7 +103,7 @@ public class ApiStreamController { PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); JSONObject result = new JSONObject(); - result.put("StreamID", streamInfo.getStreamId()); + result.put("StreamID", streamInfo.getStream()); result.put("DeviceID", device.getDeviceId()); result.put("ChannelID", code); result.put("ChannelName", deviceChannel.getName()); @@ -177,7 +177,7 @@ public class ApiStreamController { result.put("error","未找到流信息"); return result; } - cmder.streamByeCmd(serial, code); + cmder.streamByeCmd(serial, code, streamInfo.getStream()); redisCatchStorage.stopPlay(streamInfo); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); return null; diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 5e772365..f383629f 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -30,24 +30,44 @@ spring: poolMaxWait: 5 # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 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 - # username: - # password: - # type: com.alibaba.druid.pool.DruidDataSource - # driver-class-name: com.mysql.cj.jdbc.Driver - name: eiot - url: jdbc:sqlite::resource:wvp.sqlite - username: - password: type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: org.sqlite.JDBC - journal_mode: WAL - synchronous: NORMAL - transaction_mode: IMMEDIATE - max-active: 1 - min-idle: 1 + 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 + username: root + password: root123 + druid: + initialSize: 10 # 连接池初始化连接数 + maxActive: 200 # 连接池最大连接数 + minIdle: 5 # 连接池最小空闲连接数 + maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 + keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。 + validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 + testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 + testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 + testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 + poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小 + timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 + minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒 + filters: stat,wall,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j, 防御sql注入的filter:wall + useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据 + # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000 + #stat-view-servlet.url-pattern: /admin/druid/* + +# druid管理监控页面的一些配置 +rj-druid-manage: + allow: # 访问druid监控页面的IP白名单 + deny: 192.168.1.100 # 访问druid监控页面IP黑名单 + loginUsername: rjAdmin # 访问druid监控页面账号 + loginPassword: rj@2022 # 访问druid监控页面密码 + +#mybatis: +# configuration: +# # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +# # 返回类型为Map,显示null对应的字段 +# call-setters-on-nulls: true +## [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 server: @@ -136,15 +156,8 @@ media: # [可选] 日志配置, 一般不需要改 logging: - file: - name: logs/wvp.log - max-history: 30 - max-size: 10MB - total-size-cap: 300MB - level: - com.genersoft.iot: debug - com.genersoft.iot.vmp.storager.dao: info - com.genersoft.iot.vmp.gb28181: debug + config: classpath:logback-spring-local.xml + # [根据业务需求配置] user-settings: # [可选] 服务ID,不写则为000000 @@ -173,7 +186,7 @@ user-settings: # 是否将日志存储进数据库 logInDatebase: true # 第三方匹配,用于从stream钟获取有效信息 - thirdPartyGBIdReg: [\s\S]* + thirdPartyGBIdReg: "[\\s\\S]*" # 在线文档: swagger-ui(生产环境建议关闭) swagger-ui: diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 55738fbf..dfd7865f 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -16,24 +16,41 @@ spring: password: # [可选] 超时时间 timeout: 10000 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 + # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 + # mysql数据源 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 - username: - password: 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 + username: root + password: root123 + druid: + initialSize: 10 # 连接池初始化连接数 + maxActive: 200 # 连接池最大连接数 + minIdle: 5 # 连接池最小空闲连接数 + maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 + keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。 + validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 + testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 + testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 + testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 + poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小 + timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 + minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒 + filters: stat,wall,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j, 防御sql注入的filter:wall + useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据 + # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000 + #stat-view-servlet.url-pattern: /admin/druid/* -# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 +#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 server: port: 18080 # 作为28181服务器的配置 sip: # [必须修改] 本机的IP - ip: + ip: 192.168.118.70 # [可选] 28181服务监听的端口 port: 5060 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) @@ -48,10 +65,9 @@ sip: #zlm 默认服务器配置 media: - # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId - id: + id: FQ3TF8yT83wh5Wvz # [必须修改] zlm服务器的内网IP - ip: + ip: 192.168.118.70 # [必须修改] zlm服务器的http.port http-port: 80 # [可选] zlm服务器的hook.admin_params=secret @@ -68,25 +84,7 @@ media: record-assist-port: 18081 # [可选] 日志配置, 一般不需要改 logging: - file: - name: logs/wvp.log - max-history: 30 - max-size: 10MB - total-size-cap: 300MB - level: - com.genersoft.iot: debug - com.genersoft.iot.vmp.storager.dao: info - com.genersoft.iot.vmp.gb28181: info - -# [根据业务需求配置] -user-settings: - # 推流直播是否录制 - record-push-live: true - auto-apply-play: false - -# 在线文档: swagger-ui(生产环境建议关闭) -swagger-ui: - enabled: true + config: classpath:logback-spring-local.xml # 版本信息, 不需修改 version: diff --git a/src/main/resources/application-docker.yml b/src/main/resources/application-docker.yml index 96a9ad0c..6487f9a9 100644 --- a/src/main/resources/application-docker.yml +++ b/src/main/resources/application-docker.yml @@ -69,16 +69,9 @@ media: sdp-ip: ${sip.ip} stream-ip: ${sip.ip} # [可选] 日志配置, 一般不需要改 +# [可选] 日志配置, 一般不需要改 logging: - file: - name: logs/wvp.log - max-history: 30 - max-size: 10MB - total-size-cap: 300MB - level: - com.genersoft.iot: debug - com.genersoft.iot.vmp.storager.dao: info - com.genersoft.iot.vmp.gb28181: info + config: classpath:logback-spring-local.xml # [根据业务需求配置] user-settings: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d74c444c..3d7808a0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,3 +1,3 @@ spring: profiles: - active: local + active: dev diff --git a/src/main/resources/logback-spring-local.xml b/src/main/resources/logback-spring-local.xml new file mode 100644 index 00000000..9951c696 --- /dev/null +++ b/src/main/resources/logback-spring-local.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n + + + + + + + + + + ${LOG_HOME}/wvp-%d{yyyy-MM-dd}.%i.log + + 30 + 20MB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n + + + + + DEBUG + + + + + + + + + ${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.log + + 30 + 20MB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n + + + + WARN + + + + + + + + + + ${LOG_HOME}/druid-%d{yyyy-MM-dd}.%i.log + + 30 + 50MB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web_src/src/components/DeviceList.vue b/web_src/src/components/DeviceList.vue index 0dab7465..7922a934 100644 --- a/web_src/src/components/DeviceList.vue +++ b/web_src/src/components/DeviceList.vue @@ -55,14 +55,14 @@ - + @@ -165,15 +165,29 @@ }, deleteDevice: function(row) { - let that = this; - this.$axios({ - method: 'delete', - url:`/api/device/query/devices/${row.deviceId}/delete` - }).then((res)=>{ - this.getDeviceList(); - }).catch((error) =>{ - console.log(error); - }); + let msg = "确定删除此设备?" + if (row.online !== 0) { + msg = "在线设备删除后仍可通过注册再次上线。
如需彻底删除请先将设备离线。
确定删除此设备?" + } + this.$confirm(msg, '提示', { + dangerouslyUseHTMLString : true, + confirmButtonText: '确定', + cancelButtonText: '取消', + center: true, + type: 'warning' + }).then(() => { + this.$axios({ + method: 'delete', + url:`/api/device/query/devices/${row.deviceId}/delete` + }).then((res)=>{ + this.getDeviceList(); + }).catch((error) =>{ + console.log(error); + }); + }).catch(() => { + + }); + }, showChannelList: function(row) { diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 3cd4bc9e..6eae383d 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -28,9 +28,7 @@ - - - + diff --git a/web_src/src/components/dialog/changePassword.vue b/web_src/src/components/dialog/changePassword.vue index a95736f2..23d761e1 100644 --- a/web_src/src/components/dialog/changePassword.vue +++ b/web_src/src/components/dialog/changePassword.vue @@ -75,7 +75,10 @@ export default { isLoging: false, rules: { oldPassword: [{ required: true, validator: validatePass0, trigger: "blur" }], - newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }], + newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, { + pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/, + message: "密码长度在8-20位之间,由字母+数字+特殊字符组成", + },], confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }], }, }; diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 74c14c81..5a080060 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -307,7 +307,7 @@ export default { this.isLoging = false; // this.videoUrl = streamInfo.rtc; this.videoUrl = this.getUrlByStreamInfo(streamInfo); - this.streamId = streamInfo.streamId; + this.streamId = streamInfo.stream; this.app = streamInfo.app; this.mediaServerId = streamInfo.mediaServerId; this.playFromStreamInfo(false, streamInfo) @@ -485,8 +485,9 @@ export default { }).then(function (res) { var streamInfo = res.data; that.app = streamInfo.app; - that.streamId = streamInfo.streamId; + that.streamId = streamInfo.stream; that.mediaServerId = streamInfo.mediaServerId; + that.ssrc = streamInfo.ssrc; that.videoUrl = that.getUrlByStreamInfo(streamInfo); that.recordPlay = true; }); @@ -497,7 +498,7 @@ export default { 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() }); @@ -517,7 +518,7 @@ export default { }).then(function (res) { var streamInfo = res.data; that.app = streamInfo.app; - that.streamId = streamInfo.streamId; + that.streamId = streamInfo.stream; that.mediaServerId = streamInfo.mediaServerId; that.videoUrl = that.getUrlByStreamInfo(streamInfo); that.recordPlay = true; @@ -529,7 +530,7 @@ export default { this.videoUrl = ''; this.$axios({ method: 'get', - url: '/api/download/stop/' + this.deviceId + "/" + this.channelId + url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId }).then(function (res) { if (callback) callback() }); @@ -539,8 +540,6 @@ export default { 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) {}); },