diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b4bd40c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+/logs/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..e3ea6cb
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,310 @@
+
+
+ 4.0.0
+
+ com.jytech
+ riis
+ 2.7
+ 配电网变电站智能化平台
+ 配电网变电站智能化平台
+ pom
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.3
+
+
+
+
+ riis-system
+ riis-monitor
+
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ com.google.guava
+ guava
+ 30.0-jre
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ provided
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+
+
+
+
+
+
+
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.2.2
+
+
+
+
+ com.alibaba
+ druid
+ 1.2.3
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.1.22
+
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.32.3.2
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.4.3
+
+
+
+ com.baomidou
+ mybatis-plus-generator
+ 3.4.1
+
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ cn.hutool
+ hutool-all
+ 5.8.8
+
+
+
+
+ org.apache.poi
+ poi
+ 4.1.2
+
+
+ org.apache.poi
+ poi-ooxml
+ 4.1.2
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.70
+
+
+
+ io.springfox
+ springfox-boot-starter
+ 3.0.0
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+ 3.0.2
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+ org.freemarker
+ freemarker
+ 2.3.28
+ compile
+
+
+ org.jsoup
+ jsoup
+ 1.11.3
+
+
+
+
+ com.github.ulisesbocchio
+ jasypt-spring-boot-starter
+ 1.16
+
+
+
+ org.lionsoul
+ ip2region
+ 1.7.2
+
+
+
+
+ com.github.whvcse
+ easy-captcha
+ 1.6.2
+
+
+
+
+ eu.bitwalker
+ UserAgentUtils
+ 1.21
+
+
+
+
+ org.dom4j
+ dom4j
+ 2.1.3
+
+
+
+
+
+
+
+ src/main/resources
+
+ **/*.*
+
+ false
+
+
+ src/main/java
+
+ **/*.*
+
+
+ **/*.java
+
+ false
+
+
+
+
+
+
+ org.asciidoctor
+ asciidoctor-maven-plugin
+ 1.5.8
+
+
+ generate-docs
+ prepare-package
+
+ process-asciidoc
+
+
+ html
+ book
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.7.3
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git a/riis-monitor/pom.xml b/riis-monitor/pom.xml
new file mode 100644
index 0000000..9ba9cf0
--- /dev/null
+++ b/riis-monitor/pom.xml
@@ -0,0 +1,252 @@
+
+
+ 4.0.0
+
+ riis-monitor
+ 视频监控模块
+ war
+
+
+ com.jytech
+ riis
+ 2.7
+
+
+
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+ 1.4.3
+
+
+
+
+ javax.validation
+ validation-api
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ javax.sip
+ jain-sip-ri
+ 1.3.0-91
+
+
+
+
+ org.slf4j
+ log4j-over-slf4j
+ 1.7.36
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.17
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.9.3
+
+
+
+
+ com.squareup.okhttp3
+ logging-interceptor
+ 4.9.3
+
+
+
+
+ io.github.rburgst
+ okhttp-digest
+ 2.7
+
+
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ 1.6.10
+
+
+
+ com.github.xiaoymin
+ knife4j-springdoc-ui
+ 3.0.3
+
+
+
+
+ org.bitbucket.b_c
+ jose4j
+ 0.9.3
+
+
+
+
+ org.mitre.dsmiley.httpproxy
+ smiley-http-proxy-servlet
+ 1.12.1
+
+
+
+
+ com.alibaba
+ easyexcel
+ 3.1.1
+
+
+
+ com.google.guava
+ guava
+ 31.1-jre
+
+
+
+
+ com.github.oshi
+ oshi-core
+ 6.2.2
+
+
+
+ com.github.pagehelper
+ pagehelper
+ 5.3.1
+ compile
+
+
+ org.dom4j
+ dom4j
+ 2.1.3
+ compile
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.17
+ compile
+
+
+ com.alibaba
+ easyexcel-core
+ 3.1.1
+ compile
+
+
+ org.jetbrains
+ annotations
+ 22.0.0
+ compile
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+
+
+ com.alibaba.fastjson2
+ fastjson2-extension
+ 2.0.17
+ compile
+
+
+ org.bytedeco.javacpp-presets
+ ffmpeg
+ 4.0.2-1.4.3
+ compile
+
+
+
+
+
+
+
+
+ src/main/resources
+
+
+ src/main/java
+
+ **/*.xml
+
+
+
+
+
+
+ org.asciidoctor
+ asciidoctor-maven-plugin
+ 1.5.8
+
+
+ generate-docs
+ prepare-package
+
+ process-asciidoc
+
+
+ html
+ book
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.7.3
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+ true
+
+
+
+
+
+
+
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/MonitorApplication.java b/riis-monitor/src/main/java/com/yfd/monitor/MonitorApplication.java
new file mode 100644
index 0000000..07c9b71
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/MonitorApplication.java
@@ -0,0 +1,70 @@
+package com.yfd.monitor;
+
+import com.yfd.monitor.utils.GitUtil;
+import com.yfd.monitor.utils.SpringBeanFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import java.util.Collections;
+
+/**
+ * 启动类
+ */
+@ServletComponentScan("com.yfd.monitor.conf")
+@SpringBootApplication
+@EnableScheduling
+@EnableWebMvc
+public class MonitorApplication extends SpringBootServletInitializer {
+
+ private final static Logger logger = LoggerFactory.getLogger(MonitorApplication.class);
+
+ private static String[] args;
+ private static ConfigurableApplicationContext context;
+ public static void main(String[] args) {
+ MonitorApplication.args = args;
+ MonitorApplication.context = SpringApplication.run(MonitorApplication.class, args);
+ GitUtil gitUtil1 = SpringBeanFactory.getBean("gitUtil");
+ logger.info("构建版本: {}", gitUtil1.getBuildVersion());
+ logger.info("构建时间: {}", gitUtil1.getBuildDate());
+ logger.info("GIT最后提交时间: {}", gitUtil1.getCommitTime());
+ }
+ // 项目重启
+ public static void restart() {
+ context.close();
+ MonitorApplication.context = SpringApplication.run(MonitorApplication.class, args);
+ }
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(MonitorApplication.class);
+ }
+
+ @Override
+ public void onStartup(ServletContext servletContext) throws ServletException {
+ super.onStartup(servletContext);
+
+ servletContext.setSessionTrackingModes(
+ Collections.singleton(SessionTrackingMode.COOKIE)
+ );
+ SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
+ sessionCookieConfig.setHttpOnly(true);
+
+ }
+
+ static {
+ System.setProperty("druid.mysql.usePingMethod","false");
+ }
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/ApiSaveConstant.java b/riis-monitor/src/main/java/com/yfd/monitor/common/ApiSaveConstant.java
new file mode 100644
index 0000000..e57555d
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/ApiSaveConstant.java
@@ -0,0 +1,197 @@
+package com.yfd.monitor.common;
+
+/**
+ * 为API重命名, 方便向数据库记录数据的时候展示
+ */
+public class ApiSaveConstant {
+
+ public static String getVal(String key) {
+ String[] keyItemArray = key.split("/");
+ if (keyItemArray.length <= 1 || !"api".equals(keyItemArray[1])) {
+ return null;
+ }
+ if (keyItemArray.length >= 4) {
+ switch (keyItemArray[2]) {
+ case "alarm":
+ if ("delete".equals(keyItemArray[3])) {
+ return "删除报警";
+ }
+ break;
+ case "device":
+ switch (keyItemArray[3]) {
+ case "config":
+ if (keyItemArray.length >= 5 && "basicParam".equals(keyItemArray[4])) {
+ return "[设备配置] 基本配置设置命令";
+ }
+ break;
+ case "control":
+ switch (keyItemArray[4]) {
+ case "teleboot":
+ return "[设备控制] 远程启动";
+ case "record":
+ return "[设备控制] 录像控制";
+ case "guard":
+ return "[设备控制] 布防/撤防命令";
+ case "reset_alarm":
+ return "[设备控制] 报警复位";
+ case "i_frame":
+ return "[设备控制] 强制关键帧";
+ case "home_position":
+ return "[设备控制] 看守位控制";
+ default:
+ return "";
+ }
+ case "query":
+ if (keyItemArray.length <= 5) {
+ return null;
+ }
+ switch (keyItemArray[4]) {
+ case "devices":
+ if (keyItemArray.length < 7) {
+ return null;
+ }
+ switch (keyItemArray[6]) {
+ case "sync":
+ return "[设备查询] 同步设备通道";
+ case "delete":
+ return "[设备查询] 移除设备";
+ default:
+ return "";
+ }
+ case "channel":
+ return "[设备查询] 更新通道信息";
+ case "transport":
+ return "[设备查询] 修改数据流传输模式";
+ default:
+ return "";
+ }
+ default:
+ return "";
+ }
+
+ break;
+ case "gbStream":
+ switch (keyItemArray[3]) {
+ case "del":
+ return "移除通道与国标的关联";
+ case "add":
+ return "添加通道与国标的关联";
+ default:
+ return "";
+ }
+ case "media":
+ break;
+ case "position":
+ if ("subscribe".equals(keyItemArray[3])) {
+ return "订阅位置信息";
+ }
+ break;
+ case "platform":
+ switch (keyItemArray[3]) {
+ case "save":
+ return "添加上级平台";
+ case "delete":
+ return "移除上级平台";
+ case "update_channel_for_gb":
+ return "向上级平台添加国标通道";
+ case "del_channel_for_gb":
+ return "从上级平台移除国标通道";
+ default:
+ return "";
+ }
+ case "platform_gb_stream":
+ break;
+ case "play":
+ switch (keyItemArray[3]) {
+ case "start":
+ return "开始点播";
+ case "stop":
+ return "停止点播";
+ case "convert":
+ return "转码";
+ case "convertStop":
+ return "结束转码";
+ case "broadcast":
+ return "语音广播";
+ default:
+ return "";
+ }
+ case "download":
+ switch (keyItemArray[3]) {
+ case "start":
+ return "开始历史媒体下载";
+ case "stop":
+ return "停止历史媒体下载";
+ default:
+ return "";
+ }
+ case "playback":
+ switch (keyItemArray[3]) {
+ case "start":
+ return "开始视频回放";
+ case "stop":
+ return "停止视频回放";
+ default:
+ return "";
+ }
+ case "ptz":
+ switch (keyItemArray[3]) {
+ case "control":
+ return "云台控制";
+ case "front_end_command":
+ return "通用前端控制命令";
+ default:
+ return "";
+ }
+ case "gb_record":
+ break;
+ case "onvif":
+ break;
+ case "server":
+ if ("restart".equals(keyItemArray[3])) {
+ return "重启流媒体服务";
+ }
+ break;
+ case "proxy":
+ switch (keyItemArray[3]) {
+ case "save":
+ return "保存代理";
+ case "del":
+ return "移除代理";
+ case "start":
+ return "启用代理";
+ case "stop":
+ return "停用代理";
+ default:
+ return "";
+ }
+ case "push":
+ switch (keyItemArray[3]) {
+ case "save_to_gb":
+ return "将推流添加到国标";
+ case "remove_form_gb":
+ return "将推流移出到国标";
+ default:
+ return "";
+ }
+ case "user":
+ switch (keyItemArray[3]) {
+ case "login":
+ return "登录";
+ case "changePassword":
+ return "修改密码";
+ case "add":
+ return "添加用户";
+ case "delete":
+ return "删除用户";
+ default:
+ return "";
+ }
+ default:
+ return "";
+ }
+ }
+ return null;
+ }
+}
+
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/CommonCallback.java b/riis-monitor/src/main/java/com/yfd/monitor/common/CommonCallback.java
new file mode 100644
index 0000000..a18b2f0
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/CommonCallback.java
@@ -0,0 +1,5 @@
+package com.yfd.monitor.common;
+
+public interface CommonCallback{
+ void run(T t);
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/InviteInfo.java b/riis-monitor/src/main/java/com/yfd/monitor/common/InviteInfo.java
new file mode 100644
index 0000000..25ecc93
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/InviteInfo.java
@@ -0,0 +1,145 @@
+package com.yfd.monitor.common;
+
+
+import com.yfd.monitor.service.bean.SSRCInfo;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * 记录每次发送invite消息的状态
+ */
+public class InviteInfo {
+
+ private String deviceId;
+
+ private String channelId;
+
+ private String stream;
+
+ private SSRCInfo ssrcInfo;
+
+ private String receiveIp;
+
+ private Integer receivePort;
+
+ private String streamMode;
+
+ private InviteSessionType type;
+
+ private InviteSessionStatus status;
+
+ private StreamInfo streamInfo;
+
+
+ public static InviteInfo getInviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo,
+ String receiveIp, Integer receivePort, String streamMode,
+ InviteSessionType type, InviteSessionStatus status) {
+ InviteInfo inviteInfo = new InviteInfo();
+ inviteInfo.setDeviceId(deviceId);
+ inviteInfo.setChannelId(channelId);
+ inviteInfo.setStream(stream);
+ inviteInfo.setSsrcInfo(ssrcInfo);
+ inviteInfo.setReceiveIp(receiveIp);
+ inviteInfo.setReceivePort(receivePort);
+ inviteInfo.setStreamMode(streamMode);
+ inviteInfo.setType(type);
+ inviteInfo.setStatus(status);
+ return inviteInfo;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getChannelId() {
+ return channelId;
+ }
+
+ public void setChannelId(String channelId) {
+ this.channelId = channelId;
+ }
+
+ public InviteSessionType getType() {
+ return type;
+ }
+
+ public void setType(InviteSessionType type) {
+ this.type = type;
+ }
+
+ public InviteSessionStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(InviteSessionStatus status) {
+ this.status = status;
+ }
+
+ public StreamInfo getStreamInfo() {
+ return streamInfo;
+ }
+
+ public void setStreamInfo(StreamInfo streamInfo) {
+ this.streamInfo = streamInfo;
+ }
+
+ public String getStream() {
+ return stream;
+ }
+
+ public void setStream(String stream) {
+ this.stream = stream;
+ }
+
+ public SSRCInfo getSsrcInfo() {
+ return ssrcInfo;
+ }
+
+ public void setSsrcInfo(SSRCInfo ssrcInfo) {
+ this.ssrcInfo = ssrcInfo;
+ }
+
+ public String getReceiveIp() {
+ return receiveIp;
+ }
+
+ public void setReceiveIp(String receiveIp) {
+ this.receiveIp = receiveIp;
+ }
+
+ public Integer getReceivePort() {
+ return receivePort;
+ }
+
+ public void setReceivePort(Integer receivePort) {
+ this.receivePort = receivePort;
+ }
+
+ public String getStreamMode() {
+ return streamMode;
+ }
+
+ public void setStreamMode(String streamMode) {
+ this.streamMode = streamMode;
+ }
+
+
+ /*=========================设备主子码流逻辑START====================*/
+ @Schema(description = "是否为子码流(true-是,false-主码流)")
+ private boolean subStream;
+
+ public boolean isSubStream() {
+ return subStream;
+ }
+
+ public void setSubStream(boolean subStream) {
+ this.subStream = subStream;
+ }
+
+
+
+
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/InviteSessionStatus.java b/riis-monitor/src/main/java/com/yfd/monitor/common/InviteSessionStatus.java
new file mode 100644
index 0000000..adaee8e
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/InviteSessionStatus.java
@@ -0,0 +1,11 @@
+package com.yfd.monitor.common;
+
+/**
+ * 标识invite消息发出后的各个状态,
+ * 收到ok钱停止invite发送cancel,
+ * 收到200ok后发送BYE停止invite
+ */
+public enum InviteSessionStatus {
+ ready,
+ ok,
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/InviteSessionType.java b/riis-monitor/src/main/java/com/yfd/monitor/common/InviteSessionType.java
new file mode 100644
index 0000000..8c24b81
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/InviteSessionType.java
@@ -0,0 +1,9 @@
+package com.yfd.monitor.common;
+
+public enum InviteSessionType {
+ PLAY,
+ PLAYBACK,
+ DOWNLOAD,
+ BROADCAST,
+ TALK
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/ServerSendEventServer.java b/riis-monitor/src/main/java/com/yfd/monitor/common/ServerSendEventServer.java
new file mode 100644
index 0000000..712bcc7
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/ServerSendEventServer.java
@@ -0,0 +1,134 @@
+package com.yfd.monitor.common;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+/**
+ * SSE Server send Event 服务器推送服务
+ */
+@Slf4j
+public class ServerSendEventServer {
+
+ /**
+ * 当前连接数
+ */
+ private static AtomicInteger count = new AtomicInteger(0);
+
+ private static Map sseEmitterMap = new ConcurrentHashMap<>();
+
+ public static SseEmitter connect(String userId){
+ //设置超时时间,0表示不过期,默认是30秒,超过时间未完成会抛出异常
+ SseEmitter sseEmitter = new SseEmitter(0L);
+ //SseEmitter sseEmitter = new SseEmitter();
+ //注册回调
+ sseEmitter.onCompletion(completionCallBack(userId));
+ sseEmitter.onError(errorCallBack(userId));
+ sseEmitter.onTimeout(timeOutCallBack(userId));
+ sseEmitterMap.put(userId,sseEmitter);
+ //数量+1
+ count.getAndIncrement();
+ log.info("create new sse connect ,current user:{}",userId);
+ return sseEmitter;
+ }
+ /**
+ * 给指定用户发消息
+ */
+ public static void sendMessage(String userId, String message){
+ if(sseEmitterMap.containsKey(userId)){
+ try{
+ sseEmitterMap.get(userId).send(message);
+ }catch (IOException e){
+ log.error("user id:{}, send message error:{}", userId, e.getMessage());
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 给所有用户发消息
+ */
+ public static void sendMessage(String message) {
+ if (sseEmitterMap != null && !sseEmitterMap.isEmpty()) {
+ sseEmitterMap.forEach((k, v) -> {
+ // 发送消息
+ sendMessage(k, message);
+
+ });
+ }
+ }
+
+ /**
+ * 想多人发送消息,组播
+ */
+ public static void groupSendMessage(String groupId, String message){
+ if(sseEmitterMap!=null&&!sseEmitterMap.isEmpty()){
+ sseEmitterMap.forEach((k,v) -> {
+ try{
+ if(k.startsWith(groupId)){
+ v.send(message, MediaType.APPLICATION_JSON);
+ }
+ }catch (IOException e){
+ log.error("user id:{}, send message error:{}",groupId,message);
+ removeUser(k);
+ }
+ });
+ }
+ }
+ public static void batchSendMessage(String message) {
+ sseEmitterMap.forEach((k,v)->{
+ try{
+ v.send(message, MediaType.APPLICATION_JSON);
+ }catch (IOException e){
+ log.error("user id:{}, send message error:{}",k,e.getMessage());
+ removeUser(k);
+ }
+ });
+ }
+ /**
+ * 群发消息
+ */
+ public static void batchSendMessage(String message, Set userIds){
+ userIds.forEach(userId->sendMessage(userId,message));
+ }
+ public static void removeUser(String userId){
+ sseEmitterMap.remove(userId);
+ //数量-1
+ count.getAndDecrement();
+ log.info("remove user id:{}",userId);
+ }
+
+ public static List getIds(){
+ return new ArrayList<>(sseEmitterMap.keySet());
+ }
+ public static int getUserCount(){
+ return count.intValue();
+ }
+ private static Runnable completionCallBack(String userId) {
+ return () -> {
+ log.info("结束连接,{}",userId);
+ removeUser(userId);
+ };
+ }
+ private static Runnable timeOutCallBack(String userId){
+ return ()->{
+ log.info("连接超时,{}",userId);
+ removeUser(userId);
+ };
+ }
+ private static Consumer errorCallBack(String userId){
+ return throwable -> {
+ log.error("连接异常,{}",userId);
+ removeUser(userId);
+ };
+ }
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/StreamInfo.java b/riis-monitor/src/main/java/com/yfd/monitor/common/StreamInfo.java
new file mode 100644
index 0000000..87aacf0
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/StreamInfo.java
@@ -0,0 +1,544 @@
+package com.yfd.monitor.common;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+@Schema(description = "流信息")
+public class StreamInfo implements Serializable, Cloneable{
+
+ @Schema(description = "应用名")
+ private String app;
+ @Schema(description = "流ID")
+ private String stream;
+ @Schema(description = "设备编号")
+ private String deviceID;
+ @Schema(description = "通道编号")
+ private String channelId;
+
+ @Schema(description = "IP")
+ private String ip;
+
+ @Schema(description = "HTTP-FLV流地址")
+ private StreamURL flv;
+
+ @Schema(description = "HTTPS-FLV流地址")
+ private StreamURL https_flv;
+ @Schema(description = "Websocket-FLV流地址")
+ private StreamURL ws_flv;
+ @Schema(description = "Websockets-FLV流地址")
+ private StreamURL wss_flv;
+ @Schema(description = "HTTP-FMP4流地址")
+ private StreamURL fmp4;
+ @Schema(description = "HTTPS-FMP4流地址")
+ private StreamURL https_fmp4;
+ @Schema(description = "Websocket-FMP4流地址")
+ private StreamURL ws_fmp4;
+ @Schema(description = "Websockets-FMP4流地址")
+ private StreamURL wss_fmp4;
+ @Schema(description = "HLS流地址")
+ private StreamURL hls;
+ @Schema(description = "HTTPS-HLS流地址")
+ private StreamURL https_hls;
+ @Schema(description = "Websocket-HLS流地址")
+ private StreamURL ws_hls;
+ @Schema(description = "Websockets-HLS流地址")
+ private StreamURL wss_hls;
+ @Schema(description = "HTTP-TS流地址")
+ private StreamURL ts;
+ @Schema(description = "HTTPS-TS流地址")
+ private StreamURL https_ts;
+ @Schema(description = "Websocket-TS流地址")
+ private StreamURL ws_ts;
+ @Schema(description = "Websockets-TS流地址")
+ private StreamURL wss_ts;
+ @Schema(description = "RTMP流地址")
+ private StreamURL rtmp;
+ @Schema(description = "RTMPS流地址")
+ private StreamURL rtmps;
+ @Schema(description = "RTSP流地址")
+ private StreamURL rtsp;
+ @Schema(description = "RTSPS流地址")
+ private StreamURL rtsps;
+ @Schema(description = "RTC流地址")
+ private StreamURL rtc;
+
+ @Schema(description = "RTCS流地址")
+ private StreamURL rtcs;
+ @Schema(description = "流媒体ID")
+ private String mediaServerId;
+ @Schema(description = "流编码信息")
+ private Object tracks;
+ @Schema(description = "开始时间")
+ private String startTime;
+ @Schema(description = "结束时间")
+ private String endTime;
+ @Schema(description = "进度(录像下载使用)")
+ private double progress;
+
+ @Schema(description = "是否暂停(录像回放使用)")
+ private boolean pause;
+
+ 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 setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam, boolean isPlay) {
+ if (callIdParam != null) {
+ callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
+ }
+ String file = String.format("index/api/webrtc?app=%s&stream=%s&type=%s%s", app, stream, isPlay?"play":"push", callIdParam);
+ if (port > 0) {
+ this.rtc = new StreamURL("http", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.rtcs = new StreamURL("https", host, sslPort, file);
+ }
+ }
+
+ 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) {
+ this.rtmp = new StreamURL("rtmp", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.rtmps = new StreamURL("rtmps", host, sslPort, file);
+ }
+ }
+
+ public void setRtsp(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) {
+ this.rtsp = new StreamURL("rtsp", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.rtsps = new StreamURL("rtsps", host, sslPort, file);
+ }
+ }
+
+ public void setFlv(String host, int port, int sslPort, String app, String stream, String callIdParam) {
+ String file = String.format("%s/%s.live.flv%s", app, stream, callIdParam);
+ if (port > 0) {
+ this.flv = new StreamURL("http", host, port, file);
+ }
+ this.ws_flv = new StreamURL("ws", host, port, file);
+ if (sslPort > 0) {
+ this.https_flv = new StreamURL("https", host, sslPort, file);
+ this.wss_flv = new StreamURL("wss", host, sslPort, file);
+ }
+ }
+
+ public void setFmp4(String host, int port, int sslPort, String app, String stream, String callIdParam) {
+ String file = String.format("%s/%s.live.mp4%s", app, stream, callIdParam);
+ if (port > 0) {
+ this.fmp4 = new StreamURL("http", host, port, file);
+ this.ws_fmp4 = new StreamURL("ws", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.https_fmp4 = new StreamURL("https", host, sslPort, file);
+ this.wss_fmp4 = new StreamURL("wss", host, sslPort, file);
+ }
+ }
+
+ public void setHls(String host, int port, int sslPort, String app, String stream, String callIdParam) {
+ String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
+ if (port > 0) {
+ this.hls = new StreamURL("http", host, port, file);
+ this.ws_hls = new StreamURL("ws", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.https_hls = new StreamURL("https", host, sslPort, file);
+ this.wss_hls = new StreamURL("wss", host, sslPort, file);
+ }
+ }
+
+ public void setTs(String host, int port, int sslPort, String app, String stream, String callIdParam) {
+ String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
+
+ if (port > 0) {
+ this.ts = new StreamURL("http", host, port, file);
+ this.ws_ts = new StreamURL("ws", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.https_ts = new StreamURL("https", host, sslPort, file);
+ this.wss_ts = new StreamURL("wss", host, sslPort, file);
+ }
+ }
+
+ public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam) {
+ if (callIdParam != null) {
+ callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
+ }
+ String file = String.format("index/api/webrtc?app=%s&stream=%s&type=play%s", app, stream, callIdParam);
+ if (port > 0) {
+ this.rtc = new StreamURL("http", host, port, file);
+ }
+ if (sslPort > 0) {
+ this.rtcs = new StreamURL("https", host, sslPort, file);
+ }
+ }
+
+ public void channgeStreamIp(String localAddr) {
+ if (this.flv != null) {
+ this.flv.setHost(localAddr);
+ }
+ if (this.ws_flv != null ){
+ this.ws_flv.setHost(localAddr);
+ }
+ if (this.hls != null ) {
+ this.hls.setHost(localAddr);
+ }
+ if (this.ws_hls != null ) {
+ this.ws_hls.setHost(localAddr);
+ }
+ if (this.ts != null ) {
+ this.ts.setHost(localAddr);
+ }
+ if (this.ws_ts != null ) {
+ this.ws_ts.setHost(localAddr);
+ }
+ if (this.fmp4 != null ) {
+ this.fmp4.setHost(localAddr);
+ }
+ if (this.ws_fmp4 != null ) {
+ this.ws_fmp4.setHost(localAddr);
+ }
+ if (this.rtc != null ) {
+ this.rtc.setHost(localAddr);
+ }
+ if (this.https_flv != null) {
+ this.https_flv.setHost(localAddr);
+ }
+ if (this.wss_flv != null) {
+ this.wss_flv.setHost(localAddr);
+ }
+ if (this.https_hls != null) {
+ this.https_hls.setHost(localAddr);
+ }
+ if (this.wss_hls != null) {
+ this.wss_hls.setHost(localAddr);
+ }
+ if (this.wss_ts != null) {
+ this.wss_ts.setHost(localAddr);
+ }
+ if (this.https_fmp4 != null) {
+ this.https_fmp4.setHost(localAddr);
+ }
+ if (this.wss_fmp4 != null) {
+ this.wss_fmp4.setHost(localAddr);
+ }
+ if (this.rtcs != null) {
+ this.rtcs.setHost(localAddr);
+ }
+ if (this.rtsp != null) {
+ this.rtsp.setHost(localAddr);
+ }
+ if (this.rtsps != null) {
+ this.rtsps.setHost(localAddr);
+ }
+ if (this.rtmp != null) {
+ this.rtmp.setHost(localAddr);
+ }
+ if (this.rtmps != null) {
+ this.rtmps.setHost(localAddr);
+ }
+ }
+
+
+ public static class TransactionInfo{
+ public String callId;
+ public String localTag;
+ public String remoteTag;
+ public String branch;
+ }
+
+ 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 String getChannelId() {
+ return channelId;
+ }
+
+ public void setChannelId(String 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 String getMediaServerId() {
+ return mediaServerId;
+ }
+
+ public void setMediaServerId(String mediaServerId) {
+ this.mediaServerId = mediaServerId;
+ }
+
+ public Object getTracks() {
+ return tracks;
+ }
+
+ public void setTracks(Object tracks) {
+ this.tracks = tracks;
+ }
+
+ 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;
+ }
+
+ @Override
+ public StreamInfo clone() {
+ StreamInfo instance = null;
+ try{
+ instance = (StreamInfo)super.clone();
+ }catch(CloneNotSupportedException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return instance;
+ }
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/StreamURL.java b/riis-monitor/src/main/java/com/yfd/monitor/common/StreamURL.java
new file mode 100644
index 0000000..a663018
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/StreamURL.java
@@ -0,0 +1,80 @@
+package com.yfd.monitor.common;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serializable;
+
+
+@Schema(description = "流地址信息")
+public class StreamURL implements Serializable {
+
+ @Schema(description = "协议")
+ private String protocol;
+
+ @Schema(description = "主机地址")
+ private String host;
+
+ @Schema(description = "端口")
+ private int port = -1;
+
+ @Schema(description = "定位位置")
+ private String file;
+
+ @Schema(description = "拼接后的地址")
+ private String url;
+
+ public StreamURL() {
+ }
+
+ public StreamURL(String protocol, String host, int port, String file) {
+ this.protocol = protocol;
+ this.host = host;
+ this.port = port;
+ this.file = file;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ public String getUrl() {
+ return this.toString();
+ }
+
+ @Override
+ public String toString() {
+ if (protocol != null && host != null && port != -1 ) {
+ return String.format("%s://%s:%s/%s", protocol, host, port, file);
+ }else {
+ return null;
+ }
+ }
+}
diff --git a/riis-monitor/src/main/java/com/yfd/monitor/common/SystemAllInfo.java b/riis-monitor/src/main/java/com/yfd/monitor/common/SystemAllInfo.java
new file mode 100644
index 0000000..59c100e
--- /dev/null
+++ b/riis-monitor/src/main/java/com/yfd/monitor/common/SystemAllInfo.java
@@ -0,0 +1,54 @@
+package com.yfd.monitor.common;
+
+import java.util.List;
+
+public class SystemAllInfo {
+
+ private List