Merge branch 'wvp-28181-2.0' into wvp-28181-2.0

This commit is contained in:
mrjackwang 2022-03-03 19:52:16 +08:00 committed by GitHub
commit e5370bbd6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
87 changed files with 1119 additions and 613 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
# Log file # Log file
*.log *.log
logs/*
# BlueJ files # BlueJ files
*.ctxt *.ctxt

View File

@ -105,6 +105,10 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] WEB端支持播放H264与H265音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 - [X] WEB端支持播放H264与H265音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
# docker快速体验 # 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 ```shell
docker pull 648540858/wvp_pro docker pull 648540858/wvp_pro

13
pom.xml
View File

@ -90,8 +90,8 @@
<!-- druid数据库连接池 --> <!-- druid数据库连接池 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>druid</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.3</version> <version>1.1.22</version>
</dependency> </dependency>
<!-- mysql数据库 --> <!-- mysql数据库 -->
@ -183,6 +183,15 @@
<version>4.9.0</version> <version>4.9.0</version>
</dependency> </dependency>
<!-- okhttp 调试日志 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>4.9.0</version>
</dependency>
<!-- okhttp-digest --> <!-- okhttp-digest -->
<dependency> <dependency>
<groupId>com.burgstaller</groupId> <groupId>com.burgstaller</groupId>

View File

@ -44,7 +44,7 @@ CREATE TABLE `device` (
`charset` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, `charset` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `device_deviceId_uindex` (`deviceId`) 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 */; /*!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 */; /*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */; /*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_channel` ( CREATE TABLE `device_channel` (
`channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `manufacture` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `model` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `owner` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `block` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`parentId` varchar(50) CHARACTER SET utf8mb4 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, `safetyWay` int DEFAULT NULL,
`registerWay` 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, `certifiable` int DEFAULT NULL,
`errCode` int DEFAULT NULL, `errCode` int DEFAULT NULL,
`endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `endTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `secrecy` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `ipAddress` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`port` int 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, `PTZType` int DEFAULT NULL,
`status` int DEFAULT NULL, `status` int DEFAULT NULL,
`longitude` double DEFAULT NULL, `longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL, `latitude` double DEFAULT NULL,
`streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `streamId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `parental` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`hasAudio` bit(1) DEFAULT NULL, `hasAudio` bit(1) DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`subCount` int DEFAULT '0', `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`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -196,7 +198,7 @@ CREATE TABLE `gb_stream` (
PRIMARY KEY (`gbStreamId`) USING BTREE, PRIMARY KEY (`gbStreamId`) USING BTREE,
UNIQUE KEY `app` (`app`,`stream`) USING BTREE, UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
UNIQUE KEY `gbId` (`gbId`) 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 */; /*!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, `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`createTime` 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 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -315,7 +317,7 @@ CREATE TABLE `parent_platform` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `parent_platform_id_uindex` (`id`), UNIQUE KEY `parent_platform_id_uindex` (`id`),
UNIQUE KEY `parent_platform_pk` (`serverGBId`) 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 */; /*!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 */; /*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_gb_channel` ( CREATE TABLE `platform_gb_channel` (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `platformId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `catalogId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `deviceChannelId` int 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,
PRIMARY KEY (`id`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -393,7 +393,7 @@ CREATE TABLE `platform_gb_stream` (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -415,6 +415,7 @@ DROP TABLE IF EXISTS `stream_proxy`;
CREATE TABLE `stream_proxy` ( CREATE TABLE `stream_proxy` (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, `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, `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
`name` 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, `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, `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `stream_push_pk` (`app`,`stream`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -541,4 +542,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!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

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp;
import java.util.logging.LogManager; import java.util.logging.LogManager;
import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletComponentScan;
@ -17,6 +18,7 @@ import springfox.documentation.oas.annotations.EnableOpenApi;
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
@EnableOpenApi @EnableOpenApi
@EnableDruidSupport
public class VManageBootstrap extends LogManager { public class VManageBootstrap extends LogManager {
private static String[] args; private static String[] args;
private static ConfigurableApplicationContext context; private static ConfigurableApplicationContext context;

View File

@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray;
public class StreamInfo { public class StreamInfo {
private String app; private String app;
private String streamId; private String stream;
private String deviceID; private String deviceID;
private String channelId; private String channelId;
private String flv; private String flv;
@ -153,12 +153,12 @@ public class StreamInfo {
this.ws_ts = ws_ts; this.ws_ts = ws_ts;
} }
public String getStreamId() { public String getStream() {
return streamId; return stream;
} }
public void setStreamId(String streamId) { public void setStream(String stream) {
this.streamId = streamId; this.stream = stream;
} }
public String getRtc() { public String getRtc() {

View File

@ -29,6 +29,7 @@ public class VideoManagerConstants {
// 此处多了一个_暂不修改 // 此处多了一个_暂不修改
public static final String PLAYER_PREFIX = "VMP_PLAYER_"; public static final String PLAYER_PREFIX = "VMP_PLAYER_";
public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_"; 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_"; public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";

View File

@ -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.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 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.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@ -30,7 +31,7 @@ public class SipPlatformRunner implements CommandLineRunner {
private EventPublisher publisher; private EventPublisher publisher;
@Autowired @Autowired
private ZLMRTPServerFactory zlmrtpServerFactory; private ISIPCommanderForPlatform sipCommanderForPlatform;
@Override @Override
@ -57,6 +58,9 @@ public class SipPlatformRunner implements CommandLineRunner {
parentPlatformCatch.setId(parentPlatform.getServerGBId()); parentPlatformCatch.setId(parentPlatform.getServerGBId());
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
// 取消订阅
sipCommanderForPlatform.unregister(parentPlatform, null, null);
Thread.sleep(500);
// 发送平台未注册消息 // 发送平台未注册消息
publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId()); publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId());
} }

View File

@ -14,7 +14,7 @@ import springfox.documentation.spring.web.plugins.Docket;
@Configuration @Configuration
public class Swagger3Config { public class Swagger3Config {
@Value("${swagger-ui.enabled}") @Value("${swagger-ui.enabled: true}")
private boolean enable; private boolean enable;
@Bean @Bean

View File

@ -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<Servlet> 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<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}

View File

@ -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 {
}

View File

@ -3,6 +3,10 @@ package com.genersoft.iot.vmp.gb28181.bean;
public class DeviceChannel { public class DeviceChannel {
/**
* 数据库自赠ID
*/
private int id;
/** /**
* 通道id * 通道id
@ -165,6 +169,14 @@ public class DeviceChannel {
*/ */
private boolean hasAudio; private boolean hasAudio;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDeviceId() { public String getDeviceId() {
return deviceId; return deviceId;
} }

View File

@ -4,11 +4,12 @@ public class SsrcTransaction {
private String deviceId; private String deviceId;
private String channelId; private String channelId;
private String ssrc; private String callId;
private String streamId; private String stream;
private byte[] transaction; private byte[] transaction;
private byte[] dialog; private byte[] dialog;
private String mediaServerId; private String mediaServerId;
private String ssrc;
public String getDeviceId() { public String getDeviceId() {
return deviceId; return deviceId;
@ -26,20 +27,20 @@ public class SsrcTransaction {
this.channelId = channelId; this.channelId = channelId;
} }
public String getSsrc() { public String getCallId() {
return ssrc; return callId;
} }
public void setSsrc(String ssrc) { public void setCallId(String callId) {
this.ssrc = ssrc; this.callId = callId;
} }
public String getStreamId() { public String getStream() {
return streamId; return stream;
} }
public void setStreamId(String streamId) { public void setStream(String stream) {
this.streamId = streamId; this.stream = stream;
} }
public byte[] getTransaction() { public byte[] getTransaction() {
@ -65,4 +66,12 @@ public class SsrcTransaction {
public void setMediaServerId(String mediaServerId) { public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId; this.mediaServerId = mediaServerId;
} }
public String getSsrc() {
return ssrc;
}
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
} }

View File

@ -18,15 +18,21 @@ public class SubscribeInfo {
this.fromTag = fromHeader.getTag(); this.fromTag = fromHeader.getTag();
ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME); ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME);
this.expires = expiresHeader.getExpires(); 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 String id;
private int expires; private int expires;
private String callId; private String callId;
private String event; private String eventId;
private String eventType;
private String fromTag; private String fromTag;
private String toTag; private String toTag;
private String branch;
public String getId() { public String getId() {
return id; return id;
@ -68,11 +74,27 @@ public class SubscribeInfo {
this.fromTag = fromTag; this.fromTag = fromTag;
} }
public String getEvent() { public String getEventId() {
return event; return eventId;
} }
public void setEvent(String event) { public void setEventId(String eventId) {
this.event = event; 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;
} }
} }

View File

@ -101,14 +101,14 @@ public class EventPublisher {
applicationEventPublisher.publishEvent(outEvent); applicationEventPublisher.publishEvent(outEvent);
} }
@Async
public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) { public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) {
List<DeviceChannel> deviceChannelList = new ArrayList<>(); List<DeviceChannel> deviceChannelList = new ArrayList<>();
deviceChannelList.add(deviceChannel); deviceChannelList.add(deviceChannel);
catalogEventPublish(platformId, deviceChannelList, type); catalogEventPublish(platformId, deviceChannelList, type);
} }
@Async
public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) { public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) {
CatalogEvent outEvent = new CatalogEvent(this); CatalogEvent outEvent = new CatalogEvent(this);
List<DeviceChannel> channels = new ArrayList<>(); List<DeviceChannel> channels = new ArrayList<>();
@ -130,8 +130,8 @@ public class EventPublisher {
applicationEventPublisher.publishEvent(outEvent); applicationEventPublisher.publishEvent(outEvent);
} }
@Async
public void catalogEventPublishForStream(String platformId, GbStream[] gbStreams, String type) { public void catalogEventPublishForStream(String platformId, List<GbStream> gbStreams, String type) {
CatalogEvent outEvent = new CatalogEvent(this); CatalogEvent outEvent = new CatalogEvent(this);
outEvent.setGbStreams(gbStreams); outEvent.setGbStreams(gbStreams);
outEvent.setType(type); outEvent.setType(type);
@ -139,9 +139,10 @@ public class EventPublisher {
applicationEventPublisher.publishEvent(outEvent); applicationEventPublisher.publishEvent(outEvent);
} }
@Async
public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) { public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) {
GbStream[] gbStreams = {gbStream}; List<GbStream> gbStreamList = new ArrayList<>();
catalogEventPublishForStream(platformId, gbStreams, type); gbStreamList.add(gbStream);
catalogEventPublishForStream(platformId, gbStreamList, type);
} }
} }

View File

@ -23,24 +23,36 @@ public class SipSubscribe {
private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>(); private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
private Map<String, Date> timeSubscribes = new ConcurrentHashMap<>(); private Map<String, Date> okTimeSubscribes = new ConcurrentHashMap<>();
private Map<String, Date> errorTimeSubscribes = new ConcurrentHashMap<>();
// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次 // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
// @Scheduled(fixedRate= 100 * 60 * 60 ) // @Scheduled(fixedRate= 100 * 60 * 60 )
@Scheduled(cron="0 0 * * * ?") //小时执行一次 每个整点 @Scheduled(cron="0 0/5 * * * ?") //5分钟执行一次
public void execute(){ public void execute(){
logger.info("[定时任务] 清理过期的订阅信息"); logger.info("[定时任务] 清理过期的订阅信息");
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date()); calendar.setTime(new Date());
calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) - 1); calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 5);
for (String key : timeSubscribes.keySet()) {
if (timeSubscribes.get(key).before(calendar.getTime())){ for (String key : okTimeSubscribes.keySet()) {
logger.info("[定时任务] 清理过期的订阅信息: {}", key); if (okTimeSubscribes.get(key).before(calendar.getTime())){
errorSubscribes.remove(key); // logger.info("[定时任务] 清理过期的订阅信息: {}", key);
okSubscribes.remove(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 { public interface Event {
@ -105,12 +117,12 @@ public class SipSubscribe {
public void addErrorSubscribe(String key, SipSubscribe.Event event) { public void addErrorSubscribe(String key, SipSubscribe.Event event) {
errorSubscribes.put(key, event); errorSubscribes.put(key, event);
timeSubscribes.put(key, new Date()); errorTimeSubscribes.put(key, new Date());
} }
public void addOkSubscribe(String key, SipSubscribe.Event event) { public void addOkSubscribe(String key, SipSubscribe.Event event) {
okSubscribes.put(key, event); okSubscribes.put(key, event);
timeSubscribes.put(key, new Date()); okTimeSubscribes.put(key, new Date());
} }
public SipSubscribe.Event getErrorSubscribe(String key) { public SipSubscribe.Event getErrorSubscribe(String key) {
@ -119,7 +131,7 @@ public class SipSubscribe {
public void removeErrorSubscribe(String key) { public void removeErrorSubscribe(String key) {
errorSubscribes.remove(key); errorSubscribes.remove(key);
timeSubscribes.remove(key); errorTimeSubscribes.remove(key);
} }
public SipSubscribe.Event getOkSubscribe(String key) { public SipSubscribe.Event getOkSubscribe(String key) {
@ -128,7 +140,7 @@ public class SipSubscribe {
public void removeOkSubscribe(String key) { public void removeOkSubscribe(String key) {
okSubscribes.remove(key); okSubscribes.remove(key);
timeSubscribes.remove(key); okTimeSubscribes.remove(key);
} }
public int getErrorSubscribesSize(){ public int getErrorSubscribesSize(){
return errorSubscribes.size(); return errorSubscribes.size();

View File

@ -20,7 +20,7 @@ public class CatalogEvent extends ApplicationEvent {
public static final String UPDATE = "UPDATE"; // 更新 public static final String UPDATE = "UPDATE"; // 更新
private List<DeviceChannel> deviceChannels; private List<DeviceChannel> deviceChannels;
private GbStream[] gbStreams; private List<GbStream> gbStreams;
private String type; private String type;
private String platformId; private String platformId;
@ -48,11 +48,11 @@ public class CatalogEvent extends ApplicationEvent {
this.platformId = platformId; this.platformId = platformId;
} }
public GbStream[] getGbStreams() { public List<GbStream> getGbStreams() {
return gbStreams; return gbStreams;
} }
public void setGbStreams(GbStream[] gbStreams) { public void setGbStreams(List<GbStream> gbStreams) {
this.gbStreams = gbStreams; this.gbStreams = gbStreams;
} }
} }

View File

@ -60,10 +60,14 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>(); Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
if (event.getPlatformId() != null) { if (event.getPlatformId() != null) {
parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); 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(); String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId();
subscribe = redisCatchStorage.getSubscribe(key); subscribe = redisCatchStorage.getSubscribe(key);
if (subscribe == null) return;
if (subscribe == null) {
logger.debug("发送订阅消息时发现订阅信息已经不存在");
return;
}
}else { }else {
// 获取所用订阅 // 获取所用订阅
List<String> platforms = redisCatchStorage.getAllSubscribePlatform(); List<String> platforms = redisCatchStorage.getAllSubscribePlatform();
@ -94,7 +98,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
if (event.getDeviceChannels() != null) { if (event.getDeviceChannels() != null) {
deviceChannelList.addAll(event.getDeviceChannels()); 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()) { for (GbStream gbStream : event.getGbStreams()) {
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId()); DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId());
deviceChannelList.add(deviceChannelByStream); deviceChannelList.add(deviceChannelByStream);
@ -102,7 +106,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
} }
if (deviceChannelList.size() > 0) { if (deviceChannelList.size() > 0) {
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); 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) { }else if (parentPlatformMap.keySet().size() > 0) {
for (String gbId : parentPlatformMap.keySet()) { for (String gbId : parentPlatformMap.keySet()) {
@ -117,7 +121,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
DeviceChannel deviceChannel = new DeviceChannel(); DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(gbId); deviceChannel.setChannelId(gbId);
deviceChannelList.add(deviceChannel); 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<CatalogEvent> {
if (event.getDeviceChannels() != null) { if (event.getDeviceChannels() != null) {
deviceChannelList.addAll(event.getDeviceChannels()); 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()) { for (GbStream gbStream : event.getGbStreams()) {
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId()); DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId());
deviceChannelList.add(deviceChannelByStream); deviceChannelList.add(deviceChannelByStream);
@ -142,7 +146,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
} }
if (deviceChannelList.size() > 0) { if (deviceChannelList.size() > 0) {
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); 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) { }else if (parentPlatformMap.keySet().size() > 0) {
for (String gbId : parentPlatformMap.keySet()) { for (String gbId : parentPlatformMap.keySet()) {
@ -159,7 +163,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId); GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId);
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform.getDeviceGBId()); DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform.getDeviceGBId());
deviceChannelList.add(deviceChannelByStream); deviceChannelList.add(deviceChannelByStream);
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
} }
} }
} }

View File

@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPDialog;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/** /**
* @description:视频流session管理器管理视频预览预览回放的通信句柄 * @description:视频流session管理器管理视频预览预览回放的通信句柄
@ -29,39 +30,55 @@ public class VideoStreamSessionManager {
@Autowired @Autowired
private UserSetup userSetup; 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 ssrcTransaction = new SsrcTransaction();
ssrcTransaction.setDeviceId(deviceId); ssrcTransaction.setDeviceId(deviceId);
ssrcTransaction.setChannelId(channelId); ssrcTransaction.setChannelId(channelId);
ssrcTransaction.setStreamId(streamId); ssrcTransaction.setStream(stream);
byte[] transactionByteArray = SerializeUtils.serialize(transaction); byte[] transactionByteArray = SerializeUtils.serialize(transaction);
ssrcTransaction.setTransaction(transactionByteArray); ssrcTransaction.setTransaction(transactionByteArray);
ssrcTransaction.setCallId(callId);
ssrcTransaction.setSsrc(ssrc); ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId); 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){ public void put(String deviceId, String channelId, String callId, Dialog dialog){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
if (ssrcTransaction != null) { if (ssrcTransaction != null) {
byte[] dialogByteArray = SerializeUtils.serialize(dialog); byte[] dialogByteArray = SerializeUtils.serialize(dialog);
ssrcTransaction.setDialog(dialogByteArray); 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){ public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) return null; if (ssrcTransaction == null) return null;
byte[] transactionByteArray = ssrcTransaction.getTransaction(); byte[] transactionByteArray = ssrcTransaction.getTransaction();
ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray); ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
return clientTransaction; return clientTransaction;
} }
public SIPDialog getDialog(String deviceId, String channelId){ public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) return null; if (ssrcTransaction == null) return null;
byte[] dialogByteArray = ssrcTransaction.getDialog(); byte[] dialogByteArray = ssrcTransaction.getDialog();
if (dialogByteArray == null) return null; if (dialogByteArray == null) return null;
@ -69,36 +86,37 @@ public class VideoStreamSessionManager {
return dialog; return dialog;
} }
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){ public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId); if (StringUtils.isEmpty(callId)) callId ="*";
return ssrcTransaction; if (StringUtils.isEmpty(stream)) stream ="*";
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
List<Object> 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){ public String getMediaServerId(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) return null;
return ssrcTransaction.getStreamId();
}
public String getMediaServerId(String deviceId, String channelId){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return null; if (ssrcTransaction == null) return null;
return ssrcTransaction.getMediaServerId(); return ssrcTransaction.getMediaServerId();
} }
public String getSSRC(String deviceId, String channelId){ public String getSSRC(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) return null; if (ssrcTransaction == null) return null;
return ssrcTransaction.getSsrc(); return ssrcTransaction.getSsrc();
} }
public void remove(String deviceId, String channelId) { public void remove(String deviceId, String channelId, String stream) {
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) return; 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<SsrcTransaction> getAllSsrc() { public List<SsrcTransaction> getAllSsrc() {
List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" )); List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
List<SsrcTransaction> result= new ArrayList<>(); List<SsrcTransaction> result= new ArrayList<>();
for (int i = 0; i < ssrcTransactionKeys.size(); i++) { for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
String key = (String)ssrcTransactionKeys.get(i); String key = (String)ssrcTransactionKeys.get(i);

View File

@ -73,6 +73,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
@Override @Override
@Async @Async
public void processRequest(RequestEvent requestEvent) { public void processRequest(RequestEvent requestEvent) {
logger.debug("\n收到请求\n{}", requestEvent.getRequest());
String method = requestEvent.getRequest().getMethod(); String method = requestEvent.getRequest().getMethod();
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
if (sipRequestProcessor == null) { if (sipRequestProcessor == null) {
@ -90,9 +91,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
@Override @Override
@Async @Async
public void processResponse(ResponseEvent responseEvent) { public void processResponse(ResponseEvent responseEvent) {
logger.debug(responseEvent.getResponse().toString());
Response response = responseEvent.getResponse(); Response response = responseEvent.getResponse();
logger.debug(responseEvent.getResponse().toString()); logger.debug("\n收到响应\n{}", responseEvent.getResponse());
int status = response.getStatusCode(); int status = response.getStatusCode();
if (((status >= 200) && (status < 300)) || status == 401) { // Success! if (((status >= 200) && (status < 300)) || status == 401) { // Success!
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
@ -107,8 +107,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
if (subscribe != null) { if (subscribe != null) {
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
subscribe.response(eventResult);
sipSubscribe.removeOkSubscribe(callIdHeader.getCallId()); sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
subscribe.response(eventResult);
} }
} }
} }

View File

@ -119,8 +119,8 @@ public interface ISIPCommander {
/** /**
* 视频流停止 * 视频流停止
*/ */
void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent); void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent);
void streamByeCmd(String deviceId, String channelId); void streamByeCmd(String deviceId, String channelId, String stream);
/** /**
* 回放暂停 * 回放暂停

View File

@ -17,7 +17,7 @@ public interface ISIPCommanderForPlatform {
* @return * @return
*/ */
boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); 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 parentPlatform
* @param deviceChannels * @param deviceChannels
*/ */
boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo); boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
/** /**
* 回复catalog事件-删除 * 回复catalog事件-删除
* @param parentPlatform * @param parentPlatform
* @param deviceChannels * @param deviceChannels
*/ */
boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo); boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
} }

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.MessageFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired; 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); 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 realm = www.getRealm();
String nonce = www.getNonce(); String nonce = www.getNonce();
String scheme = www.getScheme(); String scheme = www.getScheme();
@ -138,7 +147,6 @@ public class SIPRequestHeaderPlarformProvider {
callIdHeader.setCallId(callId); callIdHeader.setCallId(callId);
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
String cNonce = null; String cNonce = null;
String nc = "00000001"; String nc = "00000001";
if (qop != null) { if (qop != null) {
@ -223,30 +231,30 @@ public class SIPRequestHeaderPlarformProvider {
UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
request.addHeader(userAgentHeader); request.addHeader(userAgentHeader);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
request.setContent(content, contentTypeHeader); request.setContent(content, contentTypeHeader);
return request; 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; Request request = null;
// sipuri // sipuri
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
// via // via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
parentPlatform.getTransport(), null); parentPlatform.getTransport(), subscribeInfo.getBranch());
viaHeader.setRPort(); viaHeader.setRPort();
viaHeaders.add(viaHeader); viaHeaders.add(viaHeader);
// from // from
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getToTag());
// to // to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag());
// Forwards // Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
@ -262,7 +270,22 @@ public class SIPRequestHeaderPlarformProvider {
UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
request.addHeader(userAgentHeader); 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); request.setContent(content, contentTypeHeader);
return request; return request;
} }

View File

@ -67,7 +67,7 @@ public class SIPRequestHeaderProvider {
request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwards); toHeader, viaHeaders, maxForwards);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
request.setContent(content, contentTypeHeader); request.setContent(content, contentTypeHeader);
return request; return request;
} }
@ -217,7 +217,7 @@ public class SIPRequestHeaderProvider {
EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
request.addHeader(eventHeader); request.addHeader(eventHeader);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
request.setContent(content, contentTypeHeader); request.setContent(content, contentTypeHeader);
return request; return request;
} }
@ -226,7 +226,7 @@ public class SIPRequestHeaderProvider {
throws PeerUnavailableException, ParseException, InvalidArgumentException { throws PeerUnavailableException, ParseException, InvalidArgumentException {
Request request = null; Request request = null;
if (streamInfo == null) return 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(), SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
device.getHostAddress()); device.getHostAddress());

View File

@ -331,7 +331,7 @@ public class SIPCommander implements ISIPCommander {
*/ */
@Override @Override
public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { 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 { try {
if (device == null) return; if (device == null) return;
String streamMode = device.getStreamMode().toUpperCase(); String streamMode = device.getStreamMode().toUpperCase();
@ -404,6 +404,8 @@ public class SIPCommander implements ISIPCommander {
} }
content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc 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()); 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); Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
String finalStreamId = streamId;
transmitRequest(device, request, (e -> { transmitRequest(device, request, (e -> {
streamSession.remove(device.getDeviceId(), channelId); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
errorEvent.response(e); errorEvent.response(e);
}), e ->{ }), e ->{
streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction()); // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
streamSession.put(device.getDeviceId(), channelId , e.dialog); 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) { , SipSubscribe.Event errorEvent) {
try { 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(); JSONObject subscribeKey = new JSONObject();
subscribeKey.put("app", "rtp"); subscribeKey.put("app", "rtp");
subscribeKey.put("stream", ssrcInfo.getStreamId()); subscribeKey.put("stream", ssrcInfo.getStream());
subscribeKey.put("regist", true); subscribeKey.put("regist", true);
subscribeKey.put("mediaServerId", mediaServerItem.getId()); subscribeKey.put("mediaServerId", mediaServerItem.getId());
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
@ -466,8 +468,6 @@ public class SIPCommander implements ISIPCommander {
content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" " content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
String streamMode = device.getStreamMode().toUpperCase(); String streamMode = device.getStreamMode().toUpperCase();
if (userSetup.isSeniorSdp()) { if (userSetup.isSeniorSdp()) {
@ -527,8 +527,8 @@ public class SIPCommander implements ISIPCommander {
transmitRequest(device, request, errorEvent, okEvent -> { transmitRequest(device, request, errorEvent, okEvent -> {
ResponseEvent responseEvent = (ResponseEvent) okEvent.event; ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), responseEvent.getClientTransaction()); streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction());
streamSession.put(device.getDeviceId(), channelId, okEvent.dialog); streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
}); });
} catch ( SipException | ParseException | InvalidArgumentException e) { } catch ( SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace(); 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 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
, SipSubscribe.Event errorEvent) { , SipSubscribe.Event errorEvent) {
try { 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(); JSONObject subscribeKey = new JSONObject();
subscribeKey.put("app", "rtp"); subscribeKey.put("app", "rtp");
subscribeKey.put("stream", ssrcInfo.getStreamId()); subscribeKey.put("stream", ssrcInfo.getStream());
subscribeKey.put("regist", true); subscribeKey.put("regist", true);
subscribeKey.put("mediaServerId", mediaServerItem.getId()); subscribeKey.put("mediaServerId", mediaServerItem.getId());
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); 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()); Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
ClientTransaction transaction = transmitRequest(device, request, errorEvent); 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) { } catch ( SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace(); e.printStackTrace();
@ -645,17 +646,17 @@ public class SIPCommander implements ISIPCommander {
* 视频流停止, 不使用回调 * 视频流停止, 不使用回调
*/ */
@Override @Override
public void streamByeCmd(String deviceId, String channelId) { public void streamByeCmd(String deviceId, String channelId, String stream) {
streamByeCmd(deviceId, channelId, null); streamByeCmd(deviceId, channelId, stream, null);
} }
/** /**
* 视频流停止 * 视频流停止
*/ */
@Override @Override
public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) { public void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent) {
try { try {
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId); ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream);
if (transaction == null) { if (transaction == null) {
logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId); logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>(); SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
@ -664,7 +665,7 @@ public class SIPCommander implements ISIPCommander {
} }
return; return;
} }
SIPDialog dialog = streamSession.getDialog(deviceId, channelId); SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, stream);
if (dialog == null) { if (dialog == null) {
logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId); logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
return; return;
@ -708,11 +709,11 @@ public class SIPCommander implements ISIPCommander {
dialog.sendRequest(clientTransaction); dialog.sendRequest(clientTransaction);
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId); SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callIdHeader.getCallId(), null);
if (ssrcTransaction != null) { if (ssrcTransaction != null) {
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId()); MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
streamSession.remove(deviceId, channelId); streamSession.remove(deviceId, channelId, ssrcTransaction.getStream());
} }
} catch (SipException | ParseException e) { } catch (SipException | ParseException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -32,21 +32,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class); private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class);
// @Autowired
// private SipConfig sipConfig;
// @Autowired
// private SIPRequestHeaderProvider headerProvider;
@Autowired @Autowired
private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider; private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider;
// @Autowired
// private VideoStreamSessionManager streamSession;
// @Autowired
// private IVideoManagerStorager storager;
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@ -65,7 +53,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
@Override @Override
public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { 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 @Override
@ -77,15 +65,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
} }
return register(parentPlatform, null, null, errorEvent, okEvent); return register(parentPlatform, null, null, errorEvent, okEvent, false);
} }
@Override @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 { try {
Request request = null; Request request = null;
String tm = Long.toString(System.currentTimeMillis()); String tm = Long.toString(System.currentTimeMillis());
if (www == null ) { if (!registerAgain ) {
// //callid // //callid
CallIdHeader callIdHeader = null; CallIdHeader callIdHeader = null;
if(parentPlatform.getTransport().equals("TCP")) { 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 { 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())) { if("TCP".equals(parentPlatform.getTransport())) {
tcpSipProvider.sendRequest(request); tcpSipProvider.sendRequest(request);
@ -223,7 +213,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n"); catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParentId() != null) {
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n"); catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
@ -358,7 +350,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
String tm = Long.toString(System.currentTimeMillis()); 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); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) { } catch (SipException | ParseException | InvalidArgumentException e) {
@ -369,65 +363,82 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
@Override @Override
public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) { public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
return false; return false;
} }
for (DeviceChannel channel : deviceChannels) { if (index == null) {
index = 0;
}
try { try {
StringBuffer catalogXml = new StringBuffer(600); if (index > deviceChannels.size() - 1) {
catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); return true;
catalogXml.append("<Notify>\r\n"); }
catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); Request request = getCatalogNotifyRequestForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo);
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); index += 1;
catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n"); Integer finalIndex = index;
catalogXml.append("<DeviceList Num=\"1\">\r\n"); transmitRequest(parentPlatform, request, null, (eventResult -> {
catalogXml.append("<Item>\r\n"); sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex);
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); }));
catalogXml.append("<Event>" + type + "</Event>\r\n"); } catch (SipException | ParseException | InvalidArgumentException e) {
catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); e.printStackTrace();
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n"); return false;
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n"); }
catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n"); return true;
catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); }
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n"); private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type,
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException,
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); PeerUnavailableException {
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo);
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
catalogXml.append("<Info>\r\n");
catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
catalogXml.append("</Info>\r\n");
catalogXml.append("</Item>\r\n");
catalogXml.append("</DeviceList>\r\n");
catalogXml.append("</Notify>\r\n");
CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
callIdHeader.setCallId(subscribeInfo.getCallId()); callIdHeader.setCallId(subscribeInfo.getCallId());
Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent,
String tm = Long.toString(System.currentTimeMillis()); callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);
return request;
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();
} }
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());
} }
return true; catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
catalogXml.append("<Notify>\r\n");
catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
catalogXml.append("<SumNum>1</SumNum>\r\n");
catalogXml.append("<DeviceList Num=\"1\">\r\n");
catalogXml.append("<Item>\r\n");
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
catalogXml.append("<Owner>0</Owner>\r\n");
catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParentId() != null) {
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
if (!"presence".equals(subscribeInfo.getEventType())) {
catalogXml.append("<Event>" + type + "</Event>\r\n");
}
catalogXml.append("</Item>\r\n");
catalogXml.append("</DeviceList>\r\n");
catalogXml.append("</Notify>\r\n");
return catalogXml.toString();
} }
@Override @Override
public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) { public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
if (parentPlatform == null if (parentPlatform == null
|| deviceChannels == null || deviceChannels == null
|| deviceChannels.size() == 0 || deviceChannels.size() == 0
@ -435,14 +446,47 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return false; return false;
} }
for (DeviceChannel channel : deviceChannels) { if (index == null) {
index = 0;
}
if (index > deviceChannels.size() - 1) {
return true;
}
try { 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); StringBuffer catalogXml = new StringBuffer(600);
catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
catalogXml.append("<Notify>\r\n"); catalogXml.append("<Notify>\r\n");
catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n"); catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
catalogXml.append("<SumNum>1</SumNum>\r\n");
catalogXml.append("<DeviceList Num=\"1\">\r\n"); catalogXml.append("<DeviceList Num=\"1\">\r\n");
catalogXml.append("<Item>\r\n"); catalogXml.append("<Item>\r\n");
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
@ -450,24 +494,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("</Item>\r\n"); catalogXml.append("</Item>\r\n");
catalogXml.append("</DeviceList>\r\n"); catalogXml.append("</DeviceList>\r\n");
catalogXml.append("</Notify>\r\n"); catalogXml.append("</Notify>\r\n");
return catalogXml.toString();
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();
}
}
return true;
} }
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request; 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.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
@ -160,13 +161,18 @@ public abstract class SIPRequestProcessorParent {
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws ParseException * @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()); Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
SipFactory sipFactory = SipFactory.getInstance(); SipFactory sipFactory = SipFactory.getInstance();
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
response.setContent(sdp, contentTypeHeader); response.setContent(sdp, contentTypeHeader);
// 兼容国标中的使用编码@域名作为RequestURI的情况
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); 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( Address concatAddress = sipFactory.createAddressFactory().createAddress(
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
@ -183,13 +189,18 @@ public abstract class SIPRequestProcessorParent {
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws ParseException * @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()); Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
SipFactory sipFactory = SipFactory.getInstance(); SipFactory sipFactory = SipFactory.getInstance();
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
response.setContent(xml, contentTypeHeader); response.setContent(xml, contentTypeHeader);
// 兼容国标中的使用编码@域名作为RequestURI的情况
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); 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( Address concatAddress = sipFactory.createAddressFactory().createAddress(
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()

View File

@ -72,10 +72,10 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
if (deviceId == null) { if (deviceId == null) {
streamInfo = new StreamInfo(); streamInfo = new StreamInfo();
streamInfo.setApp(sendRtpItem.getApp()); streamInfo.setApp(sendRtpItem.getApp());
streamInfo.setStreamId(sendRtpItem.getStreamId()); streamInfo.setStream(sendRtpItem.getStreamId());
}else { }else {
streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
sendRtpItem.setStreamId(streamInfo.getStreamId()); sendRtpItem.setStreamId(streamInfo.getStream());
streamInfo.setApp("rtp"); streamInfo.setApp("rtp");
} }
@ -85,7 +85,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
Map<String, Object> param = new HashMap<>(); Map<String, Object> param = new HashMap<>();
param.put("vhost","__defaultVhost__"); param.put("vhost","__defaultVhost__");
param.put("app",streamInfo.getApp()); param.put("app",streamInfo.getApp());
param.put("stream",streamInfo.getStreamId()); param.put("stream",streamInfo.getStream());
param.put("ssrc", sendRtpItem.getSsrc()); param.put("ssrc", sendRtpItem.getSsrc());
param.put("dst_url",sendRtpItem.getIp()); param.put("dst_url",sendRtpItem.getIp());
param.put("dst_port", sendRtpItem.getPort()); param.put("dst_port", sendRtpItem.getPort());
@ -98,21 +98,21 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
try { try {
if (System.currentTimeMillis() - startTime < 30 * 1000) { if (System.currentTimeMillis() - startTime < 30 * 1000) {
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStream())) {
rtpPushed = true; rtpPushed = true;
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); streamInfo.getApp() ,streamInfo.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
} else { } else {
logger.info("等待设备推流[{}/{}].......", logger.info("等待设备推流[{}/{}].......",
streamInfo.getApp() ,streamInfo.getStreamId()); streamInfo.getApp() ,streamInfo.getStream());
Thread.sleep(1000); Thread.sleep(1000);
continue; continue;
} }
} else { } else {
rtpPushed = true; rtpPushed = true;
logger.info("设备推流[{}/{}]超时,终止向上级推流", logger.info("设备推流[{}/{}]超时,终止向上级推流",
streamInfo.getApp() ,streamInfo.getStreamId()); streamInfo.getApp() ,streamInfo.getStream());
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -89,18 +89,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
logger.info(streamId + "无其它观看者,通知设备停止推流"); logger.info(streamId + "无其它观看者,通知设备停止推流");
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId);
} }
} }
// 可能是设备主动停止 // 可能是设备主动停止
Device device = storager.queryVideoDeviceByChannelId(platformGbId); Device device = storager.queryVideoDeviceByChannelId(platformGbId);
if (device != null) { if (device != null) {
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
if (streamInfo != null) { if (streamInfo != null) {
redisCatchStorage.stopPlay(streamInfo); redisCatchStorage.stopPlay(streamInfo);
} }
storager.stopPlay(device.getDeviceId(), channelId); storager.stopPlay(device.getDeviceId(), channelId);
mediaServerService.closeRTPServer(device, channelId); mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
} }
} }
} catch (SipException e) { } catch (SipException e) {

View File

@ -252,7 +252,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
content.append("f=\r\n"); content.append("f=\r\n");
try { try {
responseSdpAck(evt, content.toString()); responseSdpAck(evt, content.toString(), platform);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -309,7 +309,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
content.append("f=\r\n"); content.append("f=\r\n");
try { try {
responseSdpAck(evt, content.toString()); responseSdpAck(evt, content.toString(), platform);
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.bean.CmdType; 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.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask; import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
@ -105,9 +106,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
logger.info("processRequest serverTransactionId is null."); logger.info("processRequest serverTransactionId is null.");
} }
} }
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
} catch (SipException e) { } catch (SipException e) {
@ -155,7 +153,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
try { 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); ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
subscribeInfo.setToTag(toHeader.getTag()); subscribeInfo.setToTag(toHeader.getTag());
redisCatchStorage.updateSubscribe(key, subscribeInfo); redisCatchStorage.updateSubscribe(key, subscribeInfo);
@ -196,7 +195,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
} }
try { 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); ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
subscribeInfo.setToTag(toHeader.getTag()); subscribeInfo.setToTag(toHeader.getTag());
redisCatchStorage.updateSubscribe(key, subscribeInfo); redisCatchStorage.updateSubscribe(key, subscribeInfo);

View File

@ -22,7 +22,7 @@ import org.springframework.util.StringUtils;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
@Component @Component
public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@ -105,6 +105,11 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
storager.insertMobilePosition(mobilePosition); storager.insertMobilePosition(mobilePosition);
} }
} }
if (!StringUtils.isEmpty(deviceAlarm.getDeviceId())) {
if (deviceAlarm.getAlarmMethod().equals("5")) {
deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));
}
}
logger.debug("存储报警信息、报警分类"); logger.debug("存储报警信息、报警分类");
// 存储报警信息报警分类 // 存储报警信息报警分类
deviceAlarmService.add(deviceAlarm); deviceAlarmService.add(deviceAlarm);

View File

@ -72,6 +72,9 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId()); List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
if (catalogs.size() > 0) { if (catalogs.size() > 0) {
for (PlatformCatalog catalog : catalogs) { for (PlatformCatalog catalog : catalogs) {
if (catalog.getParentId().equals(catalog.getPlatformId())) {
catalog.setParentId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = new DeviceChannel(); DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(catalog.getId()); deviceChannel.setChannelId(catalog.getId());
deviceChannel.setName(catalog.getName()); deviceChannel.setName(catalog.getName());
@ -83,30 +86,35 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
deviceChannel.setParental(1); deviceChannel.setParental(1);
deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(config.getDomain()); deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setSecrecy("0"); deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快 // 防止发送过快
Thread.sleep(50); Thread.sleep(100);
} }
} }
// 回复级联的通道 // 回复级联的通道
if (channelReduces.size() > 0) { if (channelReduces.size() > 0) {
for (ChannelReduce channelReduce : channelReduces) { for (ChannelReduce channelReduce : channelReduces) {
if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) {
channelReduce.setCatalogId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
deviceChannel.setParental(0); deviceChannel.setParental(0);
deviceChannel.setParentId(channelReduce.getCatalogId()); deviceChannel.setParentId(channelReduce.getCatalogId());
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快 // 防止发送过快
Thread.sleep(50); Thread.sleep(100);
} }
} }
// 回复直播的通道 // 回复直播的通道
if (gbStreams.size() > 0) { if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) { for (GbStream gbStream : gbStreams) {
if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
gbStream.setCatalogId(null);
}
DeviceChannel deviceChannel = new DeviceChannel(); DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(gbStream.getGbId()); deviceChannel.setChannelId(gbStream.getGbId());
deviceChannel.setName(gbStream.getName()); deviceChannel.setName(gbStream.getName());
@ -117,14 +125,14 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setParentId(gbStream.getCatalogId()); deviceChannel.setParentId(gbStream.getCatalogId());
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(config.getDomain()); deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0); deviceChannel.setParental(0);
deviceChannel.setSecrecy("0"); deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快 // 防止发送过快
Thread.sleep(50); Thread.sleep(100);
} }
} }
if (size == 0) { if (size == 0) {

View File

@ -68,6 +68,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
} }
if (device.getPort() != rPort) { if (device.getPort() != rPort) {
device.setPort(rPort); device.setPort(rPort);
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
videoManagerStorager.updateDevice(device); videoManagerStorager.updateDevice(device);
redisCatchStorage.updateDevice(device); redisCatchStorage.updateDevice(device);
} }

View File

@ -62,7 +62,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*"); StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*");
if (streamInfo != null) { if (streamInfo != null) {
redisCatchStorage.stopPlayback(streamInfo); redisCatchStorage.stopPlayback(streamInfo);
cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId()); cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
} }
} }
} }

View File

@ -75,6 +75,9 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
int size = catalogs.size() + channelReduces.size() + gbStreams.size(); int size = catalogs.size() + channelReduces.size() + gbStreams.size();
if (catalogs.size() > 0) { if (catalogs.size() > 0) {
for (PlatformCatalog catalog : catalogs) { for (PlatformCatalog catalog : catalogs) {
if (catalog.getParentId().equals(parentPlatform.getServerGBId())) {
catalog.setParentId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = new DeviceChannel(); DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(catalog.getId()); deviceChannel.setChannelId(catalog.getId());
deviceChannel.setName(catalog.getName()); deviceChannel.setName(catalog.getName());
@ -86,30 +89,35 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
deviceChannel.setParental(1); deviceChannel.setParental(1);
deviceChannel.setParentId(catalog.getParentId()); deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(config.getDomain()); deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setSecrecy("0"); deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快 // 防止发送过快
Thread.sleep(50); Thread.sleep(100);
} }
} }
// 回复级联的通道 // 回复级联的通道
if (channelReduces.size() > 0) { if (channelReduces.size() > 0) {
for (ChannelReduce channelReduce : channelReduces) { for (ChannelReduce channelReduce : channelReduces) {
if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) {
channelReduce.setCatalogId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
// TODO 目前暂时认为这里只用通道没有目录
deviceChannel.setParental(0); deviceChannel.setParental(0);
deviceChannel.setParentId(channelReduce.getCatalogId()); deviceChannel.setParentId(channelReduce.getCatalogId());
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快 // 防止发送过快
Thread.sleep(50); Thread.sleep(100);
} }
} }
// 回复直播的通道 // 回复直播的通道
if (gbStreams.size() > 0) { if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) { for (GbStream gbStream : gbStreams) {
if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
gbStream.setCatalogId(parentPlatform.getDeviceGBId());
}
DeviceChannel deviceChannel = new DeviceChannel(); DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(gbStream.getGbId()); deviceChannel.setChannelId(gbStream.getGbId());
deviceChannel.setName(gbStream.getName()); deviceChannel.setName(gbStream.getName());
@ -120,7 +128,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setParentId(gbStream.getCatalogId()); deviceChannel.setParentId(gbStream.getCatalogId());
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(config.getDomain()); deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0); deviceChannel.setParental(0);
@ -128,7 +136,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快 // 防止发送过快
Thread.sleep(50); Thread.sleep(100);
} }
} }
if (size == 0) { if (size == 0) {

View File

@ -78,7 +78,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
if (response.getStatusCode() == 401) { if (response.getStatusCode() == 401) {
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); 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){ }else if (response.getStatusCode() == 200){
// 注册/注销成功 // 注册/注销成功
logger.info(String.format("%s %s成功", platformGBId, action)); logger.info(String.format("%s %s成功", platformGBId, action));

View File

@ -191,7 +191,7 @@ public class XmlUtil {
String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : ""; String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : "";
deviceChannel.setChannelId(channelId); deviceChannel.setChannelId(channelId);
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 // 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); deviceChannel.setStatus(1);
} }
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
@ -255,9 +255,14 @@ public class XmlUtil {
} else { } else {
deviceChannel.setLatitude(0.00); deviceChannel.setLatitude(0.00);
} }
if (XmlUtil.getText(itemDevice, "PTZType") == null if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
|| XmlUtil.getText(itemDevice, "PTZType") == "") { //兼容INFO中的信息
Element info = itemDevice.element("Info");
if(XmlUtil.getText(info, "PTZType") == null || "".equals(XmlUtil.getText(info, "PTZType"))){
deviceChannel.setPTZType(0); deviceChannel.setPTZType(0);
}else{
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(info, "PTZType")));
}
} else { } else {
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
} }

View File

@ -361,6 +361,9 @@ public class ZLMHttpHookListener {
if (mediaServerItem != null){ if (mediaServerItem != null){
if (regist) { if (regist) {
StreamPushItem streamPushItem = null; StreamPushItem streamPushItem = null;
StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks);
item.setStreamInfo(streamInfoByAppAndStream);
redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item); redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|| item.getOriginType() == OriginType.RTMP_PUSH.ordinal() || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
@ -378,7 +381,7 @@ public class ZLMHttpHookListener {
} }
} }
if (gbStreams.size() > 0) { if (gbStreams.size() > 0) {
eventPublisher.catalogEventPublishForStream(null, gbStreams.toArray(new GbStream[0]), CatalogEvent.ON); eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON);
} }
}else { }else {
@ -439,14 +442,16 @@ public class ZLMHttpHookListener {
if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) { if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
ret.put("close", false); ret.put("close", false);
} else { } else {
cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
streamInfoForPlayCatch.getStream());
redisCatchStorage.stopPlay(streamInfoForPlayCatch); redisCatchStorage.stopPlay(streamInfoForPlayCatch);
storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
} }
}else{ }else{
StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId); StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId);
if (streamInfoForPlayBackCatch != null) { if (streamInfoForPlayBackCatch != null) {
cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId()); cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(),
streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream());
redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch); redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch);
}else { }else {
StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId); StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId);

View File

@ -91,6 +91,7 @@ public class ZLMHttpHookSubscribe {
} }
} }
if (null != result && result){ if (null != result && result){
// TODO 报错未处理
iterator.remove(); iterator.remove();
} }
} }

View File

@ -122,7 +122,6 @@ public class ZLMMediaListManager {
transform.setName(thirdPartyGB.getName()); transform.setName(thirdPartyGB.getName());
} }
} }
storager.updateMedia(transform);
if (!StringUtils.isEmpty(transform.getGbId())) { if (!StringUtils.isEmpty(transform.getGbId())) {
// 如果这个国标ID已经给了其他推流且流已离线则移除其他推流 // 如果这个国标ID已经给了其他推流且流已离线则移除其他推流
List<GbStream> gbStreams = gbStreamMapper.selectByGBId(transform.getGbId()); List<GbStream> 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); gbStreamMapper.update(transform);
}else { }else {
transform.setCreateStamp(System.currentTimeMillis()); transform.setCreateStamp(System.currentTimeMillis());
gbStreamMapper.add(transform); gbStreamMapper.add(transform);
} }
} }
storager.updateMedia(transform);
return transform; return transform;
} }

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import okhttp3.*; import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -25,8 +26,23 @@ public class ZLMRESTfulUtils {
void run(JSONObject response); 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<String, Object> param, RequestCallback callback) { public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
OkHttpClient client = new OkHttpClient(); OkHttpClient client = getClient();
if (mediaServerItem == null) { if (mediaServerItem == null) {
return null; return null;
} }

View File

@ -92,6 +92,7 @@ public class ZLMRunner implements CommandLineRunner {
// 获取所有的zlm 并开启主动连接 // 获取所有的zlm 并开启主动连接
List<MediaServerItem> all = mediaServerService.getAllFromDatabase(); List<MediaServerItem> all = mediaServerService.getAllFromDatabase();
mediaServerService.updateVmServer(all);
if (all.size() == 0) { if (all.size() == 0) {
all.add(mediaConfig.getMediaSerItem()); all.add(mediaConfig.getMediaSerItem());
} }

View File

@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.media.zlm.dto; package com.genersoft.iot.vmp.media.zlm.dto;
import com.genersoft.iot.vmp.common.StreamInfo;
import java.util.List; import java.util.List;
public class MediaItem { public class MediaItem {
@ -281,6 +283,8 @@ public class MediaItem {
} }
} }
private StreamInfo streamInfo;
public String getApp() { public String getApp() {
return app; return app;
} }
@ -402,4 +406,12 @@ public class MediaItem {
public void setMediaServerId(String mediaServerId) { public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId; this.mediaServerId = mediaServerId;
} }
public StreamInfo getStreamInfo() {
return streamInfo;
}
public void setStreamInfo(StreamInfo streamInfo) {
this.streamInfo = streamInfo;
}
} }

View File

@ -42,11 +42,13 @@ public interface IMediaServerService {
void setZLMConfig(MediaServerItem mediaServerItem, boolean restart); void setZLMConfig(MediaServerItem mediaServerItem, boolean restart);
void updateVmServer(List<MediaServerItem> mediaServerItemList);
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId); SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback); 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); void clearRTPServer(MediaServerItem mediaServerItem);
@ -74,6 +76,8 @@ public interface IMediaServerService {
void delete(String id); void delete(String id);
void deleteDb(String id);
MediaServerItem getDefaultMediaServer(); MediaServerItem getDefaultMediaServer();
void updateMediaServerKeepalive(String mediaServerId, JSONObject data); void updateMediaServerKeepalive(String mediaServerId, JSONObject data);

View File

@ -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.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 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 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 { 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); 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); 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); MediaServerItem getNewMediaServerItem(Device device);
void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString); void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString);
DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback errorCallBack);
} }

View File

@ -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);
}

View File

@ -4,12 +4,12 @@ public class SSRCInfo {
private int port; private int port;
private String ssrc; 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.port = port;
this.ssrc = ssrc; this.ssrc = ssrc;
StreamId = streamId; Stream = stream;
} }
public int getPort() { public int getPort() {
@ -28,11 +28,11 @@ public class SSRCInfo {
this.ssrc = ssrc; this.ssrc = ssrc;
} }
public String getStreamId() { public String getStream() {
return StreamId; return Stream;
} }
public void setStreamId(String streamId) { public void setStream(String stream) {
StreamId = streamId; Stream = stream;
} }
} }

View File

@ -103,7 +103,7 @@ public class GbStreamServiceImpl implements IGbStreamService {
deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId);
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(sipConfig.getDomain()); deviceChannel.setCivilCode(sipConfig.getDomain().substring(0, sipConfig.getDomain().length() - 2));
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0); deviceChannel.setParental(0);

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.VideoManagerConstants; 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.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -45,8 +46,7 @@ import java.util.*;
* 媒体服务器节点管理 * 媒体服务器节点管理
*/ */
@Service @Service
@Order(value=2) public class MediaServerServiceImpl implements IMediaServerService {
public class MediaServerServiceImpl implements IMediaServerService, CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
@ -101,9 +101,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
* 初始化 * 初始化
*/ */
@Override @Override
public void run(String... args) throws Exception { public void updateVmServer(List<MediaServerItem> mediaServerItemList) {
logger.info("[缓存初始化] Media Server "); logger.info("[缓存初始化] Media Server ");
List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
for (MediaServerItem mediaServerItem : mediaServerItemList) { for (MediaServerItem mediaServerItem : mediaServerItemList) {
if (StringUtils.isEmpty(mediaServerItem.getId())) { if (StringUtils.isEmpty(mediaServerItem.getId())) {
continue; continue;
@ -161,15 +160,16 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
} }
@Override @Override
public void closeRTPServer(Device device, String channelId) { public void closeRTPServer(Device device, String channelId, String stream) {
String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId); String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId, stream);
String ssrc = streamSession.getSSRC(device.getDeviceId(), channelId, stream);
MediaServerItem mediaServerItem = this.getOne(mediaServerId); MediaServerItem mediaServerItem = this.getOne(mediaServerId);
if (mediaServerItem != null) { if (mediaServerItem != null) {
String streamId = String.format("%s_%s", device.getDeviceId(), channelId); String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId); 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 @Override
@ -223,7 +223,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
String key = (String) mediaServerKey; String key = (String) mediaServerKey;
MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key); 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); mediaServerItem.setStatus(true);
} }
result.add(mediaServerItem); result.add(mediaServerItem);
@ -278,6 +279,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
@Override @Override
public MediaServerItem getDefaultMediaServer() { public MediaServerItem getDefaultMediaServer() {
return mediaServerMapper.queryDefault(); return mediaServerMapper.queryDefault();
} }
@ -607,6 +609,11 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + id; String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + id;
redisUtil.del(key); redisUtil.del(key);
} }
@Override
public void deleteDb(String id){
//同步删除数据库中的数据
mediaServerMapper.delOne(id);
}
@Override @Override
public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) { public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) {

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo; 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.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; 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.MediaServerItem;
@ -26,6 +27,10 @@ public class MediaServiceImpl implements IMediaService {
@Autowired @Autowired
private IMediaServerService mediaServerService; private IMediaServerService mediaServerService;
@Autowired
private MediaConfig mediaConfig;
@Autowired @Autowired
private ZLMRESTfulUtils zlmresTfulUtils; private ZLMRESTfulUtils zlmresTfulUtils;
@ -39,15 +44,12 @@ public class MediaServiceImpl implements IMediaService {
@Override @Override
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) { public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
StreamInfo streamInfo = null; StreamInfo streamInfo = null;
MediaServerItem mediaInfo;
if (mediaServerId == null) { if (mediaServerId == null) {
mediaInfo = mediaServerService.getDefaultMediaServer(); mediaServerId = mediaConfig.getId();
}else {
mediaInfo = mediaServerService.getOne(mediaServerId);
} }
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);;
if (mediaInfo == null) { if (mediaInfo == null) {
return streamInfo; return null;
} }
JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream); JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream);
if (mediaList != null) { if (mediaList != null) {
@ -72,7 +74,7 @@ public class MediaServiceImpl implements IMediaService {
@Override @Override
public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) { public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) {
StreamInfo streamInfoResult = new StreamInfo(); StreamInfo streamInfoResult = new StreamInfo();
streamInfoResult.setStreamId(stream); streamInfoResult.setStream(stream);
streamInfoResult.setApp(app); streamInfoResult.setApp(app);
if (addr == null) { if (addr == null) {
addr = mediaInfo.getStreamIp(); addr = mediaInfo.getStreamIp();

View File

@ -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.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; 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.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 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.bean.WVPResult;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IMediaService;
@ -53,9 +53,6 @@ public class PlayServiceImpl implements IPlayService {
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Autowired
private RedisUtil redis;
@Autowired @Autowired
private DeferredResultHolder resultHolder; private DeferredResultHolder resultHolder;
@ -104,19 +101,21 @@ public class PlayServiceImpl implements IPlayService {
logger.warn(String.format("设备点播超时deviceId%s channelId%s", deviceId, channelId)); logger.warn(String.format("设备点播超时deviceId%s channelId%s", deviceId, channelId));
WVPResult wvpResult = new WVPResult(); WVPResult wvpResult = new WVPResult();
wvpResult.setCode(-1); wvpResult.setCode(-1);
SIPDialog dialog = streamSession.getDialog(deviceId, channelId); SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, streamInfo.getStream());
if (dialog != null) { if (dialog != null) {
wvpResult.setMsg("收流超时,请稍候重试"); wvpResult.setMsg("收流超时,请稍候重试");
}else { }else {
wvpResult.setMsg("点播超时,请稍候重试"); wvpResult.setMsg("点播超时,请稍候重试");
} }
msg.setData(wvpResult); msg.setData(wvpResult);
// 点播超时回复BYE // 点播超时回复BYE
cmder.streamByeCmd(device.getDeviceId(), channelId); cmder.streamByeCmd(device.getDeviceId(), channelId, streamInfo.getStream());
// 释放rtpserver // 释放rtpserver
mediaServerService.closeRTPServer(playResult.getDevice(), channelId); mediaServerService.closeRTPServer(playResult.getDevice(), channelId, streamInfo.getStream());
// 回复之前所有的点播请求 // 回复之前所有的点播请求
resultHolder.invokeAllResult(msg); resultHolder.invokeAllResult(msg);
// TODO 释放ssrc
}); });
result.onCompletion(()->{ result.onCompletion(()->{
// 点播结束时调用截图接口 // 点播结束时调用截图接口
@ -154,14 +153,12 @@ public class PlayServiceImpl implements IPlayService {
} }
}); });
if (streamInfo == null) { if (streamInfo == null) {
SSRCInfo ssrcInfo;
String streamId = null; String streamId = null;
if (mediaServerItem.isRtpEnable()) { if (mediaServerItem.isRtpEnable()) {
streamId = String.format("%s_%s", device.getDeviceId(), channelId); 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) -> { cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
logger.info("收到订阅消息: " + response.toJSONString()); logger.info("收到订阅消息: " + response.toJSONString());
@ -173,7 +170,7 @@ public class PlayServiceImpl implements IPlayService {
WVPResult wvpResult = new WVPResult(); WVPResult wvpResult = new WVPResult();
wvpResult.setCode(-1); wvpResult.setCode(-1);
// 点播返回sip错误 // 点播返回sip错误
mediaServerService.closeRTPServer(playResult.getDevice(), channelId); mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
msg.setData(wvpResult); msg.setData(wvpResult);
resultHolder.invokeAllResult(msg); resultHolder.invokeAllResult(msg);
@ -184,7 +181,7 @@ public class PlayServiceImpl implements IPlayService {
}); });
} else { } else {
String streamId = streamInfo.getStreamId(); String streamId = streamInfo.getStream();
if (streamId == null) { if (streamId == null) {
WVPResult wvpResult = new WVPResult(); WVPResult wvpResult = new WVPResult();
wvpResult.setCode(-1); wvpResult.setCode(-1);
@ -213,18 +210,16 @@ public class PlayServiceImpl implements IPlayService {
// TODO 点播前是否重置状态 // TODO 点播前是否重置状态
redisCatchStorage.stopPlay(streamInfo); redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
SSRCInfo ssrcInfo;
String streamId2 = null; String streamId2 = null;
if (mediaServerItem.isRtpEnable()) { if (mediaServerItem.isRtpEnable()) {
streamId2 = String.format("%s_%s", device.getDeviceId(), channelId); 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) -> { cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
logger.info("收到订阅消息: " + response.toJSONString()); logger.info("收到订阅消息: " + response.toJSONString());
onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid); onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid);
}, (event) -> { }, (event) -> {
mediaServerService.closeRTPServer(playResult.getDevice(), channelId); mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
WVPResult wvpResult = new WVPResult(); WVPResult wvpResult = new WVPResult();
wvpResult.setCode(-1); wvpResult.setCode(-1);
wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
@ -242,12 +237,12 @@ public class PlayServiceImpl implements IPlayService {
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
msg.setId(uuid); msg.setId(uuid);
msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); 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) { if (streamInfo != null) {
DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
if (deviceChannel != null) { if (deviceChannel != null) {
deviceChannel.setStreamId(streamInfo.getStreamId()); deviceChannel.setStreamId(streamInfo.getStream());
storager.startPlay(deviceId, channelId, streamInfo.getStreamId()); storager.startPlay(deviceId, channelId, streamInfo.getStream());
} }
redisCatchStorage.startPlay(streamInfo); redisCatchStorage.startPlay(streamInfo);
msg.setData(JSON.toJSONString(streamInfo)); msg.setData(JSON.toJSONString(streamInfo));
@ -284,29 +279,53 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { public DeferredResult<ResponseEntity<String>> 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<ResponseEntity<String>> 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(); RequestMessage msg = new RequestMessage();
msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId);
msg.setId(uuid); msg.setId(uuid);
StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); msg.setKey(key);
if (streamInfo != null) { result.onTimeout(()->{
redisCatchStorage.startPlayback(streamInfo); msg.setData("回放超时");
msg.setData(JSON.toJSONString(streamInfo)); callback.call(msg);
resultHolder.invokeResult(msg); });
} else { 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调用失败"); logger.warn("设备回放API调用失败");
msg.setData("设备回放API调用失败"); msg.setData("设备回放API调用失败");
resultHolder.invokeResult(msg); callback.call(msg);
return;
} }
redisCatchStorage.startPlayback(streamInfo);
msg.setData(JSON.toJSONString(streamInfo));
callback.call(msg);
}, event -> {
msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
callback.call(msg);
});
return result;
} }
@Override @Override
public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) {
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId); msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);
msg.setId(uuid); msg.setId(uuid);
StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid); StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
if (streamInfo != null) { if (streamInfo != null) {
redisCatchStorage.startDownload(streamInfo); redisCatchStorage.startDownload(streamInfo);
msg.setData(JSON.toJSONString(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"); String streamId = resonse.getString("stream");
JSONArray tracks = resonse.getJSONArray("tracks"); JSONArray tracks = resonse.getJSONArray("tracks");
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks); StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);

View File

@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 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.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.MessageListener;
@ -11,11 +13,14 @@ import org.springframework.stereotype.Component;
@Component @Component
public class RedisGPSMsgListener implements MessageListener { public class RedisGPSMsgListener implements MessageListener {
private final static Logger logger = LoggerFactory.getLogger(RedisGPSMsgListener.class);
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Override @Override
public void onMessage(Message message, byte[] bytes) { public void onMessage(Message message, byte[] bytes) {
logger.debug("收到来自REDIS的GPS通知 {}", new String(message.getBody()));
GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class); GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
} }

View File

@ -132,7 +132,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
}else { }else {
streamLive = true; streamLive = true;
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
mediaInfo, param.getApp(), param.getStream(), null); mediaInfo, param.getApp(), param.getStream(), null, null);
wvpResult.setData(streamInfo); wvpResult.setData(streamInfo);
} }

View File

@ -377,7 +377,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
if (streamPushItemsForPlatform.size() > 0) { if (streamPushItemsForPlatform.size() > 0) {
List<StreamPushItem> streamPushItemListFroPlatform = new ArrayList<>(); List<StreamPushItem> streamPushItemListFroPlatform = new ArrayList<>();
Map<String, List<StreamPushItem>> platformForEvent = new HashMap<>(); Map<String, List<GbStream>> platformForEvent = new HashMap<>();
// 遍历存储结果查找app+Stream->platformId+catalogId的对应关系然后执行批量写入 // 遍历存储结果查找app+Stream->platformId+catalogId的对应关系然后执行批量写入
for (StreamPushItem streamPushItem : streamPushItemsForPlatform) { for (StreamPushItem streamPushItem : streamPushItemsForPlatform) {
List<String[]> platFormInfoList = streamPushItemsForAll.get(streamPushItem.getApp() + streamPushItem.getStream()); List<String[]> platFormInfoList = streamPushItemsForAll.get(streamPushItem.getApp() + streamPushItem.getStream());
@ -390,16 +390,17 @@ public class StreamPushServiceImpl implements IStreamPushService {
// 数组 platFormInfoArray 0 为平台ID 1为目录ID // 数组 platFormInfoArray 0 为平台ID 1为目录ID
streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]); streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]);
List<StreamPushItem> streamPushItemsInPlatform = platformForEvent.get(streamPushItem.getPlatformId()); List<GbStream> gbStreamList = platformForEvent.get(streamPushItem.getPlatformId());
if (streamPushItemsInPlatform == null) { if (gbStreamList == null) {
streamPushItemsInPlatform = new ArrayList<>(); gbStreamList = new ArrayList<>();
platformForEvent.put(platFormInfoArray[0], streamPushItemsInPlatform); platformForEvent.put(platFormInfoArray[0], gbStreamList);
} }
// 为发送通知整理数据 // 为发送通知整理数据
streamPushItemForPlatform.setName(streamPushItem.getName());
streamPushItemForPlatform.setApp(streamPushItem.getApp()); streamPushItemForPlatform.setApp(streamPushItem.getApp());
streamPushItemForPlatform.setStream(streamPushItem.getStream()); streamPushItemForPlatform.setStream(streamPushItem.getStream());
streamPushItemForPlatform.setGbId(streamPushItem.getGbId()); streamPushItemForPlatform.setGbId(streamPushItem.getGbId());
streamPushItemsInPlatform.add(streamPushItemForPlatform); gbStreamList.add(streamPushItemForPlatform);
} }
if (platFormInfoArray.length > 1) { if (platFormInfoArray.length > 1) {
streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]); streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]);
@ -416,7 +417,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
// 发送通知 // 发送通知
for (String platformId : platformForEvent.keySet()) { for (String platformId : platformForEvent.keySet()) {
eventPublisher.catalogEventPublishForStream( eventPublisher.catalogEventPublishForStream(
platformId, platformForEvent.get(platformId).toArray(new GbStream[0]), CatalogEvent.ADD); platformId, platformForEvent.get(platformId), CatalogEvent.ADD);
} }
} }
} }

View File

@ -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.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 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.service.bean.ThirdPartyGB;
import java.util.List; import java.util.List;
@ -220,4 +221,5 @@ public interface IRedisCatchStorage {
void addMemInfo(double memInfo); void addMemInfo(double memInfo);
void addNetInfo(Map<String, String> networkInterfaces); void addNetInfo(Map<String, String> networkInterfaces);
} }

View File

@ -87,26 +87,27 @@ public interface DeviceChannelMapper {
void startPlay(String deviceId, String channelId, String streamId); void startPlay(String deviceId, String channelId, String streamId);
@Select(value = {" <script>" + @Select(value = {" <script>" +
"SELECT dc.channelId, "+ "SELECT " +
"dc.deviceId, " + " dc.id,\n" +
"dc.name, " + " dc.channelId,\n" +
"de.manufacturer, " + " dc.deviceId,\n" +
"de.hostAddress, " + " dc.name,\n" +
"dc.subCount, " + " de.manufacturer,\n" +
"pgc.platformId as platformId, " + " de.hostAddress,\n" +
"pgc.catalogId as catalogId " + " dc.subCount,\n" +
"FROM device_channel dc " + " pgc.platformId as platformId,\n" +
"LEFT JOIN device de ON dc.deviceId = de.deviceId " + " pgc.catalogId as catalogId " +
"LEFT JOIN platform_gb_channel pgc on de.deviceId = pgc.deviceId and pgc.channelId = dc.channelId " + " FROM device_channel dc " +
"LEFT JOIN device_channel dc2 ON dc2.deviceId = de.deviceId AND dc2.parentId = dc.channelId " + " LEFT JOIN device de ON dc.deviceId = de.deviceId " +
" LEFT JOIN platform_gb_channel pgc on pgc.deviceChannelId = dc.id " +
" WHERE 1=1 " + " WHERE 1=1 " +
" <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " + " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " +
" <if test='online == true' > AND dc.status=1</if> " + " <if test='online == true' > AND dc.status=1</if> " +
" <if test='online == false' > AND dc.status=0</if> " + " <if test='online == false' > AND dc.status=0</if> " +
" <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc2.channelId is not null</if> " + " <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc.subCount > 0</if> " +
" <if test='hasSubChannel!= null and hasSubChannel == false' > AND dc2.channelId is null</if> " + " <if test='hasSubChannel!= null and hasSubChannel == false' > AND dc.subCount == 0</if> " +
" <if test='catalogId == null ' > AND ((pgc.platformId IS NULL AND pgc.catalogId IS NULL) or (pgc.platformId != #{platformId}))</if> " + " <if test='catalogId == null ' > AND dc.id not in (select deviceChannelId from platform_gb_channel where platformId=#{platformId} ) </if> " +
" <if test='catalogId != null ' > AND pgc.platformId =#{platformId} AND pgc.catalogId = #{catalogId}</if> " + " <if test='catalogId != null ' > AND pgc.platformId = #{platformId} and pgc.catalogId=#{catalogId} </if> " +
" ORDER BY dc.deviceId, dc.channelId ASC" + " ORDER BY dc.deviceId, dc.channelId ASC" +
" </script>"}) " </script>"})
List<ChannelReduce> queryChannelListInAll(String query, Boolean online, Boolean hasSubChannel, String platformId, String catalogId); List<ChannelReduce> queryChannelListInAll(String query, Boolean online, Boolean hasSubChannel, String platformId, String catalogId);
@ -196,8 +197,8 @@ public interface DeviceChannelMapper {
List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId);
@Select(" SELECT\n" + @Select(" SELECT\n" +
" id,\n" +
" channelId,\n" + " channelId,\n" +
" channelId as id,\n" +
" deviceId,\n" + " deviceId,\n" +
" parentId,\n" + " parentId,\n" +
" status,\n" + " status,\n" +

View File

@ -74,7 +74,7 @@ public interface DeviceMapper {
"<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" + "<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" +
"<if test=\"expires != null\">, expires=${expires}</if>" + "<if test=\"expires != null\">, expires=${expires}</if>" +
"<if test=\"charset != null\">, charset='${charset}'</if>" + "<if test=\"charset != null\">, charset='${charset}'</if>" +
"<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=#{subscribeCycleForCatalog}</if>" + "<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=${subscribeCycleForCatalog}</if>" +
"WHERE deviceId='${deviceId}'"+ "WHERE deviceId='${deviceId}'"+
" </script>"}) " </script>"})
int update(Device device); int update(Device device);

View File

@ -19,6 +19,7 @@ public interface GbStreamMapper {
"('${app}', '${stream}', '${gbId}', '${name}', " + "('${app}', '${stream}', '${gbId}', '${name}', " +
"'${longitude}', '${latitude}', '${streamType}', " + "'${longitude}', '${latitude}', '${streamType}', " +
"'${mediaServerId}', ${status}, ${createStamp})") "'${mediaServerId}', ${status}, ${createStamp})")
@Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
int add(GbStream gbStream); int add(GbStream gbStream);
@Update("UPDATE gb_stream " + @Update("UPDATE gb_stream " +

View File

@ -21,27 +21,31 @@ public interface PlatformChannelMapper {
* 查询列表里已经关联的 * 查询列表里已经关联的
*/ */
@Select("<script> "+ @Select("<script> "+
"SELECT deviceAndChannelId FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceAndChannelId in" + "SELECT deviceChannelId FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" +
"<foreach collection='deviceAndChannelIds' open='(' item='id_' separator=',' close=')'> '${id_}'</foreach> ORDER BY deviceAndChannelId ASC" + "<foreach collection='channelReduces' open='(' item='item' separator=',' close=')'> '${item.id}'</foreach>" +
"</script>") "</script>")
List<String> findChannelRelatedPlatform(String platformId, List<String> deviceAndChannelIds); List<Integer> findChannelRelatedPlatform(String platformId, List<ChannelReduce> channelReduces);
@Insert("<script> "+ @Insert("<script> "+
"INSERT INTO platform_gb_channel (channelId, deviceId, platformId, deviceAndChannelId, catalogId) VALUES" + "INSERT INTO platform_gb_channel (platformId, deviceChannelId, catalogId) VALUES" +
"<foreach collection='channelReducesToAdd' item='item' separator=','>" + "<foreach collection='channelReducesToAdd' item='item' separator=','>" +
" ('${item.channelId}','${item.deviceId}', '${platformId}', '${item.deviceId}_${item.channelId}' , '${item.catalogId}' )" + " ('${platformId}', '${item.id}' , '${item.catalogId}' )" +
"</foreach>" + "</foreach>" +
"</script>") "</script>")
int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd); int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd);
@Delete("<script> "+ @Delete("<script> "+
"DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceAndChannelId in" + "DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" +
"<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.deviceId}_${item.channelId}'</foreach>" + "<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.id}'</foreach>" +
"</script>") "</script>")
int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel); int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel);
@Delete("<script> "+ @Delete("<script> "+
"DELETE FROM platform_gb_channel WHERE deviceId='${deviceId}' " + "DELETE FROM platform_gb_channel WHERE deviceChannelId in " +
"( select temp.deviceChannelId from " +
"(select pgc.deviceChannelId from platform_gb_channel pgc " +
"left join device_channel dc on dc.id = pgc.deviceChannelId where dc.deviceId =#{deviceId} " +
") temp)" +
"</script>") "</script>")
int delChannelForDeviceId(String deviceId); int delChannelForDeviceId(String deviceId);
@ -50,16 +54,19 @@ public interface PlatformChannelMapper {
"</script>") "</script>")
int cleanChannelForGB(String platformId); int cleanChannelForGB(String platformId);
@Select("SELECT * FROM device_channel WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE " + @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}'")
"platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'")
DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); 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 " + @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 " + " from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId " +
"where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") " where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}")
List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId); List<PlatformCatalog> 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); Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
@Delete("<script> "+ @Delete("<script> "+
@ -79,8 +86,10 @@ public interface PlatformChannelMapper {
"parent_platform pp " + "parent_platform pp " +
"left join platform_gb_channel pgc on " + "left join platform_gb_channel pgc on " +
"pp.serverGBId = pgc.platformId " + "pp.serverGBId = pgc.platformId " +
"left join device_channel dc on " +
"dc.id = pgc.deviceChannelId " +
"WHERE " + "WHERE " +
"pgc.channelId = #{channelId} and pp.status = true " + "dc.channelId = #{channelId} and pp.status = true " +
"AND pp.serverGBId IN" + "AND pp.serverGBId IN" +
"<foreach collection='platforms' item='item' open='(' separator=',' close=')' > #{item}</foreach>" + "<foreach collection='platforms' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
"</script> ") "</script> ")

View File

@ -19,6 +19,7 @@ public interface StreamProxyMapper {
@Update("UPDATE stream_proxy " + @Update("UPDATE stream_proxy " +
"SET type=#{type}, " + "SET type=#{type}, " +
"name=#{name}," +
"app=#{app}," + "app=#{app}," +
"name=#{name}," + "name=#{name}," +
"stream=#{stream}," + "stream=#{stream}," +

View File

@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
import org.omg.PortableInterceptor.INACTIVE; // import org.omg.PortableInterceptor.INACTIVE;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Collection; import java.util.Collection;

View File

@ -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.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 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.service.bean.ThirdPartyGB;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
@ -91,7 +92,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
*/ */
@Override @Override
public boolean startPlay(StreamInfo stream) { 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); stream);
} }
@ -105,7 +107,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
if (streamInfo == null) return false; if (streamInfo == null) return false;
return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
userSetup.getServerId(), userSetup.getServerId(),
streamInfo.getStreamId(), streamInfo.getStream(),
streamInfo.getDeviceID(), streamInfo.getDeviceID(),
streamInfo.getChannelId())); streamInfo.getChannelId()));
} }
@ -119,7 +121,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s", return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s",
VideoManagerConstants.PLAYER_PREFIX, VideoManagerConstants.PLAYER_PREFIX,
userSetup.getServerId(), userSetup.getServerId(),
streamInfo.getStreamId(), streamInfo.getStream(),
streamInfo.getDeviceID(), streamInfo.getDeviceID(),
streamInfo.getChannelId())); streamInfo.getChannelId()));
} }
@ -165,14 +167,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override @Override
public boolean startPlayback(StreamInfo stream) { public boolean startPlayback(StreamInfo stream) {
return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),stream.getStreamId(), return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
stream.getDeviceID(), stream.getChannelId()), stream); userSetup.getServerId(), stream.getStream(), stream.getDeviceID(), stream.getChannelId()), stream);
} }
@Override @Override
public boolean startDownload(StreamInfo streamInfo) { public boolean startDownload(StreamInfo streamInfo) {
return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),streamInfo.getStreamId(), return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),
streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo); streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
} }
@Override @Override
@ -186,7 +188,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
} }
return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
userSetup.getServerId(), userSetup.getServerId(),
streamInfo.getStreamId(), streamInfo.getStream(),
streamInfo.getDeviceID(), streamInfo.getDeviceID(),
streamInfo.getChannelId())); streamInfo.getChannelId()));
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.storager.impl; package com.genersoft.iot.vmp.storager.impl;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 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) { public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
String channelId = channel.getChannelId(); String channelId = channel.getChannelId();
channel.setDeviceId(deviceId); 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()); String now = this.format.format(System.currentTimeMillis());
channel.setUpdateTime(now); channel.setUpdateTime(now);
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
@ -178,7 +182,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
if (channelList.size() == 0) { if (channelList.size() == 0) {
for (DeviceChannel channel : channels) { for (DeviceChannel channel : channels) {
channel.setDeviceId(deviceId); 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()); String now = this.format.format(System.currentTimeMillis());
channel.setUpdateTime(now); channel.setUpdateTime(now);
channel.setCreateTime(now); channel.setCreateTime(now);
@ -189,9 +196,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
channelsInStore.put(deviceChannel.getChannelId(), deviceChannel); channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
} }
for (DeviceChannel channel : channels) { for (DeviceChannel channel : channels) {
String channelId = channel.getChannelId();
channel.setDeviceId(deviceId); 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()); String now = this.format.format(System.currentTimeMillis());
channel.setUpdateTime(now); channel.setUpdateTime(now);
if (channelsInStore.get(channel.getChannelId()) != null) { if (channelsInStore.get(channel.getChannelId()) != null) {
@ -607,19 +616,19 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
@Override @Override
public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) { public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
Map<String, ChannelReduce> deviceAndChannels = new HashMap<>(); Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
for (ChannelReduce channelReduce : channelReduces) { for (ChannelReduce channelReduce : channelReduces) {
channelReduce.setCatalogId(catalogId); channelReduce.setCatalogId(catalogId);
deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce); deviceAndChannels.put(channelReduce.getId(), channelReduce);
} }
List<String> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet()); List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
// 查询当前已经存在的 // 查询当前已经存在的
List<String> relatedPlatformchannels = platformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList); List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
if (relatedPlatformchannels != null) { if (deviceAndChannelList != null) {
deviceAndChannelList.removeAll(relatedPlatformchannels); deviceAndChannelList.removeAll(channelIds);
} }
for (String relatedPlatformchannel : relatedPlatformchannels) { for (Integer channelId : channelIds) {
deviceAndChannels.remove(relatedPlatformchannel); deviceAndChannels.remove(channelId);
} }
List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
// 对剩下的数据进行存储 // 对剩下的数据进行存储

View File

@ -18,7 +18,7 @@ public class BaseNode<T> implements INode<T> {
/** /**
* 主键ID * 主键ID
*/ */
protected String id; protected int id;
/** /**
* 父节点ID * 父节点ID

View File

@ -19,7 +19,7 @@ public class ForestNode extends BaseNode<ForestNode> {
*/ */
private Object content; private Object content;
public ForestNode(String id, String parentId, Object content) { public ForestNode(int id, String parentId, Object content) {
this.id = id; this.id = id;
this.parentId = parentId; this.parentId = parentId;
this.content = content; this.content = content;

View File

@ -17,12 +17,12 @@ public class ForestNodeManager<T extends INode<T>> {
/** /**
* 森林的所有节点 * 森林的所有节点
*/ */
private final ImmutableMap<String, T> nodeMap; private final ImmutableMap<Integer, T> nodeMap;
/** /**
* 森林的父节点ID * 森林的父节点ID
*/ */
private final Map<String, Object> parentIdMap = Maps.newHashMap(); private final Map<Integer, Object> parentIdMap = Maps.newHashMap();
public ForestNodeManager(List<T> nodes) { public ForestNodeManager(List<T> nodes) {
nodeMap = Maps.uniqueIndex(nodes, INode::getId); nodeMap = Maps.uniqueIndex(nodes, INode::getId);
@ -46,7 +46,7 @@ public class ForestNodeManager<T extends INode<T>> {
* *
* @param parentId 父节点ID * @param parentId 父节点ID
*/ */
public void addParentId(String parentId) { public void addParentId(int parentId) {
parentIdMap.put(parentId, ""); parentIdMap.put(parentId, "");
} }

View File

@ -14,7 +14,7 @@ public interface INode<T> extends Serializable {
* *
* @return String * @return String
*/ */
String getId(); int getId();
/** /**
* 父主键 * 父主键

View File

@ -19,7 +19,7 @@ public class DeviceChannelTree extends DeviceChannel implements INode<DeviceChan
/** /**
* 主键ID * 主键ID
*/ */
private String id; private int id;
/** /**
* 父节点ID * 父节点ID

View File

@ -205,9 +205,6 @@ public class DeviceQuery {
logger.debug("设备信息删除API调用deviceId" + deviceId); logger.debug("设备信息删除API调用deviceId" + deviceId);
} }
if (offLineDetector.isOnline(deviceId)) {
return new ResponseEntity<String>("不允许删除在线设备!", HttpStatus.NOT_ACCEPTABLE);
}
// 清除redis记录 // 清除redis记录
boolean isSuccess = storager.delete(deviceId); boolean isSuccess = storager.delete(deviceId);
if (isSuccess) { if (isSuccess) {
@ -319,20 +316,20 @@ public class DeviceQuery {
if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset()); if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset());
if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId()); if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId());
if ((deviceInStore.getSubscribeCycleForCatalog() <=0 && device.getSubscribeCycleForCatalog() > 0) if (device.getSubscribeCycleForCatalog() > 0) {
|| deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
// 开启订阅 // 开启订阅
deviceService.addCatalogSubscribe(deviceInStore); deviceService.addCatalogSubscribe(deviceInStore);
} }
if (deviceInStore.getSubscribeCycleForCatalog() > 0 && device.getSubscribeCycleForCatalog() <= 0) { }else if (device.getSubscribeCycleForCatalog() == 0) {
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); if (deviceInStore.getSubscribeCycleForCatalog() != 0) {
// 取消订阅 // 取消订阅
deviceService.removeCatalogSubscribe(deviceInStore); deviceService.removeCatalogSubscribe(deviceInStore);
} }
}
storager.updateDevice(deviceInStore); storager.updateDevice(device);
cmder.deviceInfoQuery(deviceInStore); cmder.deviceInfoQuery(device);
} }
WVPResult<String> result = new WVPResult<>(); WVPResult<String> result = new WVPResult<>();
result.setCode(0); result.setCode(0);

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.vmanager.gb28181.media; package com.genersoft.iot.vmp.vmanager.gb28181.media;
import com.genersoft.iot.vmp.common.StreamInfo; 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.IStreamPushService;
import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 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.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -33,6 +35,9 @@ public class MediaController {
@Autowired @Autowired
private IMediaService mediaService; private IMediaService mediaService;
@Autowired
private IMediaServerService mediaServerService;
/** /**
* 根据应用名和流id获取播放地址 * 根据应用名和流id获取播放地址

View File

@ -149,8 +149,16 @@ public class PlatformController {
if (updateResult) { if (updateResult) {
// 保存时启用就发送注册 // 保存时启用就发送注册
if (parentPlatform.isEnable()) { if (parentPlatform.isEnable()) {
if (parentPlatformOld.isStatus()) {
commanderForPlatform.unregister(parentPlatformOld, null, eventResult -> {
// 只要保存就发送注册 // 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null); commanderForPlatform.register(parentPlatform, null, null);
});
}else {
// 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null);
}
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销
commanderForPlatform.unregister(parentPlatform, null, null); commanderForPlatform.unregister(parentPlatform, null, null);
} }
@ -203,10 +211,21 @@ public class PlatformController {
if (updateResult) { if (updateResult) {
// 保存时启用就发送注册 // 保存时启用就发送注册
if (parentPlatform.isEnable()) { if (parentPlatform.isEnable()) {
if (parentPlatformOld.isStatus()) {
commanderForPlatform.unregister(parentPlatformOld, null, null);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 只要保存就发送注册 // 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null); commanderForPlatform.register(parentPlatform, null, null);
}else {
// 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null);
}
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销
commanderForPlatform.unregister(parentPlatform, null, null); commanderForPlatform.unregister(parentPlatformOld, null, null);
} }
wvpResult.setCode(0); wvpResult.setCode(0);
wvpResult.setMsg("success"); wvpResult.setMsg("success");

View File

@ -1,10 +1,17 @@
package com.genersoft.iot.vmp.vmanager.gb28181.platform.bean; package com.genersoft.iot.vmp.vmanager.gb28181.platform.bean;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
/** /**
* 精简的channel信息展示主要是选择通道的时候展示列表使用 * 精简的channel信息展示主要是选择通道的时候展示列表使用
*/ */
public class ChannelReduce { public class ChannelReduce {
/**
* deviceChannel的数据库自增ID
*/
private int id;
/** /**
* 通道id * 通道id
*/ */
@ -45,6 +52,13 @@ public class ChannelReduce {
*/ */
private String catalogId; private String catalogId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getChannelId() { public String getChannelId() {
return channelId; return channelId;

View File

@ -110,7 +110,6 @@ public class PlayController {
String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId;
resultHolder.put(key, uuid, result); resultHolder.put(key, uuid, result);
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
cmder.streamByeCmd(deviceId, channelId, (event) -> {
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
if (streamInfo == null) { if (streamInfo == null) {
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
@ -119,7 +118,9 @@ public class PlayController {
msg.setData("点播未找到"); msg.setData("点播未找到");
resultHolder.invokeAllResult(msg); resultHolder.invokeAllResult(msg);
storager.stopPlay(deviceId, channelId); storager.stopPlay(deviceId, channelId);
}else { return result;
}
cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), (event) -> {
redisCatchStorage.stopPlay(streamInfo); redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
@ -128,8 +129,7 @@ public class PlayController {
//Response response = event.getResponse(); //Response response = event.getResponse();
msg.setData(String.format("success")); msg.setData(String.format("success"));
resultHolder.invokeAllResult(msg); resultHolder.invokeAllResult(msg);
} mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
mediaServerService.closeRTPServer(device, channelId);
}); });
if (deviceId != null || channelId != null) { if (deviceId != null || channelId != null) {
@ -329,7 +329,7 @@ public class PlayController {
jsonObject.put("deviceId", transaction.getDeviceId()); jsonObject.put("deviceId", transaction.getDeviceId());
jsonObject.put("channelId", transaction.getChannelId()); jsonObject.put("channelId", transaction.getChannelId());
jsonObject.put("ssrc", transaction.getSsrc()); jsonObject.put("ssrc", transaction.getSsrc());
jsonObject.put("streamId", transaction.getStreamId()); jsonObject.put("streamId", transaction.getStream());
objects.add(jsonObject); objects.add(jsonObject);
} }

View File

@ -96,7 +96,7 @@ public class DownloadController {
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
if (streamInfo != null) { if (streamInfo != null) {
// 停止之前的下载 // 停止之前的下载
cmder.streamByeCmd(deviceId, channelId); cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream());
} }
MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); 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) -> { cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
logger.info("收到订阅消息: " + response.toJSONString()); logger.info("收到订阅消息: " + response.toJSONString());
playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString()); playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid);
}, event -> { }, event -> {
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
msg.setId(uuid); msg.setId(uuid);
@ -130,11 +130,12 @@ public class DownloadController {
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
@ApiImplicitParam(name = "channelId", 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}") @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) { public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
cmder.streamByeCmd(deviceId, channelId); cmder.streamByeCmd(deviceId, channelId, stream);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId)); logger.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId));

View File

@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -75,52 +76,8 @@ public class PlaybackController {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备回放 API调用deviceId%s channelId%s", deviceId, channelId)); 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<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(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);
// 超时处理 DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, msg->{
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));
resultHolder.invokeResult(msg); resultHolder.invokeResult(msg);
}); });
@ -131,24 +88,31 @@ public class PlaybackController {
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
@ApiImplicitParam(name = "channelId", 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}") @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) { public ResponseEntity<String> playStop(
@PathVariable String deviceId,
@PathVariable String channelId,
@PathVariable String stream) {
cmder.streamByeCmd(deviceId, channelId); cmder.streamByeCmd(deviceId, channelId, stream);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备录像回放停止 API调用deviceId/channelId%s/%s", deviceId, channelId)); 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) { if (deviceId != null && channelId != null) {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("deviceId", deviceId); json.put("deviceId", deviceId);
json.put("channelId", channelId); json.put("channelId", channelId);
return new ResponseEntity<String>(json.toString(), HttpStatus.OK); return new ResponseEntity<>(json.toString(), HttpStatus.OK);
} else { } else {
logger.warn("设备录像回放停止API调用失败"); logger.warn("设备录像回放停止API调用失败");
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
} }
} }

View File

@ -158,6 +158,7 @@ public class ServerController {
public WVPResult<String> deleteMediaServer(@RequestParam String id){ public WVPResult<String> deleteMediaServer(@RequestParam String id){
if (mediaServerService.getOne(id) != null) { if (mediaServerService.getOne(id) != null) {
mediaServerService.delete(id); mediaServerService.delete(id);
mediaServerService.deleteDb(id);
}else { }else {
WVPResult<String> result = new WVPResult<>(); WVPResult<String> result = new WVPResult<>();
result.setCode(-1); result.setCode(-1);

View File

@ -103,7 +103,7 @@ public class ApiStreamController {
PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code);
JSONObject result = new JSONObject(); JSONObject result = new JSONObject();
result.put("StreamID", streamInfo.getStreamId()); result.put("StreamID", streamInfo.getStream());
result.put("DeviceID", device.getDeviceId()); result.put("DeviceID", device.getDeviceId());
result.put("ChannelID", code); result.put("ChannelID", code);
result.put("ChannelName", deviceChannel.getName()); result.put("ChannelName", deviceChannel.getName());
@ -177,7 +177,7 @@ public class ApiStreamController {
result.put("error","未找到流信息"); result.put("error","未找到流信息");
return result; return result;
} }
cmder.streamByeCmd(serial, code); cmder.streamByeCmd(serial, code, streamInfo.getStream());
redisCatchStorage.stopPlay(streamInfo); redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
return null; return null;

View File

@ -30,24 +30,44 @@ spring:
poolMaxWait: 5 poolMaxWait: 5
# [可选] jdbc数据库配置, 项目使用sqlite作为数据库一般不需要配置 # [可选] jdbc数据库配置, 项目使用sqlite作为数据库一般不需要配置
datasource: 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 type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.sqlite.JDBC driver-class-name: com.mysql.cj.jdbc.Driver
journal_mode: WAL url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false
synchronous: NORMAL username: root
transaction_mode: IMMEDIATE password: root123
max-active: 1 druid:
min-idle: 1 initialSize: 10 # 连接池初始化连接数
maxActive: 200 # 连接池最大连接数
minIdle: 5 # 连接池最小空闲连接数
maxWait: 60000 # 获取连接时最大等待时间单位毫秒。配置了maxWait之后缺省启用公平锁并发效率会有所下降如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
keepAlive: true # 连接池中的minIdle数量以内的连接空闲时间超过minEvictableIdleTimeMillis则会执行keepAlive操作。
validationQuery: select 1 # 检测连接是否有效sql要求是查询语句常用select 'x'。如果validationQuery为nulltestOnBorrow、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端口, 网页和接口调用都是这个端口 # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
server: server:
@ -136,15 +156,8 @@ media:
# [可选] 日志配置, 一般不需要改 # [可选] 日志配置, 一般不需要改
logging: logging:
file: config: classpath:logback-spring-local.xml
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
# [根据业务需求配置] # [根据业务需求配置]
user-settings: user-settings:
# [可选] 服务ID不写则为000000 # [可选] 服务ID不写则为000000
@ -173,7 +186,7 @@ user-settings:
# 是否将日志存储进数据库 # 是否将日志存储进数据库
logInDatebase: true logInDatebase: true
# 第三方匹配用于从stream钟获取有效信息 # 第三方匹配用于从stream钟获取有效信息
thirdPartyGBIdReg: [\s\S]* thirdPartyGBIdReg: "[\\s\\S]*"
# 在线文档: swagger-ui生产环境建议关闭 # 在线文档: swagger-ui生产环境建议关闭
swagger-ui: swagger-ui:

View File

@ -17,23 +17,40 @@ spring:
# [可选] 超时时间 # [可选] 超时时间
timeout: 10000 timeout: 10000
# [可选] jdbc数据库配置, 项目使用sqlite作为数据库一般不需要配置 # [可选] jdbc数据库配置, 项目使用sqlite作为数据库一般不需要配置
# mysql数据源
datasource: 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 type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver 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为nulltestOnBorrow、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: server:
port: 18080 port: 18080
# 作为28181服务器的配置 # 作为28181服务器的配置
sip: sip:
# [必须修改] 本机的IP # [必须修改] 本机的IP
ip: ip: 192.168.118.70
# [可选] 28181服务监听的端口 # [可选] 28181服务监听的端口
port: 5060 port: 5060
# 根据国标6.1.2中规定domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码由省级、市级、区级、基层编号组成参照GB/T 2260-2007 # 根据国标6.1.2中规定domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码由省级、市级、区级、基层编号组成参照GB/T 2260-2007
@ -48,10 +65,9 @@ sip:
#zlm 默认服务器配置 #zlm 默认服务器配置
media: media:
# [必须修改] zlm服务器唯一id用于触发hook时区别是哪台服务器,general.mediaServerId id: FQ3TF8yT83wh5Wvz
id:
# [必须修改] zlm服务器的内网IP # [必须修改] zlm服务器的内网IP
ip: ip: 192.168.118.70
# [必须修改] zlm服务器的http.port # [必须修改] zlm服务器的http.port
http-port: 80 http-port: 80
# [可选] zlm服务器的hook.admin_params=secret # [可选] zlm服务器的hook.admin_params=secret
@ -68,25 +84,7 @@ media:
record-assist-port: 18081 record-assist-port: 18081
# [可选] 日志配置, 一般不需要改 # [可选] 日志配置, 一般不需要改
logging: logging:
file: config: classpath:logback-spring-local.xml
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
# 版本信息, 不需修改 # 版本信息, 不需修改
version: version:

View File

@ -69,16 +69,9 @@ media:
sdp-ip: ${sip.ip} sdp-ip: ${sip.ip}
stream-ip: ${sip.ip} stream-ip: ${sip.ip}
# [可选] 日志配置, 一般不需要改 # [可选] 日志配置, 一般不需要改
# [可选] 日志配置, 一般不需要改
logging: logging:
file: config: classpath:logback-spring-local.xml
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: user-settings:

View File

@ -1,3 +1,3 @@
spring: spring:
profiles: profiles:
active: local active: dev

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 -->
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/>
<property name="LOG_HOME" value="logs/${spring.application.name}" />
<!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />-->
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 DEBUG以上级别的日志,仅用于测试环境,正式环境为info级别以上的日志-->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--历史日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/wvp-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>20MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!--与ThresholdFilter的区别,允许onmatch-->
<!--设置日志级别 接收info级别的日志-->
<level>DEBUG</level>
</filter>
</appender>
<!-- 生成 error格式日志开始 -->
<appender name="RollingFileError" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--历史日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>20MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!--设置日志级别,过滤掉info日志,只输入error日志-->
<level>WARN</level>
<!-- <onMatch>ACCEPT</onMatch> &lt;!&ndash; 用过滤器只接受ERROR级别的日志信息其余全部过滤掉 &ndash;&gt;-->
<!-- <onMismatch>DENY</onMismatch>-->
</filter>
</appender>
<!-- 生成 druid日志追加 -->
<appender name="druidSqlRollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--历史日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/druid-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>50MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="RollingFile" />
<appender-ref ref="RollingFileError" />
</root>
<logger name="com.genersoft.iot.vmp.storager.dao" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="com.genersoft.iot.vmp.gb28181" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
<!--记录druid-sql的记录-->
<logger name="druid.sql.Statement" level="debug" additivity="true">
<!--AppenderRef ref="Console"/-->
<!-- <appender-ref ref="RollingFile"/>-->
<appender-ref ref="RollingFileError"/>
<appender-ref ref="druidSqlRollingFile"/>
</logger>
</configuration>

View File

@ -55,14 +55,14 @@
<el-table-column prop="createTime" label="创建时间" align="center" width="140"> <el-table-column prop="createTime" label="创建时间" align="center" width="140">
</el-table-column> </el-table-column>
<el-table-column label="操作" width="360" align="center" fixed="right"> <el-table-column label="操作" width="450" align="center" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>
<el-button-group> <el-button-group>
<el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button> <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button>
<el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button> <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>
<el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button> <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>
<el-button size="mini" icon="el-icon-delete" type="danger" v-if="scope.row.online==0" @click="deleteDevice(scope.row)">删除</el-button> <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button>
</el-button-group> </el-button-group>
</template> </template>
</el-table-column> </el-table-column>
@ -165,7 +165,17 @@
}, },
deleteDevice: function(row) { deleteDevice: function(row) {
let that = this; let msg = "确定删除此设备?"
if (row.online !== 0) {
msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>"
}
this.$confirm(msg, '提示', {
dangerouslyUseHTMLString : true,
confirmButtonText: '确定',
cancelButtonText: '取消',
center: true,
type: 'warning'
}).then(() => {
this.$axios({ this.$axios({
method: 'delete', method: 'delete',
url:`/api/device/query/devices/${row.deviceId}/delete` url:`/api/device/query/devices/${row.deviceId}/delete`
@ -174,6 +184,10 @@
}).catch((error) =>{ }).catch((error) =>{
console.log(error); console.log(error);
}); });
}).catch(() => {
});
}, },
showChannelList: function(row) { showChannelList: function(row) {

View File

@ -28,9 +28,7 @@
<devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
<!--设备列表--> <!--设备列表-->
<el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%"> <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%">
<el-table-column prop="channelId" label="通道编号" width="210"> <el-table-column prop="channelId" label="通道编号" width="200">
</el-table-column>
<el-table-column prop="deviceId" label="设备编号" width="210">
</el-table-column> </el-table-column>
<el-table-column prop="name" label="通道名称"> <el-table-column prop="name" label="通道名称">
</el-table-column> </el-table-column>

View File

@ -75,7 +75,10 @@ export default {
isLoging: false, isLoging: false,
rules: { rules: {
oldPassword: [{ required: true, validator: validatePass0, trigger: "blur" }], 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" }], confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
}, },
}; };

View File

@ -307,7 +307,7 @@ export default {
this.isLoging = false; this.isLoging = false;
// this.videoUrl = streamInfo.rtc; // this.videoUrl = streamInfo.rtc;
this.videoUrl = this.getUrlByStreamInfo(streamInfo); this.videoUrl = this.getUrlByStreamInfo(streamInfo);
this.streamId = streamInfo.streamId; this.streamId = streamInfo.stream;
this.app = streamInfo.app; this.app = streamInfo.app;
this.mediaServerId = streamInfo.mediaServerId; this.mediaServerId = streamInfo.mediaServerId;
this.playFromStreamInfo(false, streamInfo) this.playFromStreamInfo(false, streamInfo)
@ -485,8 +485,9 @@ export default {
}).then(function (res) { }).then(function (res) {
var streamInfo = res.data; var streamInfo = res.data;
that.app = streamInfo.app; that.app = streamInfo.app;
that.streamId = streamInfo.streamId; that.streamId = streamInfo.stream;
that.mediaServerId = streamInfo.mediaServerId; that.mediaServerId = streamInfo.mediaServerId;
that.ssrc = streamInfo.ssrc;
that.videoUrl = that.getUrlByStreamInfo(streamInfo); that.videoUrl = that.getUrlByStreamInfo(streamInfo);
that.recordPlay = true; that.recordPlay = true;
}); });
@ -497,7 +498,7 @@ export default {
this.videoUrl = ''; this.videoUrl = '';
this.$axios({ this.$axios({
method: 'get', method: 'get',
url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
}).then(function (res) { }).then(function (res) {
if (callback) callback() if (callback) callback()
}); });
@ -517,7 +518,7 @@ export default {
}).then(function (res) { }).then(function (res) {
var streamInfo = res.data; var streamInfo = res.data;
that.app = streamInfo.app; that.app = streamInfo.app;
that.streamId = streamInfo.streamId; that.streamId = streamInfo.stream;
that.mediaServerId = streamInfo.mediaServerId; that.mediaServerId = streamInfo.mediaServerId;
that.videoUrl = that.getUrlByStreamInfo(streamInfo); that.videoUrl = that.getUrlByStreamInfo(streamInfo);
that.recordPlay = true; that.recordPlay = true;
@ -529,7 +530,7 @@ export default {
this.videoUrl = ''; this.videoUrl = '';
this.$axios({ this.$axios({
method: 'get', method: 'get',
url: '/api/download/stop/' + this.deviceId + "/" + this.channelId url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
}).then(function (res) { }).then(function (res) {
if (callback) callback() if (callback) callback()
}); });
@ -539,8 +540,6 @@ export default {
let that = this; let that = this;
this.$axios({ this.$axios({
method: 'post', 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 url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
}).then(function (res) {}); }).then(function (res) {});
}, },