diff --git a/README.md b/README.md
index 1116581f7..5afd26d43 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
# 功能特性
- [X] 集成web界面
- [X] 兼容性良好
+- [X] 跨平台服务,一次编译多端部署, 可以同时用于x86和arm架构
- [X] 接入设备
- [X] 视频预览
- [X] 支持主码流子码流切换
@@ -98,7 +99,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 语音对讲
- [X] 支持同时级联到多个上级平台
- [X] 支持自动配置ZLM媒体服务, 减少因配置问题所出现的问题;
-- [X] 多流媒体节点,自动选择负载最低的节点使用。
+- [X] 支持流媒体节点集群,负载均衡。
- [X] 支持启用udp多端口模式, 提高udp模式下媒体传输性能;
- [X] 支持公网部署;
- [X] 支持wvp与zlm分开部署,提升平台并发能力
@@ -113,10 +114,12 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 支持录制计划, 根据设定的时间对通道进行录制. 暂不支持将录制的内容转发到国标上级
- [X] 支持Onvif, 目前付费提供, 永久免费试用包在知识星球获取
- [X] 支持国标28181-2022协议, 目前付费提供, 永久免费试用包在知识星球获取
+- [X] 支持国标信令集群
# 非开源的内容
- [X] ONVIF设备的接入,支持点播,云台控制,国标级联点播,自动点播。试用安装包以及使用教程: [知识星球](https://t.zsxq.com/10WAnH2MP),没有使用时间限制,需要源码可以星球私信我或者邮箱联系。
+- [X] 支持部标1078+808协议,支持点播,云台控制,录像回放,位置上报,自动点播。
- [X] 支持国标28181-2022协议,支持巡航轨迹查询,PTZ精准控制,存储卡格式化,设备软件升级,OSD配置,h265+aac,支持辅码流,录像倒放等。具体的功能列表可在[知识星球](https://t.zsxq.com/18GXkpkqs)查看,试用安装包: [知识星球](https://t.zsxq.com/UJ6V3),没有使用时间限制,需要源码可以星球私信我或者邮箱联系。
diff --git a/pom.xml b/pom.xml
index 67e0b1a2c..07aa9d38f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -199,13 +199,6 @@
springdoc-openapi-security
1.6.10
-
-
- com.baomidou
- dynamic-datasource-spring-boot-starter
- 3.6.1
-
-
diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
index acd6092fd..9a7912d20 100644
--- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
+++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp;
+import com.genersoft.iot.vmp.jt1078.util.ClassUtil;
import com.genersoft.iot.vmp.utils.GitUtil;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import lombok.extern.slf4j.Slf4j;
@@ -33,6 +34,7 @@ public class VManageBootstrap extends SpringBootServletInitializer {
public static void main(String[] args) {
VManageBootstrap.args = args;
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
+ ClassUtil.context = VManageBootstrap.context;
GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil");
if (gitUtil == null) {
log.info("获取版本信息失败");
@@ -62,6 +64,5 @@ public class VManageBootstrap extends SpringBootServletInitializer {
);
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(true);
-
}
}
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java b/src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
index adf9643fd..0c1279688 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
@@ -35,10 +35,16 @@ public class InviteInfo {
private Long createTime;
+ private Boolean record;
+
+ private String startTime;
+
+ private String endTime;
+
public static InviteInfo getInviteInfo(String deviceId, Integer channelId, String stream, SSRCInfo ssrcInfo, String mediaServerId,
String receiveIp, Integer receivePort, String streamMode,
- InviteSessionType type, InviteSessionStatus status) {
+ InviteSessionType type, InviteSessionStatus status, Boolean record) {
InviteInfo inviteInfo = new InviteInfo();
inviteInfo.setDeviceId(deviceId);
inviteInfo.setChannelId(channelId);
@@ -50,6 +56,7 @@ public class InviteInfo {
inviteInfo.setType(type);
inviteInfo.setStatus(status);
inviteInfo.setMediaServerId(mediaServerId);
+ inviteInfo.setRecord(record);
return inviteInfo;
}
diff --git a/src/main/java/com/genersoft/iot/vmp/common/ServerInfo.java b/src/main/java/com/genersoft/iot/vmp/common/ServerInfo.java
new file mode 100644
index 000000000..fb1941a13
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/common/ServerInfo.java
@@ -0,0 +1,23 @@
+package com.genersoft.iot.vmp.common;
+
+import com.genersoft.iot.vmp.utils.DateUtil;
+import lombok.Data;
+
+@Data
+public class ServerInfo {
+
+ private String ip;
+ private int port;
+ /**
+ * 现在使用的线程数
+ */
+ private String createTime;
+
+ public static ServerInfo create(String ip, int port) {
+ ServerInfo serverInfo = new ServerInfo();
+ serverInfo.setIp(ip);
+ serverInfo.setPort(port);
+ serverInfo.setCreateTime(DateUtil.getNow());
+ return serverInfo;
+ }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
index 280c11ba0..28e7d6416 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -4,11 +4,12 @@ import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
import java.io.Serializable;
import java.util.Objects;
-
+@Data
@Schema(description = "流信息")
public class StreamInfo implements Serializable, Cloneable{
@@ -91,100 +92,15 @@ public class StreamInfo implements Serializable, Cloneable{
@Schema(description = "产生源类型,包括 unknown = 0,rtmp_push=1,rtsp_push=2,rtp_push=3,pull=4,ffmpeg_pull=5,mp4_vod=6,device_chn=7")
private int originType;
+ @Schema(description = "originType的文本描述")
+ private String originTypeStr;
+
@Schema(description = "转码后的视频流")
private StreamInfo transcodeStream;
@Schema(description = "使用的WVP ID")
private String serverId;
- public void setFlv(StreamURL flv) {
- this.flv = flv;
- }
-
- public void setHttps_flv(StreamURL https_flv) {
- this.https_flv = https_flv;
- }
-
- public void setWs_flv(StreamURL ws_flv) {
- this.ws_flv = ws_flv;
- }
-
- public void setWss_flv(StreamURL wss_flv) {
- this.wss_flv = wss_flv;
- }
-
- public void setFmp4(StreamURL fmp4) {
- this.fmp4 = fmp4;
- }
-
- public void setHttps_fmp4(StreamURL https_fmp4) {
- this.https_fmp4 = https_fmp4;
- }
-
- public void setWs_fmp4(StreamURL ws_fmp4) {
- this.ws_fmp4 = ws_fmp4;
- }
-
- public void setWss_fmp4(StreamURL wss_fmp4) {
- this.wss_fmp4 = wss_fmp4;
- }
-
- public void setHls(StreamURL hls) {
- this.hls = hls;
- }
-
- public void setHttps_hls(StreamURL https_hls) {
- this.https_hls = https_hls;
- }
-
- public void setWs_hls(StreamURL ws_hls) {
- this.ws_hls = ws_hls;
- }
-
- public void setWss_hls(StreamURL wss_hls) {
- this.wss_hls = wss_hls;
- }
-
- public void setTs(StreamURL ts) {
- this.ts = ts;
- }
-
- public void setHttps_ts(StreamURL https_ts) {
- this.https_ts = https_ts;
- }
-
- public void setWs_ts(StreamURL ws_ts) {
- this.ws_ts = ws_ts;
- }
-
- public void setWss_ts(StreamURL wss_ts) {
- this.wss_ts = wss_ts;
- }
-
- public void setRtmp(StreamURL rtmp) {
- this.rtmp = rtmp;
- }
-
- public void setRtmps(StreamURL rtmps) {
- this.rtmps = rtmps;
- }
-
- public void setRtsp(StreamURL rtsp) {
- this.rtsp = rtsp;
- }
-
- public void setRtsps(StreamURL rtsps) {
- this.rtsps = rtsps;
- }
-
- public void setRtc(StreamURL rtc) {
- this.rtc = rtc;
- }
-
- public void setRtcs(StreamURL rtcs) {
- this.rtcs = rtcs;
- }
-
public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s%s", app, stream, callIdParam);
if (port > 0) {
@@ -275,7 +191,7 @@ public class StreamInfo implements Serializable, Cloneable{
}
}
- public void channgeStreamIp(String localAddr) {
+ public void changeStreamIp(String localAddr) {
if (this.flv != null) {
this.flv.setHost(localAddr);
}
@@ -351,205 +267,6 @@ public class StreamInfo implements Serializable, Cloneable{
private TransactionInfo transactionInfo;
- public String getApp() {
- return app;
- }
-
- public void setApp(String app) {
- this.app = app;
- }
-
- public String getDeviceId() {
- return deviceId;
- }
-
- public void setDeviceId(String deviceId) {
- this.deviceId = deviceId;
- }
-
- public Integer getChannelId() {
- return channelId;
- }
-
- public void setChannelId(Integer channelId) {
- this.channelId = channelId;
- }
-
- public String getStream() {
- return stream;
- }
-
- public void setStream(String stream) {
- this.stream = stream;
- }
-
- public String getIp() {
- return ip;
- }
-
- public void setIp(String ip) {
- this.ip = ip;
- }
-
- public StreamURL getFlv() {
- return flv;
- }
-
- public StreamURL getHttps_flv() {
- return https_flv;
- }
-
- public StreamURL getWs_flv() {
- return ws_flv;
- }
-
-
- public StreamURL getWss_flv() {
- return wss_flv;
- }
-
- public StreamURL getFmp4() {
- return fmp4;
- }
-
-
-
- public StreamURL getHttps_fmp4() {
- return https_fmp4;
- }
-
- public StreamURL getWs_fmp4() {
- return ws_fmp4;
- }
-
- public StreamURL getWss_fmp4() {
- return wss_fmp4;
- }
-
- public StreamURL getHls() {
- return hls;
- }
-
-
- public StreamURL getHttps_hls() {
- return https_hls;
- }
-
- public StreamURL getWs_hls() {
- return ws_hls;
- }
-
- public StreamURL getWss_hls() {
- return wss_hls;
- }
-
- public StreamURL getTs() {
- return ts;
- }
-
-
- public StreamURL getHttps_ts() {
- return https_ts;
- }
-
-
- public StreamURL getWs_ts() {
- return ws_ts;
- }
-
-
- public StreamURL getWss_ts() {
- return wss_ts;
- }
-
-
- public StreamURL getRtmp() {
- return rtmp;
- }
-
- public StreamURL getRtmps() {
- return rtmps;
- }
-
- public StreamURL getRtsp() {
- return rtsp;
- }
-
- public StreamURL getRtsps() {
- return rtsps;
- }
-
- public StreamURL getRtc() {
- return rtc;
- }
-
- public StreamURL getRtcs() {
- return rtcs;
- }
-
- public MediaServer getMediaServer() {
- return mediaServer;
- }
-
- public void setMediaServer(MediaServer mediaServer) {
- this.mediaServer = mediaServer;
- }
-
- public MediaInfo getMediaInfo() {
- return mediaInfo;
- }
-
- public void setMediaInfo(MediaInfo mediaInfo) {
- this.mediaInfo = mediaInfo;
- }
-
- public String getStartTime() {
- return startTime;
- }
-
- public void setStartTime(String startTime) {
- this.startTime = startTime;
- }
-
- public String getEndTime() {
- return endTime;
- }
-
- public void setEndTime(String endTime) {
- this.endTime = endTime;
- }
-
- public double getProgress() {
- return progress;
- }
-
- public void setProgress(double progress) {
- this.progress = progress;
- }
-
- public boolean isPause() {
- return pause;
- }
-
- public void setPause(boolean pause) {
- this.pause = pause;
- }
-
- public TransactionInfo getTransactionInfo() {
- return transactionInfo;
- }
-
- public void setTransactionInfo(TransactionInfo transactionInfo) {
- this.transactionInfo = transactionInfo;
- }
-
- public StreamInfo getTranscodeStream() {
- return transcodeStream;
- }
-
- public void setTranscodeStream(StreamInfo transcodeStream) {
- this.transcodeStream = transcodeStream;
- }
@Override
public StreamInfo clone() {
@@ -625,48 +342,4 @@ public class StreamInfo implements Serializable, Cloneable{
return instance;
}
-
- /*=========================设备主子码流逻辑START====================*/
- @Schema(description = "是否为子码流(true-是,false-主码流)")
- private boolean subStream;
-
- public boolean isSubStream() {
- return subStream;
- }
-
- public void setSubStream(boolean subStream) {
- this.subStream = subStream;
- }
-
- public DownloadFileInfo getDownLoadFilePath() {
- return downLoadFilePath;
- }
-
- public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) {
- this.downLoadFilePath = downLoadFilePath;
- }
-
- public int getOriginType() {
- return originType;
- }
-
- public void setOriginType(int originType) {
- this.originType = originType;
- }
-
- public String getServerId() {
- return serverId;
- }
-
- public void setServerId(String serverId) {
- this.serverId = serverId;
- }
-
- public String getCallId() {
- return callId;
- }
-
- public void setCallId(String callId) {
- this.callId = callId;
- }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
index 442709918..f498ba51b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -10,6 +10,8 @@ public class VideoManagerConstants {
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
+ public static final String WVP_SERVER_LIST = "VMP_SERVER_LIST";
+
public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_";
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_INFO:";
diff --git a/src/main/java/com/genersoft/iot/vmp/common/enums/ChannelDataType.java b/src/main/java/com/genersoft/iot/vmp/common/enums/ChannelDataType.java
new file mode 100644
index 000000000..c2d2a11e0
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/common/enums/ChannelDataType.java
@@ -0,0 +1,21 @@
+package com.genersoft.iot.vmp.common.enums;
+
+/**
+ * 支持的通道数据类型
+ */
+
+public enum ChannelDataType {
+
+ GB28181(1,"国标28181"),
+ STREAM_PUSH(2,"推流设备"),
+ STREAM_PROXY(3,"拉流代理");
+
+ public final int value;
+
+ public final String desc;
+
+ ChannelDataType(Integer value, String desc) {
+ this.value = value;
+ this.desc = desc;
+ }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
index 4742daa55..67c926e61 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
@@ -6,6 +6,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
+import java.util.List;
+
@Component
@ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true)
@Order(0)
@@ -16,6 +18,8 @@ public class SipConfig {
private String showIp;
+ private List monitorIps;
+
private Integer port;
private String domain;
@@ -30,5 +34,5 @@ public class SipConfig {
private boolean alarm = false;
- private long timeout = 15;
+ private long timeout = 150;
}
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
index e6a9006a0..cb12754e6 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
@@ -31,10 +31,13 @@ public class SipPlatformRunner implements CommandLineRunner {
@Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform;
+ @Autowired
+ private UserSetting userSetting;
+
@Override
public void run(String... args) throws Exception {
// 获取所有启用的平台
- List parentPlatforms = platformService.queryEnablePlatformList();
+ List parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId());
for (Platform platform : parentPlatforms) {
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
index c64b4ba88..ca346dfab 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
@@ -37,6 +37,11 @@ public class UserSetting {
*/
private Integer playTimeout = 10000;
+ /**
+ * 获取设备录像数据超时时间,单位:毫秒
+ */
+ private Integer recordInfoTimeout = 15000;
+
/**
* 上级点播等待超时时间,单位:毫秒
*/
@@ -175,4 +180,15 @@ public class UserSetting {
*/
private long loginTimeout = 30;
+ /**
+ * jwk文件路径,若不指定则使用resources目录下的jwk.json
+ */
+ private String jwkFile = "classpath:jwk.json";
+
+ /**
+ * wvp集群模式下如果注册向上级的wvp奔溃,则自动选择一个其他wvp继续注册到上级
+ */
+ private boolean autoRegisterPlatform = false;
+
+
}
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java b/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java
index 6da0caf3a..4a2098a27 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java
@@ -1,12 +1,14 @@
package com.genersoft.iot.vmp.conf;
-import com.alibaba.fastjson2.JSONObject;
+import com.genersoft.iot.vmp.common.ServerInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
+import java.util.concurrent.TimeUnit;
+
@Component
public class WVPTimerTask {
@@ -19,11 +21,8 @@ public class WVPTimerTask {
@Autowired
private SipConfig sipConfig;
- @Scheduled(fixedDelay = 2 * 1000) //每3秒执行一次
+ @Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
public void execute(){
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("ip", sipConfig.getShowIp());
- jsonObject.put("port", serverPort);
- redisCatchStorage.updateWVPInfo(jsonObject, 3);
+ redisCatchStorage.updateWVPInfo(ServerInfo.create(sipConfig.getShowIp(), serverPort), 3);
}
}
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java
index b762838c6..b541f7448 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisRpcConfig.java
@@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.conf.redis;
import com.alibaba.fastjson2.JSON;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcClassHandler;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcMessage;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
-import com.genersoft.iot.vmp.service.redisMsg.control.RedisRpcController;
+import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -16,8 +18,10 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
+import javax.sip.message.Response;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@@ -36,9 +40,6 @@ public class RedisRpcConfig implements MessageListener {
@Autowired
private UserSetting userSetting;
- @Autowired
- private RedisRpcController redisRpcController;
-
@Autowired
private RedisTemplate