删除src文件
This commit is contained in:
parent
474e3a671c
commit
14e0048e3b
|
|
@ -1,68 +0,0 @@
|
|||
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;
|
||||
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.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.SessionCookieConfig;
|
||||
import jakarta.servlet.SessionTrackingMode;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* 启动类
|
||||
*/
|
||||
@ServletComponentScan("com.genersoft.iot.vmp.conf")
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableCaching
|
||||
@Slf4j
|
||||
public class VManageBootstrap extends SpringBootServletInitializer {
|
||||
|
||||
private static String[] args;
|
||||
private static ConfigurableApplicationContext context;
|
||||
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("获取版本信息失败");
|
||||
}else {
|
||||
log.info("构建版本: {}", gitUtil.getBuildVersion());
|
||||
log.info("构建时间: {}", gitUtil.getBuildDate());
|
||||
log.info("GIT信息: 分支: {}, ID: {}, 时间: {}", gitUtil.getBranch(), gitUtil.getCommitIdShort(), gitUtil.getCommitTime());
|
||||
}
|
||||
}
|
||||
// 项目重启
|
||||
public static void restart() {
|
||||
context.close();
|
||||
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(VManageBootstrap.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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
public class CivilCodePo {
|
||||
|
||||
private String code;
|
||||
|
||||
private String name;
|
||||
|
||||
private String parentCode;
|
||||
|
||||
public static CivilCodePo getInstance(String[] infoArray) {
|
||||
CivilCodePo civilCodePo = new CivilCodePo();
|
||||
civilCodePo.setCode(infoArray[0]);
|
||||
civilCodePo.setName(infoArray[1]);
|
||||
if (!ObjectUtils.isEmpty(infoArray[2])) {
|
||||
civilCodePo.setParentCode(infoArray[2]);
|
||||
}
|
||||
return civilCodePo;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getParentCode() {
|
||||
return parentCode;
|
||||
}
|
||||
|
||||
public void setParentCode(String parentCode) {
|
||||
this.parentCode = parentCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
public interface CommonCallback<T>{
|
||||
public void run(T t);
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
|
||||
public interface DeviceStatusCallback {
|
||||
public void run(String deviceId, SipTransactionInfo transactionInfo);
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 记录每次发送invite消息的状态
|
||||
*/
|
||||
@Data
|
||||
public class InviteInfo {
|
||||
|
||||
private String deviceId;
|
||||
|
||||
private Integer 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;
|
||||
|
||||
private String mediaServerId;
|
||||
|
||||
private Long expirationTime;
|
||||
|
||||
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, Boolean record) {
|
||||
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);
|
||||
inviteInfo.setMediaServerId(mediaServerId);
|
||||
inviteInfo.setRecord(record);
|
||||
return inviteInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
/**
|
||||
* 标识invite消息发出后的各个状态,
|
||||
* 收到ok钱停止invite发送cancel,
|
||||
* 收到200ok后发送BYE停止invite
|
||||
*/
|
||||
public enum InviteSessionStatus {
|
||||
ready,
|
||||
ok,
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
public enum InviteSessionType {
|
||||
PLAY,
|
||||
PLAYBACK,
|
||||
DOWNLOAD,
|
||||
BROADCAST,
|
||||
TALK
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
public class RemoteAddressInfo {
|
||||
private String ip;
|
||||
private int port;
|
||||
|
||||
public RemoteAddressInfo(String ip, int port) {
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 统计信息
|
||||
*/
|
||||
@Data
|
||||
public class StatisticsInfo {
|
||||
|
||||
private long id;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 分支
|
||||
*/
|
||||
private String branch;
|
||||
|
||||
/**
|
||||
* git提交版本ID
|
||||
*/
|
||||
private String gitCommitId;
|
||||
|
||||
/**
|
||||
* git地址
|
||||
*/
|
||||
private String gitUrl;
|
||||
|
||||
/**
|
||||
* 构建版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 操作系统名称
|
||||
*/
|
||||
private String osName;
|
||||
|
||||
/**
|
||||
* 是否是docker环境
|
||||
*/
|
||||
private Boolean docker;
|
||||
|
||||
/**
|
||||
* 架构
|
||||
*/
|
||||
private String arch;
|
||||
|
||||
/**
|
||||
* jdk版本
|
||||
*/
|
||||
private String jdkVersion;
|
||||
|
||||
/**
|
||||
* redis版本
|
||||
*/
|
||||
private String redisVersion;
|
||||
|
||||
/**
|
||||
* sql数据库版本
|
||||
*/
|
||||
private String sqlVersion;
|
||||
|
||||
/**
|
||||
* sql数据库类型, mysql/postgresql/金仓等
|
||||
*/
|
||||
private String sqlType;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private String time;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StatisticsInfo{" +
|
||||
"id=" + id +
|
||||
", deviceId='" + deviceId + '\'' +
|
||||
", branch='" + branch + '\'' +
|
||||
", gitCommitId='" + gitCommitId + '\'' +
|
||||
", gitUrl='" + gitUrl + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
", osName='" + osName + '\'' +
|
||||
", docker=" + docker +
|
||||
", arch='" + arch + '\'' +
|
||||
", jdkVersion='" + jdkVersion + '\'' +
|
||||
", redisVersion='" + redisVersion + '\'' +
|
||||
", sqlVersion='" + sqlVersion + '\'' +
|
||||
", sqlType='" + sqlType + '\'' +
|
||||
", time='" + time + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,372 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
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{
|
||||
|
||||
@Schema(description = "应用名")
|
||||
private String app;
|
||||
@Schema(description = "流ID")
|
||||
private String stream;
|
||||
@Schema(description = "设备编号")
|
||||
private String deviceId;
|
||||
@Schema(description = "通道ID")
|
||||
private Integer 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 = "流媒体节点")
|
||||
private MediaServer mediaServer;
|
||||
@Schema(description = "流编码信息")
|
||||
private MediaInfo mediaInfo;
|
||||
@Schema(description = "开始时间")
|
||||
private String startTime;
|
||||
@Schema(description = "结束时间")
|
||||
private String endTime;
|
||||
@Schema(description = "时长(回放时使用)")
|
||||
private Double duration;
|
||||
@Schema(description = "进度(录像下载使用)")
|
||||
private double progress;
|
||||
@Schema(description = "文件下载地址(录像下载使用)")
|
||||
private DownloadFileInfo downLoadFilePath;
|
||||
@Schema(description = "点播请求的callId")
|
||||
private String callId;
|
||||
|
||||
@Schema(description = "是否暂停(录像回放使用)")
|
||||
private boolean pause;
|
||||
|
||||
@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;
|
||||
|
||||
@Schema(description = "流绑定的流媒体操作key")
|
||||
private String key;
|
||||
|
||||
public void setRtmp(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s%s", app, stream, callIdParam);
|
||||
if (port != null && port > 0) {
|
||||
this.rtmp = new StreamURL("rtmp", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.rtmps = new StreamURL("rtmps", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setRtsp(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s%s", app, stream, callIdParam);
|
||||
if (port != null && port > 0) {
|
||||
this.rtsp = new StreamURL("rtsp", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.rtsps = new StreamURL("rtsps", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFlv(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.flv = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_flv = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsFlv(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.ws_flv = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_flv = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFmp4(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.fmp4 = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_fmp4 = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsMp4(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.ws_fmp4 = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_fmp4 = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setHls(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
|
||||
if (port != null && port > 0) {
|
||||
this.hls = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_hls = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsHls(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
|
||||
if (port != null && port > 0) {
|
||||
this.ws_hls = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_hls = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTs(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
|
||||
|
||||
if (port != null && port > 0) {
|
||||
this.ts = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_ts = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsTs(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
|
||||
|
||||
if (port != null && port > 0) {
|
||||
this.ws_ts = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_ts = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setRtc(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam, boolean isPlay) {
|
||||
if (callIdParam != null) {
|
||||
callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
|
||||
}
|
||||
// String file = String.format("%s/%s?type=%s%s", app, stream, isPlay?"play":"push", callIdParam);
|
||||
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 changeStreamIp(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;
|
||||
|
||||
|
||||
@Override
|
||||
public StreamInfo clone() {
|
||||
StreamInfo instance = null;
|
||||
try{
|
||||
instance = (StreamInfo)super.clone();
|
||||
if (this.flv != null) {
|
||||
instance.flv=this.flv.clone();
|
||||
}
|
||||
if (this.ws_flv != null ){
|
||||
instance.ws_flv= this.ws_flv.clone();
|
||||
}
|
||||
if (this.hls != null ) {
|
||||
instance.hls= this.hls.clone();
|
||||
}
|
||||
if (this.ws_hls != null ) {
|
||||
instance.ws_hls= this.ws_hls.clone();
|
||||
}
|
||||
if (this.ts != null ) {
|
||||
instance.ts= this.ts.clone();
|
||||
}
|
||||
if (this.ws_ts != null ) {
|
||||
instance.ws_ts= this.ws_ts.clone();
|
||||
}
|
||||
if (this.fmp4 != null ) {
|
||||
instance.fmp4= this.fmp4.clone();
|
||||
}
|
||||
if (this.ws_fmp4 != null ) {
|
||||
instance.ws_fmp4= this.ws_fmp4.clone();
|
||||
}
|
||||
if (this.rtc != null ) {
|
||||
instance.rtc= this.rtc.clone();
|
||||
}
|
||||
if (this.https_flv != null) {
|
||||
instance.https_flv= this.https_flv.clone();
|
||||
}
|
||||
if (this.wss_flv != null) {
|
||||
instance.wss_flv= this.wss_flv.clone();
|
||||
}
|
||||
if (this.https_hls != null) {
|
||||
instance.https_hls= this.https_hls.clone();
|
||||
}
|
||||
if (this.wss_hls != null) {
|
||||
instance.wss_hls= this.wss_hls.clone();
|
||||
}
|
||||
if (this.wss_ts != null) {
|
||||
instance.wss_ts= this.wss_ts.clone();
|
||||
}
|
||||
if (this.https_fmp4 != null) {
|
||||
instance.https_fmp4= this.https_fmp4.clone();
|
||||
}
|
||||
if (this.wss_fmp4 != null) {
|
||||
instance.wss_fmp4= this.wss_fmp4.clone();
|
||||
}
|
||||
if (this.rtcs != null) {
|
||||
instance.rtcs= this.rtcs.clone();
|
||||
}
|
||||
if (this.rtsp != null) {
|
||||
instance.rtsp= this.rtsp.clone();
|
||||
}
|
||||
if (this.rtsps != null) {
|
||||
instance.rtsps= this.rtsps.clone();
|
||||
}
|
||||
if (this.rtmp != null) {
|
||||
instance.rtmp= this.rtmp.clone();
|
||||
}
|
||||
if (this.rtmps != null) {
|
||||
instance.rtmps= this.rtmps.clone();
|
||||
}
|
||||
}catch(CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@Schema(description = "流地址信息")
|
||||
public class StreamURL implements Serializable,Cloneable {
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public StreamURL clone() throws CloneNotSupportedException {
|
||||
return (StreamURL) super.clone();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
|
||||
public interface SubscribeCallback{
|
||||
public void run(String deviceId, SipTransactionInfo transactionInfo);
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SystemAllInfo {
|
||||
|
||||
private List<Object> cpu;
|
||||
private List<Object> mem;
|
||||
private List<Object> net;
|
||||
|
||||
private long netTotal;
|
||||
|
||||
private Object disk;
|
||||
|
||||
public List<Object> getCpu() {
|
||||
return cpu;
|
||||
}
|
||||
|
||||
public void setCpu(List<Object> cpu) {
|
||||
this.cpu = cpu;
|
||||
}
|
||||
|
||||
public List<Object> getMem() {
|
||||
return mem;
|
||||
}
|
||||
|
||||
public void setMem(List<Object> mem) {
|
||||
this.mem = mem;
|
||||
}
|
||||
|
||||
public List<Object> getNet() {
|
||||
return net;
|
||||
}
|
||||
|
||||
public void setNet(List<Object> net) {
|
||||
this.net = net;
|
||||
}
|
||||
|
||||
public Object getDisk() {
|
||||
return disk;
|
||||
}
|
||||
|
||||
public void setDisk(Object disk) {
|
||||
this.disk = disk;
|
||||
}
|
||||
|
||||
public long getNetTotal() {
|
||||
return netTotal;
|
||||
}
|
||||
|
||||
public void setNetTotal(long netTotal) {
|
||||
this.netTotal = netTotal;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
|
||||
public class VersionPo {
|
||||
/**
|
||||
* git的全版本号
|
||||
*/
|
||||
@JSONField(name="GIT_Revision")
|
||||
private String GIT_Revision;
|
||||
/**
|
||||
* maven版本
|
||||
*/
|
||||
@JSONField(name = "Create_By")
|
||||
private String Create_By;
|
||||
/**
|
||||
* git的分支
|
||||
*/
|
||||
@JSONField(name = "GIT_BRANCH")
|
||||
private String GIT_BRANCH;
|
||||
/**
|
||||
* git的url
|
||||
*/
|
||||
@JSONField(name = "GIT_URL")
|
||||
private String GIT_URL;
|
||||
/**
|
||||
* 构建日期
|
||||
*/
|
||||
@JSONField(name = "BUILD_DATE")
|
||||
private String BUILD_DATE;
|
||||
/**
|
||||
* 构建日期
|
||||
*/
|
||||
@JSONField(name = "GIT_DATE")
|
||||
private String GIT_DATE;
|
||||
/**
|
||||
* 项目名称 配合pom使用
|
||||
*/
|
||||
@JSONField(name = "artifactId")
|
||||
private String artifactId;
|
||||
/**
|
||||
* git局部版本号
|
||||
*/
|
||||
@JSONField(name = "GIT_Revision_SHORT")
|
||||
private String GIT_Revision_SHORT;
|
||||
/**
|
||||
* 项目的版本如2.0.1.0 配合pom使用
|
||||
*/
|
||||
@JSONField(name = "version")
|
||||
private String version;
|
||||
/**
|
||||
* 子系统名称
|
||||
*/
|
||||
@JSONField(name = "project")
|
||||
private String project;
|
||||
/**
|
||||
* jdk版本
|
||||
*/
|
||||
@JSONField(name="Build_Jdk")
|
||||
private String Build_Jdk;
|
||||
|
||||
public void setGIT_Revision(String GIT_Revision) {
|
||||
this.GIT_Revision = GIT_Revision;
|
||||
}
|
||||
|
||||
public void setCreate_By(String create_By) {
|
||||
Create_By = create_By;
|
||||
}
|
||||
|
||||
public void setGIT_BRANCH(String GIT_BRANCH) {
|
||||
this.GIT_BRANCH = GIT_BRANCH;
|
||||
}
|
||||
|
||||
public void setGIT_URL(String GIT_URL) {
|
||||
this.GIT_URL = GIT_URL;
|
||||
}
|
||||
|
||||
public void setBUILD_DATE(String BUILD_DATE) {
|
||||
this.BUILD_DATE = BUILD_DATE;
|
||||
}
|
||||
|
||||
public void setArtifactId(String artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
public void setGIT_Revision_SHORT(String GIT_Revision_SHORT) {
|
||||
this.GIT_Revision_SHORT = GIT_Revision_SHORT;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setProject(String project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public void setBuild_Jdk(String build_Jdk) {
|
||||
Build_Jdk = build_Jdk;
|
||||
}
|
||||
|
||||
public String getGIT_Revision() {
|
||||
return GIT_Revision;
|
||||
}
|
||||
|
||||
public String getCreate_By() {
|
||||
return Create_By;
|
||||
}
|
||||
|
||||
public String getGIT_BRANCH() {
|
||||
return GIT_BRANCH;
|
||||
}
|
||||
|
||||
public String getGIT_URL() {
|
||||
return GIT_URL;
|
||||
}
|
||||
|
||||
public String getBUILD_DATE() {
|
||||
return BUILD_DATE;
|
||||
}
|
||||
|
||||
public String getArtifactId() {
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
public String getGIT_Revision_SHORT() {
|
||||
return GIT_Revision_SHORT;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public String getBuild_Jdk() {
|
||||
return Build_Jdk;
|
||||
}
|
||||
|
||||
public String getGIT_DATE() {
|
||||
return GIT_DATE;
|
||||
}
|
||||
|
||||
public void setGIT_DATE(String GIT_DATE) {
|
||||
this.GIT_DATE = GIT_DATE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
/**
|
||||
* @description: 定义常量
|
||||
* @author: swwheihei
|
||||
* @date: 2019年5月30日 下午3:04:04
|
||||
*
|
||||
*/
|
||||
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:";
|
||||
|
||||
public static final String ONLINE_MEDIA_SERVERS_PREFIX = "VMP_ONLINE_MEDIA_SERVERS:";
|
||||
|
||||
public static final String DEVICE_PREFIX = "VMP_DEVICE_INFO";
|
||||
|
||||
public static final String INVITE_PREFIX = "VMP_GB_INVITE_INFO";
|
||||
|
||||
public static final String SEND_RTP_PORT = "VM_SEND_RTP_PORT:";
|
||||
public static final String SEND_RTP_INFO_CALLID = "VMP_SEND_RTP_INFO:CALL_ID:";
|
||||
public static final String SEND_RTP_INFO_STREAM = "VMP_SEND_RTP_INFO:STREAM:";
|
||||
public static final String SEND_RTP_INFO_CHANNEL = "VMP_SEND_RTP_INFO:CHANNEL:";
|
||||
|
||||
public static final String SIP_INVITE_SESSION = "VMP_SIP_INVITE_SESSION_INFO:";
|
||||
public static final String SIP_INVITE_SESSION_CALL_ID = SIP_INVITE_SESSION + "CALL_ID:";
|
||||
public static final String SIP_INVITE_SESSION_STREAM = SIP_INVITE_SESSION + "STREAM:";
|
||||
|
||||
public static final String MEDIA_STREAM_AUTHORITY = "VMP_MEDIA_STREAM_AUTHORITY";
|
||||
|
||||
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
|
||||
|
||||
public static final String SIP_SUBSCRIBE_PREFIX = "VMP_SIP_SUBSCRIBE_";
|
||||
|
||||
public static final String SYSTEM_INFO_CPU_PREFIX = "VMP_SYSTEM_INFO_CPU_";
|
||||
|
||||
public static final String SYSTEM_INFO_MEM_PREFIX = "VMP_SYSTEM_INFO_MEM_";
|
||||
|
||||
public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
|
||||
|
||||
public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_";
|
||||
public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_";
|
||||
|
||||
public static final String PUSH_STREAM_LIST = "VMP_PUSH_STREAM_LIST_";
|
||||
public static final String WAITE_SEND_PUSH_STREAM = "VMP_WAITE_SEND_PUSH_STREAM:";
|
||||
public static final String START_SEND_PUSH_STREAM = "VMP_START_SEND_PUSH_STREAM:";
|
||||
public static final String SSE_TASK_KEY = "SSE_TASK_";
|
||||
public static final String DRAW_THIN_PROCESS_PREFIX = "VMP_DRAW_THIN_PROCESS_";
|
||||
|
||||
|
||||
|
||||
|
||||
//************************** redis 消息*********************************
|
||||
|
||||
/**
|
||||
* 流变化的通知
|
||||
*/
|
||||
public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
|
||||
|
||||
/**
|
||||
* 接收推流设备的GPS变化通知
|
||||
*/
|
||||
public static final String VM_MSG_GPS = "VM_MSG_GPS";
|
||||
|
||||
/**
|
||||
* 接收推流设备的GPS变化通知
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
|
||||
/**
|
||||
* 接收推流设备列表更新变化通知
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE";
|
||||
|
||||
/**
|
||||
* 请求同步三方组织结构
|
||||
*/
|
||||
public static final String VM_MSG_GROUP_LIST_REQUEST = "VM_MSG_GROUP_LIST_REQUEST";
|
||||
|
||||
/**
|
||||
* 同步三方组织结构回复
|
||||
*/
|
||||
public static final String VM_MSG_GROUP_LIST_RESPONSE = "VM_MSG_GROUP_LIST_RESPONSE";
|
||||
|
||||
/**
|
||||
* 同步三方组织结构回复
|
||||
*/
|
||||
public static final String VM_MSG_GROUP_LIST_CHANGE = "VM_MSG_GROUP_LIST_CHANGE";
|
||||
|
||||
/**
|
||||
* redis 消息通知设备推流到平台
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
|
||||
|
||||
/**
|
||||
* redis 消息通知上级平台开始观看流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_START_PLAY_NOTIFY = "VM_MSG_STREAM_START_PLAY_NOTIFY";
|
||||
|
||||
/**
|
||||
* redis 消息通知上级平台停止观看流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_STOP_PLAY_NOTIFY = "VM_MSG_STREAM_STOP_PLAY_NOTIFY";
|
||||
|
||||
/**
|
||||
* redis 消息接收关闭一个推流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_CLOSE_REQUESTED = "VM_MSG_STREAM_PUSH_CLOSE_REQUESTED";
|
||||
|
||||
|
||||
/**
|
||||
* redis 消息通知平台通知设备推流结果
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_RESPONSE = "VM_MSG_STREAM_PUSH_RESPONSE";
|
||||
|
||||
/**
|
||||
* redis 通知平台关闭推流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_CLOSE = "VM_MSG_STREAM_PUSH_CLOSE";
|
||||
|
||||
/**
|
||||
* redis 消息请求所有的在线通道
|
||||
*/
|
||||
public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED";
|
||||
|
||||
/**
|
||||
* 报警订阅的通知(收到报警向redis发出通知)
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm";
|
||||
|
||||
|
||||
/**
|
||||
* 报警通知的发送 (收到redis发出的通知,转发给其他平台)
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive";
|
||||
|
||||
/**
|
||||
* 设备状态订阅的通知
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
|
||||
|
||||
|
||||
|
||||
|
||||
//************************** 第三方 ****************************************
|
||||
|
||||
public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
|
||||
public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
|
||||
public static final String WVP_OTHER_SEND_RTP_INFO = "VMP_OTHER_SEND_RTP_INFO_";
|
||||
public static final String WVP_OTHER_SEND_PS_INFO = "VMP_OTHER_SEND_PS_INFO_";
|
||||
public static final String WVP_OTHER_RECEIVE_RTP_INFO = "VMP_OTHER_RECEIVE_RTP_INFO_";
|
||||
public static final String WVP_OTHER_RECEIVE_PS_INFO = "VMP_OTHER_RECEIVE_PS_INFO_";
|
||||
|
||||
/**
|
||||
* Redis Const
|
||||
* 设备录像信息结果前缀
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_PRE = "GB_RECORD_INFO_RES_";
|
||||
/**
|
||||
* Redis Const
|
||||
* 设备录像信息结果前缀
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:";
|
||||
|
||||
//************************** 1078 ****************************************
|
||||
|
||||
|
||||
public static final String INVITE_INFO_1078_POSITION = "INVITE_INFO_1078_POSITION:";
|
||||
public static final String INVITE_INFO_1078_PLAY = "INVITE_INFO_1078_PLAY:";
|
||||
public static final String INVITE_INFO_1078_PLAYBACK = "INVITE_INFO_1078_PLAYBACK:";
|
||||
public static final String INVITE_INFO_1078_TALK = "INVITE_INFO_1078_TALK:";
|
||||
|
||||
|
||||
public static final String RECORD_LIST_1078 = "RECORD_LIST_1078:";
|
||||
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common.enums;
|
||||
|
||||
/**
|
||||
* 支持的通道数据类型
|
||||
*/
|
||||
|
||||
public class ChannelDataType {
|
||||
|
||||
public final static int GB28181 = 1;
|
||||
public final static int STREAM_PUSH = 2;
|
||||
public final static int STREAM_PROXY = 3;
|
||||
public final static int JT_1078 = 200;
|
||||
|
||||
public final static String PLAY_SERVICE = "sourceChannelPlayService";
|
||||
public final static String PLAYBACK_SERVICE = "sourceChannelPlaybackService";
|
||||
public final static String DOWNLOAD_SERVICE = "sourceChannelDownloadService";
|
||||
public final static String PTZ_SERVICE = "sourceChannelPTZService";
|
||||
|
||||
|
||||
public static String getDateTypeDesc(Integer dataType) {
|
||||
if (dataType == null) {
|
||||
return "未知";
|
||||
}
|
||||
return switch (dataType) {
|
||||
case ChannelDataType.GB28181 -> "国标28181";
|
||||
case ChannelDataType.STREAM_PUSH -> "推流设备";
|
||||
case ChannelDataType.STREAM_PROXY -> "拉流代理";
|
||||
case ChannelDataType.JT_1078 -> "部标设备";
|
||||
default -> "未知";
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
package com.genersoft.iot.vmp.common.enums;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
||||
/**
|
||||
* @author gaofuwang
|
||||
* @date 2023/01/18/ 10:09:00
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum DeviceControlType {
|
||||
|
||||
/**
|
||||
* 云台控制
|
||||
* 上下左右,预置位,扫描,辅助功能,巡航
|
||||
*/
|
||||
PTZ("PTZCmd","云台控制"),
|
||||
/**
|
||||
* 远程启动
|
||||
*/
|
||||
TELE_BOOT("TeleBoot","远程启动"),
|
||||
/**
|
||||
* 录像控制
|
||||
*/
|
||||
RECORD("RecordCmd","录像控制"),
|
||||
/**
|
||||
* 布防撤防
|
||||
*/
|
||||
GUARD("GuardCmd","布防撤防"),
|
||||
/**
|
||||
* 告警控制
|
||||
*/
|
||||
ALARM("AlarmCmd","告警控制"),
|
||||
/**
|
||||
* 强制关键帧
|
||||
*/
|
||||
I_FRAME("IFameCmd","强制关键帧"),
|
||||
/**
|
||||
* 拉框放大
|
||||
*/
|
||||
DRAG_ZOOM_IN("DragZoomIn","拉框放大"),
|
||||
/**
|
||||
* 拉框缩小
|
||||
*/
|
||||
DRAG_ZOOM_OUT("DragZoomOut","拉框缩小"),
|
||||
/**
|
||||
* 看守位
|
||||
*/
|
||||
HOME_POSITION("HomePosition","看守位");
|
||||
|
||||
private final String val;
|
||||
|
||||
private final String desc;
|
||||
|
||||
DeviceControlType(String val, String desc) {
|
||||
this.val = val;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static DeviceControlType typeOf(Element rootElement) {
|
||||
for (DeviceControlType item : DeviceControlType.values()) {
|
||||
if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.common.CivilCodePo;
|
||||
import com.genersoft.iot.vmp.utils.CivilCodeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* 启动时读取行政区划表
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@Order(value=15)
|
||||
public class CivilCodeFileConf implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
if (ObjectUtils.isEmpty(userSetting.getCivilCodeFile())) {
|
||||
log.warn("[行政区划] 文件未设置,可能造成目录刷新结果不完整");
|
||||
return;
|
||||
}
|
||||
InputStream inputStream;
|
||||
if (userSetting.getCivilCodeFile().startsWith("classpath:")){
|
||||
String filePath = userSetting.getCivilCodeFile().substring("classpath:".length());
|
||||
ClassPathResource civilCodeFile = new ClassPathResource(filePath);
|
||||
if (!civilCodeFile.exists()) {
|
||||
log.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
|
||||
return;
|
||||
}
|
||||
inputStream = civilCodeFile.getInputStream();
|
||||
|
||||
}else {
|
||||
File civilCodeFile = new File(userSetting.getCivilCodeFile());
|
||||
if (!civilCodeFile.exists()) {
|
||||
log.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
|
||||
return;
|
||||
}
|
||||
inputStream = Files.newInputStream(civilCodeFile.toPath());
|
||||
}
|
||||
|
||||
BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
int index = -1;
|
||||
String line;
|
||||
while ((line = inputStreamReader.readLine()) != null) {
|
||||
index ++;
|
||||
if (index == 0) {
|
||||
continue;
|
||||
}
|
||||
String[] infoArray = line.split(",");
|
||||
CivilCodePo civilCodePo = CivilCodePo.getInstance(infoArray);
|
||||
CivilCodeUtil.INSTANCE.add(civilCodePo);
|
||||
}
|
||||
inputStreamReader.close();
|
||||
inputStream.close();
|
||||
if (CivilCodeUtil.INSTANCE.isEmpty()) {
|
||||
log.warn("[行政区划] 文件内容为空,可能造成目录刷新结果不完整");
|
||||
}else {
|
||||
log.info("[行政区划] 加载成功,共加载数据{}条", CivilCodeUtil.INSTANCE.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 录像文件定时删除
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CloudRecordTimer {
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private CloudRecordServiceMapper cloudRecordServiceMapper;
|
||||
|
||||
/**
|
||||
* 定时查询待删除的录像文件
|
||||
*/
|
||||
// @Scheduled(fixedRate = 10000) //每五秒执行一次,方便测试
|
||||
@Scheduled(cron = "0 0 0 * * ?") //每天的0点执行
|
||||
public void execute(){
|
||||
log.info("[录像文件定时清理] 开始清理过期录像文件");
|
||||
// 获取配置了assist的流媒体节点
|
||||
List<MediaServer> mediaServerItemList = mediaServerService.getAllOnline();
|
||||
if (mediaServerItemList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
long result = 0;
|
||||
for (MediaServer mediaServerItem : mediaServerItemList) {
|
||||
|
||||
Calendar lastCalendar = Calendar.getInstance();
|
||||
if (mediaServerItem.getRecordDay() > 0) {
|
||||
lastCalendar.setTime(new Date());
|
||||
// 获取保存的最后截至日[期,因为每个节点都有一个日期,也就是支持每个节点设置不同的保存日期,
|
||||
lastCalendar.add(Calendar.DAY_OF_MONTH, -mediaServerItem.getRecordDay());
|
||||
Long lastDate = lastCalendar.getTimeInMillis();
|
||||
|
||||
// 获取到截至日期之前的录像文件列表,文件列表满足未被收藏和保持的。这两个字段目前共能一致,
|
||||
// 为我自己业务系统相关的代码,大家使用的时候直接使用收藏(collect)这一个类型即可
|
||||
List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.queryRecordListForDelete(lastDate, mediaServerItem.getId());
|
||||
if (cloudRecordItemList.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// TODO 后续可以删除空了的过期日期文件夹
|
||||
for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
|
||||
String date = new File(cloudRecordItem.getFilePath()).getParentFile().getName();
|
||||
try {
|
||||
boolean deleteResult = mediaServerService.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(),
|
||||
cloudRecordItem.getStream(), date, cloudRecordItem.getFileName());
|
||||
if (deleteResult) {
|
||||
log.warn("[录像文件定时清理] 删除磁盘文件成功: {}", cloudRecordItem.getFilePath());
|
||||
}
|
||||
}catch (ControllerException ignored) {}
|
||||
|
||||
}
|
||||
result += cloudRecordServiceMapper.deleteList(cloudRecordItemList);
|
||||
}
|
||||
}
|
||||
log.info("[录像文件定时清理] 共清理{}个过期录像文件", result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 动态定时任务
|
||||
* @author lin
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DynamicTask {
|
||||
|
||||
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||
|
||||
private final Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void DynamicTask() {
|
||||
threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
threadPoolTaskScheduler.setPoolSize(300);
|
||||
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
|
||||
threadPoolTaskScheduler.setAwaitTerminationSeconds(10);
|
||||
threadPoolTaskScheduler.setThreadNamePrefix("dynamicTask-");
|
||||
threadPoolTaskScheduler.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环执行的任务
|
||||
* @param key 任务ID
|
||||
* @param task 任务
|
||||
* @param cycleForCatalog 间隔 毫秒
|
||||
* @return
|
||||
*/
|
||||
public void startCron(String key, Runnable task, int cycleForCatalog) {
|
||||
if(ObjectUtils.isEmpty(key)) {
|
||||
return;
|
||||
}
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
if (future != null) {
|
||||
if (future.isCancelled()) {
|
||||
log.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
} else {
|
||||
log.debug("任务【{}】已存在且已启动!!!", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
|
||||
|
||||
future = threadPoolTaskScheduler.scheduleAtFixedRate(task, new Date(System.currentTimeMillis() + cycleForCatalog), cycleForCatalog);
|
||||
if (future != null){
|
||||
futureMap.put(key, future);
|
||||
runnableMap.put(key, task);
|
||||
log.debug("任务【{}】启动成功!!!", key);
|
||||
}else {
|
||||
log.debug("任务【{}】启动失败!!!", key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延时任务
|
||||
* @param key 任务ID
|
||||
* @param task 任务
|
||||
* @param delay 延时 /毫秒
|
||||
* @return
|
||||
*/
|
||||
public void startDelay(String key, Runnable task, int delay) {
|
||||
if(ObjectUtils.isEmpty(key)) {
|
||||
return;
|
||||
}
|
||||
stop(key);
|
||||
|
||||
// 获取执行的时刻
|
||||
Instant startInstant = Instant.now().plusMillis(TimeUnit.MILLISECONDS.toMillis(delay));
|
||||
|
||||
ScheduledFuture future = futureMap.get(key);
|
||||
if (future != null) {
|
||||
if (future.isCancelled()) {
|
||||
log.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
} else {
|
||||
log.debug("任务【{}】已存在且已启动!!!", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
|
||||
future = threadPoolTaskScheduler.schedule(task, startInstant);
|
||||
if (future != null){
|
||||
futureMap.put(key, future);
|
||||
runnableMap.put(key, task);
|
||||
log.debug("任务【{}】启动成功!!!", key);
|
||||
}else {
|
||||
log.debug("任务【{}】启动失败!!!", key);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean stop(String key) {
|
||||
if(ObjectUtils.isEmpty(key)) {
|
||||
return false;
|
||||
}
|
||||
boolean result = false;
|
||||
if (!ObjectUtils.isEmpty(futureMap.get(key)) && !futureMap.get(key).isCancelled() && !futureMap.get(key).isDone()) {
|
||||
result = futureMap.get(key).cancel(false);
|
||||
futureMap.remove(key);
|
||||
runnableMap.remove(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean contains(String key) {
|
||||
if(ObjectUtils.isEmpty(key)) {
|
||||
return false;
|
||||
}
|
||||
return futureMap.get(key) != null;
|
||||
}
|
||||
|
||||
public Set<String> getAllKeys() {
|
||||
return futureMap.keySet();
|
||||
}
|
||||
|
||||
public Runnable get(String key) {
|
||||
if(ObjectUtils.isEmpty(key)) {
|
||||
return null;
|
||||
}
|
||||
return runnableMap.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每五分钟检查失效的任务,并移除
|
||||
*/
|
||||
@Scheduled(cron="0 0/5 * * * ?")
|
||||
public void execute(){
|
||||
if (futureMap.size() > 0) {
|
||||
for (String key : futureMap.keySet()) {
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
if (future.isDone() || future.isCancelled()) {
|
||||
futureMap.remove(key);
|
||||
runnableMap.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAlive(String key) {
|
||||
return futureMap.get(key) != null && !futureMap.get(key).isDone() && !futureMap.get(key).isCancelled();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 默认异常处理
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public WVPResult<String> exceptionHandler(Exception e) {
|
||||
log.error("[全局异常]: ", e);
|
||||
return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认异常处理
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(IllegalStateException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public WVPResult<String> exceptionHandler(IllegalStateException e) {
|
||||
return WVPResult.fail(ErrorCode.ERROR400);
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认异常处理
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public WVPResult<String> exceptionHandler(HttpRequestMethodNotSupportedException e) {
|
||||
return WVPResult.fail(ErrorCode.ERROR400);
|
||||
}
|
||||
/**
|
||||
* 断言异常处理
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public WVPResult<String> exceptionHandler(IllegalArgumentException e) {
|
||||
return WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自定义异常处理, 处理controller中返回的错误
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(ControllerException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ResponseEntity<WVPResult<String>> exceptionHandler(ControllerException e) {
|
||||
return new ResponseEntity<>(WVPResult.fail(e.getCode(), e.getMsg()), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登陆失败
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(BadCredentialsException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public ResponseEntity<WVPResult<String>> exceptionHandler(BadCredentialsException e) {
|
||||
return new ResponseEntity<>(WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage()), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* 全局统一返回结果
|
||||
* @author lin
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supports(@NotNull MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType, @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) {
|
||||
// 排除api文档的接口,这个接口不需要统一
|
||||
String[] excludePath = {"/v3/api-docs","/api/v1","/index/hook","/api/video-"};
|
||||
for (String path : excludePath) {
|
||||
if (request.getURI().getPath().startsWith(path)) {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedContentType.equals(MediaType.parseMediaType("application/x-protobuf"))) {
|
||||
return body;
|
||||
}
|
||||
|
||||
if (body instanceof WVPResult) {
|
||||
return body;
|
||||
}
|
||||
|
||||
if (body instanceof ErrorCode) {
|
||||
ErrorCode errorCode = (ErrorCode) body;
|
||||
return new WVPResult<>(errorCode.getCode(), errorCode.getMsg(), null);
|
||||
}
|
||||
|
||||
if (body instanceof String) {
|
||||
return JSON.toJSONString(WVPResult.success(body));
|
||||
}
|
||||
|
||||
if (body instanceof LinkedHashMap) {
|
||||
LinkedHashMap<String, Object> bodyMap = (LinkedHashMap<String, Object>) body;
|
||||
if (bodyMap.get("status") != null && (Integer)bodyMap.get("status") != 200) {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
return WVPResult.success(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 防止返回string时出错
|
||||
* @return
|
||||
*/
|
||||
/*@Bean
|
||||
public HttpMessageConverters custHttpMessageConverter() {
|
||||
return new HttpMessageConverters(new FastJsonHttpMessageConverter());
|
||||
}*/
|
||||
}
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
@Configuration("mediaConfig")
|
||||
@Order(0)
|
||||
@Data
|
||||
public class MediaConfig{
|
||||
|
||||
// 修改必须配置,不再支持自动获取
|
||||
@Value("${media.id}")
|
||||
private String id;
|
||||
|
||||
@Value("${media.ip}")
|
||||
private String ip;
|
||||
|
||||
@Value("${media.wan_ip:}")
|
||||
private String wanIp;
|
||||
|
||||
@Value("${media.hook-ip:127.0.0.1}")
|
||||
private String hookIp;
|
||||
|
||||
@Value("${sip.domain}")
|
||||
private String sipDomain;
|
||||
|
||||
@Value("${media.sdp-ip:${media.wan_ip:}}")
|
||||
private String sdpIp;
|
||||
|
||||
@Value("${media.stream-ip:${media.wan_ip:}}")
|
||||
private String streamIp;
|
||||
|
||||
@Value("${media.http-port:0}")
|
||||
private Integer httpPort;
|
||||
|
||||
@Value("${media.flv-port:0}")
|
||||
private Integer flvPort = 0;
|
||||
|
||||
@Value("${media.mp4-port:0}")
|
||||
private Integer mp4Port = 0;
|
||||
|
||||
@Value("${media.ws-flv-port:0}")
|
||||
private Integer wsFlvPort = 0;
|
||||
|
||||
@Value("${media.http-ssl-port:0}")
|
||||
private Integer httpSSlPort = 0;
|
||||
|
||||
@Value("${media.flv-ssl-port:0}")
|
||||
private Integer flvSSlPort = 0;
|
||||
|
||||
@Value("${media.ws-flv-ssl-port:0}")
|
||||
private Integer wsFlvSSlPort = 0;
|
||||
|
||||
@Value("${media.rtmp-port:0}")
|
||||
private Integer rtmpPort = 0;
|
||||
|
||||
@Value("${media.rtmp-ssl-port:0}")
|
||||
private Integer rtmpSSlPort = 0;
|
||||
|
||||
@Value("${media.rtp-proxy-port:0}")
|
||||
private Integer rtpProxyPort = 0;
|
||||
|
||||
@Value("${media.jtt-proxy-port:0}")
|
||||
private Integer jttProxyPort = 0;
|
||||
|
||||
@Value("${media.rtsp-port:0}")
|
||||
private Integer rtspPort = 0;
|
||||
|
||||
@Value("${media.rtsp-ssl-port:0}")
|
||||
private Integer rtspSSLPort = 0;
|
||||
|
||||
@Value("${media.auto-config:true}")
|
||||
private boolean autoConfig = true;
|
||||
|
||||
@Value("${media.secret}")
|
||||
private String secret;
|
||||
|
||||
@Value("${media.rtp.enable}")
|
||||
private boolean rtpEnable;
|
||||
|
||||
@Value("${media.rtp.port-range}")
|
||||
private String rtpPortRange;
|
||||
|
||||
@Value("${media.rtp.send-port-range}")
|
||||
private String rtpSendPortRange;
|
||||
|
||||
@Value("${media.record-assist-port:0}")
|
||||
private Integer recordAssistPort = 0;
|
||||
|
||||
@Value("${media.record-day:7}")
|
||||
private Integer recordDay;
|
||||
|
||||
@Value("${media.record-path:}")
|
||||
private String recordPath;
|
||||
|
||||
@Value("${media.type:zlm}")
|
||||
private String type;
|
||||
|
||||
|
||||
|
||||
public int getRtpProxyPort() {
|
||||
if (rtpProxyPort == null) {
|
||||
return 0;
|
||||
}else {
|
||||
return rtpProxyPort;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Integer getJttProxyPort() {
|
||||
if (jttProxyPort == null) {
|
||||
return 0;
|
||||
}else {
|
||||
return jttProxyPort;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSdpIp() {
|
||||
if (ObjectUtils.isEmpty(sdpIp)){
|
||||
return ip;
|
||||
}else {
|
||||
if (isValidIPAddress(sdpIp)) {
|
||||
return sdpIp;
|
||||
}else {
|
||||
// 按照域名解析
|
||||
String hostAddress = null;
|
||||
try {
|
||||
hostAddress = InetAddress.getByName(sdpIp).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
log.error("[获取SDP IP]: 域名解析失败");
|
||||
}
|
||||
return hostAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getStreamIp() {
|
||||
if (ObjectUtils.isEmpty(streamIp)){
|
||||
return ip;
|
||||
}else {
|
||||
return streamIp;
|
||||
}
|
||||
}
|
||||
|
||||
public MediaServer getMediaSerItem(){
|
||||
MediaServer mediaServer = new MediaServer();
|
||||
mediaServer.setId(id);
|
||||
mediaServer.setIp(ip);
|
||||
mediaServer.setDefaultServer(true);
|
||||
mediaServer.setHookIp(getHookIp());
|
||||
mediaServer.setSdpIp(getSdpIp());
|
||||
mediaServer.setStreamIp(getStreamIp());
|
||||
mediaServer.setHttpPort(httpPort);
|
||||
mediaServer.setFlvPort(flvPort);
|
||||
mediaServer.setMp4Port(mp4Port);
|
||||
mediaServer.setWsFlvPort(wsFlvPort);
|
||||
mediaServer.setFlvSSLPort(flvSSlPort);
|
||||
mediaServer.setWsFlvSSLPort(wsFlvSSlPort);
|
||||
|
||||
mediaServer.setHttpSSlPort(httpSSlPort);
|
||||
mediaServer.setRtmpPort(rtmpPort);
|
||||
mediaServer.setRtmpSSlPort(rtmpSSlPort);
|
||||
mediaServer.setRtpProxyPort(getRtpProxyPort());
|
||||
mediaServer.setJttProxyPort(getJttProxyPort());
|
||||
mediaServer.setRtspPort(rtspPort);
|
||||
mediaServer.setRtspSSLPort(rtspSSLPort);
|
||||
mediaServer.setAutoConfig(autoConfig);
|
||||
mediaServer.setSecret(secret);
|
||||
mediaServer.setRtpEnable(rtpEnable);
|
||||
mediaServer.setRtpPortRange(rtpPortRange);
|
||||
mediaServer.setSendRtpPortRange(rtpSendPortRange);
|
||||
mediaServer.setRecordAssistPort(recordAssistPort);
|
||||
mediaServer.setHookAliveInterval(10f);
|
||||
mediaServer.setRecordDay(recordDay);
|
||||
mediaServer.setStatus(false);
|
||||
mediaServer.setType(type);
|
||||
if (recordPath != null) {
|
||||
mediaServer.setRecordPath(recordPath);
|
||||
}
|
||||
mediaServer.setCreateTime(DateUtil.getNow());
|
||||
mediaServer.setUpdateTime(DateUtil.getNow());
|
||||
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
private boolean isValidIPAddress(String ipAddress) {
|
||||
if ((ipAddress != null) && (!ipAddress.isEmpty())) {
|
||||
return Pattern.matches("^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", ipAddress);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
/**
|
||||
* 定时向zlm同步媒体流状态
|
||||
*/
|
||||
public class MediaStatusTimerTask {
|
||||
|
||||
|
||||
// @Scheduled(fixedRate = 2 * 1000) //每3秒执行一次
|
||||
public void execute(){
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.apache.ibatis.logging.stdout.StdOutImpl;
|
||||
import org.apache.ibatis.mapping.DatabaseIdProvider;
|
||||
import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 配置mybatis
|
||||
*/
|
||||
@Configuration
|
||||
@Order(value=1)
|
||||
public class MybatisConfig {
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Bean
|
||||
public DatabaseIdProvider databaseIdProvider() {
|
||||
VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("Oracle", "oracle");
|
||||
properties.setProperty("MySQL", "mysql");
|
||||
properties.setProperty("DB2", "db2");
|
||||
properties.setProperty("Derby", "derby");
|
||||
properties.setProperty("H2", "h2");
|
||||
properties.setProperty("HSQL", "hsql");
|
||||
properties.setProperty("Informix", "informix");
|
||||
properties.setProperty("MS-SQL", "ms-sql");
|
||||
properties.setProperty("PostgreSQL", "postgresql");
|
||||
properties.setProperty("Sybase", "sybase");
|
||||
properties.setProperty("Hana", "hana");
|
||||
properties.setProperty("DM", "dm");
|
||||
properties.setProperty("KingbaseES", "kingbase");
|
||||
properties.setProperty("KingBase8", "kingbase");
|
||||
databaseIdProvider.setProperties(properties);
|
||||
return databaseIdProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, DatabaseIdProvider databaseIdProvider) throws Exception {
|
||||
final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
|
||||
sqlSessionFactory.setDataSource(dataSource);
|
||||
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
|
||||
if (userSetting.getSqlLog()){
|
||||
config.setLogImpl(StdOutImpl.class);
|
||||
}
|
||||
config.setMapUnderscoreToCamelCase(true);
|
||||
sqlSessionFactory.setConfiguration(config);
|
||||
sqlSessionFactory.setDatabaseIdProvider(databaseIdProvider);
|
||||
return sqlSessionFactory.getObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import static com.genersoft.iot.vmp.conf.ThreadPoolTaskConfig.cpuNum;
|
||||
|
||||
/**
|
||||
* "@Scheduled"是Spring框架提供的一种定时任务执行机制,默认情况下它是单线程的,在同时执行多个定时任务时可能会出现阻塞和性能问题。
|
||||
* 为了解决这种单线程瓶颈问题,可以将定时任务的执行机制改为支持多线程
|
||||
*/
|
||||
@Configuration
|
||||
public class ScheduleConfig implements SchedulingConfigurer {
|
||||
|
||||
/**
|
||||
* 核心线程数(默认线程数)
|
||||
*/
|
||||
private static final int corePoolSize = Math.max(cpuNum, 20);
|
||||
|
||||
/**
|
||||
* 线程池名前缀
|
||||
*/
|
||||
private static final String threadNamePrefix = "schedule";
|
||||
|
||||
@Override
|
||||
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(corePoolSize,
|
||||
new BasicThreadFactory.Builder().namingPattern(threadNamePrefix).daemon(true).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
taskRegistrar.setScheduler(scheduledThreadPoolExecutor);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ServiceInfo implements ApplicationListener<WebServerInitializedEvent> {
|
||||
|
||||
@Getter
|
||||
private static int serverPort;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(WebServerInitializedEvent event) {
|
||||
// 项目启动获取启动的端口号
|
||||
ServiceInfo.serverPort = event.getWebServer().getPort();
|
||||
log.info("项目启动获取启动的端口号: {}", ServiceInfo.serverPort);
|
||||
}
|
||||
|
||||
public void setServerPort(int serverPort) {
|
||||
ServiceInfo.serverPort = serverPort;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
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)
|
||||
@Data
|
||||
public class SipConfig {
|
||||
|
||||
private String ip;
|
||||
|
||||
private String showIp;
|
||||
|
||||
private List<String> monitorIps;
|
||||
|
||||
private Integer port;
|
||||
|
||||
private String domain;
|
||||
|
||||
private String id;
|
||||
|
||||
private String password;
|
||||
|
||||
Integer ptzSpeed = 50;
|
||||
|
||||
Integer registerTimeInterval = 120;
|
||||
|
||||
private boolean alarm = false;
|
||||
|
||||
private long timeout = 1000;
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Configuration
|
||||
@Order(1)
|
||||
@ConditionalOnProperty(value = "user-settings.doc-enable", havingValue = "true", matchIfMissing = true)
|
||||
public class SpringDocConfig {
|
||||
|
||||
@Value("${doc.enabled: true}")
|
||||
private boolean enable;
|
||||
|
||||
@Bean
|
||||
public OpenAPI springShopOpenApi() {
|
||||
Contact contact = new Contact();
|
||||
contact.setName("pan");
|
||||
contact.setEmail("648540858@qq.com");
|
||||
|
||||
return new OpenAPI()
|
||||
.components(new Components()
|
||||
.addSecuritySchemes(JwtUtils.HEADER, new SecurityScheme()
|
||||
.type(SecurityScheme.Type.HTTP)
|
||||
.bearerFormat("JWT")))
|
||||
.info(new Info().title("WVP-PRO 接口文档")
|
||||
.contact(contact)
|
||||
.description("开箱即用的28181协议视频平台。 <br/>" +
|
||||
"1. 打开<a href='/doc.html#/1.%20全部/用户管理/login_1'>登录</a>接口" +
|
||||
" 登录成功后返回AccessToken。 <br/>" +
|
||||
"2. 填写到AccessToken到参数值 <a href='/doc.html#/Authorize/1.%20全部'>Token配置</a> <br/>" +
|
||||
"后续接口就可以直接测试了")
|
||||
.version("v3.1.0")
|
||||
.license(new License().name("Apache 2.0").url("http://springdoc.org")));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分组
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("1. 全部")
|
||||
.packagesToScan("com.genersoft.iot.vmp")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi2() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("2. 国标28181")
|
||||
.packagesToScan("com.genersoft.iot.vmp.gb28181")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi3() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("3. 拉流转发")
|
||||
.packagesToScan("com.genersoft.iot.vmp.streamProxy")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi4() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("4. 推流管理")
|
||||
.packagesToScan("com.genersoft.iot.vmp.streamPush")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi5() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("4. 服务管理")
|
||||
.packagesToScan("com.genersoft.iot.vmp.server")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi6() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("5. 用户管理")
|
||||
.packagesToScan("com.genersoft.iot.vmp.user")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi7() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("6. 部标设备")
|
||||
.packagesToScan("com.genersoft.iot.vmp.jt1078.controller")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi99() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("99. 第三方接口")
|
||||
.packagesToScan("com.genersoft.iot.vmp.web.custom")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.genersoft.iot.vmp.common.StatisticsInfo;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import com.genersoft.iot.vmp.utils.SystemInfoUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.File;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.util.Objects;
|
||||
|
||||
@Component
|
||||
@Order(value=100)
|
||||
@Slf4j
|
||||
public class StatisticsInfoTask implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private GitUtil gitUtil;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
try {
|
||||
StatisticsInfo statisticsInfo = new StatisticsInfo();
|
||||
statisticsInfo.setDeviceId(SystemInfoUtils.getHardwareId());
|
||||
statisticsInfo.setBranch(gitUtil.getBranch());
|
||||
statisticsInfo.setGitCommitId(gitUtil.getGitCommitId());
|
||||
statisticsInfo.setGitUrl(gitUtil.getGitUrl());
|
||||
statisticsInfo.setVersion(gitUtil.getBuildVersion());
|
||||
|
||||
statisticsInfo.setOsName(System.getProperty("os.name"));
|
||||
statisticsInfo.setArch(System.getProperty("os.arch"));
|
||||
statisticsInfo.setJdkVersion(System.getProperty("java.version"));
|
||||
|
||||
statisticsInfo.setDocker(new File("/.dockerenv").exists());
|
||||
try {
|
||||
statisticsInfo.setRedisVersion(getRedisVersion());
|
||||
}catch (Exception ignored) {}
|
||||
try {
|
||||
DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
|
||||
statisticsInfo.setSqlVersion(metaData.getDatabaseProductVersion());
|
||||
statisticsInfo.setSqlType(metaData.getDriverName());
|
||||
}catch (Exception ignored) {}
|
||||
statisticsInfo.setTime(DateUtil.getNow());
|
||||
sendPost(statisticsInfo);
|
||||
|
||||
|
||||
}catch (Exception e) {
|
||||
log.error("[获取信息失败] ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRedisVersion() {
|
||||
if (redisTemplate.getConnectionFactory() == null) {
|
||||
return null;
|
||||
}
|
||||
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
|
||||
if (connection.info() == null) {
|
||||
return null;
|
||||
}
|
||||
return connection.info().getProperty("redis_version");
|
||||
}
|
||||
|
||||
public void sendPost(StatisticsInfo statisticsInfo) {
|
||||
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
|
||||
OkHttpClient client = httpClientBuilder.build();
|
||||
|
||||
RequestBody requestBodyJson = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSON.toJSONString(statisticsInfo));
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.post(requestBodyJson)
|
||||
.url("http://api.wvp-pro.cn:136/api/statistics/ping")
|
||||
// .url("http://127.0.0.1:11236/api/statistics/ping")
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.build();
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
response.close();
|
||||
Objects.requireNonNull(response.body()).close();
|
||||
|
||||
}catch (Exception ignored){}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.SystemInfoUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 获取系统信息写入redis
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SystemInfoTimerTask {
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Scheduled(fixedRate = 2000) //每1秒执行一次
|
||||
public void execute(){
|
||||
try {
|
||||
double cpuInfo = SystemInfoUtils.getCpuInfo();
|
||||
redisCatchStorage.addCpuInfo(cpuInfo);
|
||||
double memInfo = SystemInfoUtils.getMemInfo();
|
||||
redisCatchStorage.addMemInfo(memInfo);
|
||||
Map<String, Double> networkInterfaces = SystemInfoUtils.getNetworkInterfaces();
|
||||
redisCatchStorage.addNetInfo(networkInterfaces);
|
||||
List<Map<String, Object>> diskInfo =SystemInfoUtils.getDiskInfo();
|
||||
redisCatchStorage.addDiskInfo(diskInfo);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("[获取系统信息失败] {}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* ThreadPoolTask 配置类
|
||||
* @author lin
|
||||
*/
|
||||
@Configuration
|
||||
@Order(1)
|
||||
@EnableAsync(proxyTargetClass = true)
|
||||
public class ThreadPoolTaskConfig {
|
||||
|
||||
public static final int cpuNum = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/**
|
||||
* 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
|
||||
* 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
|
||||
* 当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
|
||||
*/
|
||||
|
||||
/**
|
||||
* 核心线程数(默认线程数)
|
||||
*/
|
||||
private static final int corePoolSize = Math.max(cpuNum * 2, 16);
|
||||
/**
|
||||
* 最大线程数
|
||||
*/
|
||||
private static final int maxPoolSize = corePoolSize * 10;
|
||||
/**
|
||||
* 允许线程空闲时间(单位:默认为秒)
|
||||
*/
|
||||
private static final int keepAliveTime = 30;
|
||||
|
||||
/**
|
||||
* 缓冲队列大小
|
||||
*/
|
||||
private static final int queueCapacity = 10000;
|
||||
/**
|
||||
* 线程池名前缀
|
||||
*/
|
||||
private static final String threadNamePrefix = "async-";
|
||||
|
||||
|
||||
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
|
||||
public ThreadPoolTaskExecutor taskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(corePoolSize);
|
||||
executor.setMaxPoolSize(maxPoolSize);
|
||||
executor.setQueueCapacity(queueCapacity);
|
||||
executor.setKeepAliveSeconds(keepAliveTime);
|
||||
executor.setThreadNamePrefix(threadNamePrefix);
|
||||
|
||||
// 线程池对拒绝任务的处理策略
|
||||
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
// 初始化
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 配置文件 user-settings 映射的配置信息
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "user-settings", ignoreInvalidFields = true)
|
||||
@Order(0)
|
||||
@Data
|
||||
public class UserSetting {
|
||||
|
||||
/**
|
||||
* 是否保存位置的历史记录(轨迹)
|
||||
*/
|
||||
private Boolean savePositionHistory = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 是否开始自动点播: 请求流为未拉起的流时,自动开启点播, 需要rtp.enable=true
|
||||
*/
|
||||
private Boolean autoApplyPlay = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* [可选] 部分设备需要扩展SDP,需要打开此设置,一般设备无需打开
|
||||
*/
|
||||
private Boolean seniorSdp = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 点播/录像回放 等待超时时间,单位:毫秒
|
||||
*/
|
||||
private Integer playTimeout = 10000;
|
||||
|
||||
/**
|
||||
* 获取设备录像数据超时时间,单位:毫秒
|
||||
*/
|
||||
private Integer recordInfoTimeout = 15000;
|
||||
|
||||
/**
|
||||
* 上级点播等待超时时间,单位:毫秒
|
||||
*/
|
||||
private int platformPlayTimeout = 20000;
|
||||
|
||||
/**
|
||||
* 是否开启接口鉴权
|
||||
*/
|
||||
private Boolean interfaceAuthentication = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
|
||||
*/
|
||||
private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 推流直播是否录制
|
||||
*/
|
||||
private Boolean recordPushLive = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 国标是否录制
|
||||
*/
|
||||
private Boolean recordSip = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 使用推流状态作为推流通道状态
|
||||
*/
|
||||
private Boolean usePushingAsStatus = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
|
||||
*/
|
||||
private Boolean useSourceIpAsStreamIp = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 是否使用设备来源Ip作为回复IP, 不设置则为 false
|
||||
*/
|
||||
private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
|
||||
*/
|
||||
private Boolean streamOnDemand = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 推流鉴权, 默认开启
|
||||
*/
|
||||
private Boolean pushAuthority = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 设备上线时是否自动同步通道
|
||||
*/
|
||||
private Boolean syncChannelOnDeviceOnline = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 是否开启sip日志
|
||||
*/
|
||||
private Boolean sipLog = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 是否开启mybatis-sql日志
|
||||
*/
|
||||
private Boolean sqlLog = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 消息通道功能-缺少国标ID是否给所有上级发送消息
|
||||
*/
|
||||
private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
|
||||
*/
|
||||
private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* 设备/通道状态变化时发送消息
|
||||
*/
|
||||
private Boolean deviceStatusNotify = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
|
||||
*/
|
||||
private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 开启接口文档页面。 默认开启,生产环境建议关闭,遇到swagger相关的漏洞时也可以关闭
|
||||
*/
|
||||
private Boolean docEnable = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 服务ID,不写则为000000
|
||||
*/
|
||||
private String serverId = "000000";
|
||||
|
||||
|
||||
/**
|
||||
* 国标级联语音喊话发流模式 * UDP:udp传输 TCP-ACTIVE:tcp主动模式 TCP-PASSIVE:tcp被动模式
|
||||
*/
|
||||
private String broadcastForPlatform = "UDP";
|
||||
|
||||
/**
|
||||
* 行政区划信息文件,系统启动时会加载到系统里
|
||||
*/
|
||||
private String civilCodeFile = "classpath:civilCode.csv";
|
||||
|
||||
/**
|
||||
* 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
|
||||
*/
|
||||
private List<String> allowedOrigins = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认100000
|
||||
*/
|
||||
private int maxNotifyCountQueue = 100000;
|
||||
|
||||
/**
|
||||
* 国标级联离线后多久重试一次注册
|
||||
*/
|
||||
private int registerAgainAfterTime = 60;
|
||||
|
||||
/**
|
||||
* 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
|
||||
*/
|
||||
private boolean registerKeepIntDialog = false;
|
||||
|
||||
/**
|
||||
* # 国标设备离线后的上线策略,
|
||||
* # 0: 国标标准实现,设备离线后不回复心跳,直到设备重新注册上线,
|
||||
* # 1(默认): 对于离线设备,收到心跳就把设备设置为上线,并更新注册时间为上次这次心跳的时间。防止过期时间判断异常
|
||||
*/
|
||||
private int gbDeviceOnline = 1;
|
||||
|
||||
/**
|
||||
* 登录超时时间(分钟),
|
||||
*/
|
||||
private long loginTimeout = 60;
|
||||
|
||||
/**
|
||||
* jwk文件路径,若不指定则使用resources目录下的jwk.json
|
||||
*/
|
||||
private String jwkFile = "classpath:jwk.json";
|
||||
|
||||
/**
|
||||
* wvp集群模式下如果注册向上级的wvp奔溃,则自动选择一个其他wvp继续注册到上级
|
||||
*/
|
||||
private boolean autoRegisterPlatform = false;
|
||||
|
||||
/**
|
||||
* 按需发送推流设备位置, 默认发送移动位置订阅时如果位置不变则不发送, 设置为false按照国标间隔持续发送
|
||||
*/
|
||||
private boolean sendPositionOnDemand = true;
|
||||
|
||||
/**
|
||||
* 部分设备会在短时间内发送大量注册, 导致协议栈内存溢出, 开启此项可以防止这部分设备注册, 避免服务崩溃,但是会降低系统性能, 描述如下
|
||||
* 默认值为 true。
|
||||
* 将此设置为 false 会使 Stack 在 Server Transaction 进入 TERMINATED 状态后关闭服务器套接字。
|
||||
* 这允许服务器防止客户端发起的基于 TCP 的拒绝服务攻击(即发起数百个客户端事务)。
|
||||
* 如果为 true(默认作),则堆栈将保持套接字打开,以便以牺牲线程和内存资源为代价来最大化性能 - 使自身容易受到 DOS 攻击。
|
||||
*/
|
||||
private boolean sipCacheServerConnections = true;
|
||||
|
||||
/**
|
||||
* 禁用date头,变相禁用了校时
|
||||
*/
|
||||
private boolean disableDateHeader = false;
|
||||
|
||||
/**
|
||||
* 同步业务分组时自动生成分组国标编号的模板,不配置则默认参考当前的sip域信息生成
|
||||
*/
|
||||
private String groupSyncDeviceTemplate;
|
||||
|
||||
/**
|
||||
* 与第三方进行分组同步时使用别名而不是分组ID, 如果没有设置此项为true,那么分组编号就是必须传递的。如果是设置为true则,自动为别名的分组生成新的编号
|
||||
*/
|
||||
private boolean useAliasForGroupSync = false;
|
||||
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "version")
|
||||
@Order(0)
|
||||
public class VersionConfig {
|
||||
|
||||
private String version;
|
||||
private String artifactId;
|
||||
private String description;
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setArtifactId(String artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getArtifactId() {
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.common.VersionPo;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class VersionInfo {
|
||||
|
||||
@Autowired
|
||||
GitUtil gitUtil;
|
||||
|
||||
public VersionPo getVersion() {
|
||||
VersionPo versionPo = new VersionPo();
|
||||
versionPo.setGIT_Revision(gitUtil.getGitCommitId());
|
||||
versionPo.setGIT_BRANCH(gitUtil.getBranch());
|
||||
versionPo.setGIT_URL(gitUtil.getGitUrl());
|
||||
versionPo.setBUILD_DATE(gitUtil.getBuildDate());
|
||||
versionPo.setGIT_Revision_SHORT(gitUtil.getCommitIdShort());
|
||||
versionPo.setVersion(gitUtil.getBuildVersion());
|
||||
versionPo.setGIT_DATE(gitUtil.getCommitTime());
|
||||
|
||||
return versionPo;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
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 {
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Value("${server.port}")
|
||||
private int serverPort;
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
|
||||
public void execute(){
|
||||
redisCatchStorage.updateWVPInfo(ServerInfo.create(sipConfig.getShowIp(), serverPort), 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.exception;
|
||||
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
|
||||
/**
|
||||
* 自定义异常,controller出现错误时直接抛出异常由全局异常捕获并返回结果
|
||||
*/
|
||||
public class ControllerException extends RuntimeException{
|
||||
|
||||
private int code;
|
||||
private String msg;
|
||||
|
||||
public ControllerException(int code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
public ControllerException(ErrorCode errorCode) {
|
||||
this.code = errorCode.getCode();
|
||||
this.msg = errorCode.getMsg();
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.exception;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
public class ServiceException extends Exception{
|
||||
private String msg;
|
||||
|
||||
|
||||
|
||||
public ServiceException(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.exception;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
public class SsrcTransactionNotFoundException extends Exception{
|
||||
private String deviceId;
|
||||
private String channelId;
|
||||
private String callId;
|
||||
private String stream;
|
||||
|
||||
|
||||
|
||||
public SsrcTransactionNotFoundException(String deviceId, String channelId, String callId, String stream) {
|
||||
this.deviceId = deviceId;
|
||||
this.channelId = channelId;
|
||||
this.callId = callId;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public String getCallId() {
|
||||
return callId;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
StringBuffer msg = new StringBuffer();
|
||||
msg.append(String.format("缓存事务信息未找到,device:%s channel: %s ", deviceId, channelId));
|
||||
if (callId != null) {
|
||||
msg.append(",callId: " + callId);
|
||||
}
|
||||
if (stream != null) {
|
||||
msg.append(",stream: " + stream);
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface FileCallback {
|
||||
|
||||
OutputStream run(String path);
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.ftpserver.ftplet.Authority;
|
||||
import org.apache.ftpserver.ftplet.AuthorizationRequest;
|
||||
|
||||
public class FtpAuthority implements Authority {
|
||||
|
||||
@Override
|
||||
public boolean canAuthorize(AuthorizationRequest authorizationRequest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationRequest authorize(AuthorizationRequest authorizationRequest) {
|
||||
return authorizationRequest;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.ftpserver.ftplet.FileSystemFactory;
|
||||
import org.apache.ftpserver.ftplet.FileSystemView;
|
||||
import org.apache.ftpserver.ftplet.FtpException;
|
||||
import org.apache.ftpserver.ftplet.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
public class FtpFileSystemFactory implements FileSystemFactory {
|
||||
|
||||
private final Map<String, OutputStream> outputStreamMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public FileSystemView createFileSystemView(User user) throws FtpException {
|
||||
return new FtpFileSystemView(user, path -> {
|
||||
return outputStreamMap.get(path);
|
||||
});
|
||||
}
|
||||
|
||||
public void addOutputStream(String filePath, OutputStream outputStream) {
|
||||
outputStreamMap.put(filePath, outputStream);
|
||||
}
|
||||
|
||||
public void removeOutputStream(String filePath) {
|
||||
outputStreamMap.remove(filePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.ftpserver.ftplet.FileSystemView;
|
||||
import org.apache.ftpserver.ftplet.FtpException;
|
||||
import org.apache.ftpserver.ftplet.FtpFile;
|
||||
import org.apache.ftpserver.ftplet.User;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class FtpFileSystemView implements FileSystemView {
|
||||
|
||||
private User user;
|
||||
|
||||
private FileCallback fileCallback;
|
||||
|
||||
public FtpFileSystemView(User user, FileCallback fileCallback) {
|
||||
this.user = user;
|
||||
this.fileCallback = fileCallback;
|
||||
}
|
||||
|
||||
public static String HOME_PATH = "root";
|
||||
|
||||
public FtpFile workDir = VirtualFtpFile.getDir(HOME_PATH);
|
||||
|
||||
@Override
|
||||
public FtpFile getHomeDirectory() throws FtpException {
|
||||
return VirtualFtpFile.getDir(HOME_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpFile getWorkingDirectory() throws FtpException {
|
||||
return workDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeWorkingDirectory(String dir) throws FtpException {
|
||||
workDir = VirtualFtpFile.getDir(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpFile getFile(String file) throws FtpException {
|
||||
VirtualFtpFile ftpFile = VirtualFtpFile.getFile(file);
|
||||
if (fileCallback != null) {
|
||||
OutputStream outputStream = fileCallback.run(workDir.getName());
|
||||
if (outputStream != null) {
|
||||
ftpFile.setOutputStream(outputStream);
|
||||
}
|
||||
}
|
||||
return ftpFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRandomAccessible() throws FtpException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ftpserver.*;
|
||||
import org.apache.ftpserver.ftplet.FtpException;
|
||||
import org.apache.ftpserver.listener.Listener;
|
||||
import org.apache.ftpserver.listener.ListenerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "ftp.enable", havingValue = "true")
|
||||
@Slf4j
|
||||
public class FtpServerConfig {
|
||||
|
||||
@Autowired
|
||||
private UserManager userManager;
|
||||
|
||||
@Autowired
|
||||
private FtpFileSystemFactory fileSystemFactory;
|
||||
|
||||
@Autowired
|
||||
private Ftplet ftplet;
|
||||
|
||||
@Autowired
|
||||
private FtpSetting ftpSetting;
|
||||
|
||||
/**
|
||||
* ftp server init
|
||||
*/
|
||||
@Bean
|
||||
public FtpServer ftpServer() {
|
||||
FtpServerFactory serverFactory = new FtpServerFactory();
|
||||
ListenerFactory listenerFactory = new ListenerFactory();
|
||||
// 1、设置服务端口
|
||||
listenerFactory.setPort(ftpSetting.getPort());
|
||||
// 2、设置被动模式数据上传的接口范围,云服务器需要开放对应区间的端口给客户端
|
||||
DataConnectionConfigurationFactory dataConnectionConfFactory = new DataConnectionConfigurationFactory();
|
||||
dataConnectionConfFactory.setPassivePorts(ftpSetting.getPassivePorts());
|
||||
listenerFactory.setDataConnectionConfiguration(dataConnectionConfFactory.createDataConnectionConfiguration());
|
||||
// 4、替换默认的监听器
|
||||
Listener listener = listenerFactory.createListener();
|
||||
serverFactory.addListener("default", listener);
|
||||
// 5、配置自定义用户事件
|
||||
Map<String, org.apache.ftpserver.ftplet.Ftplet> ftpLets = new HashMap<>();
|
||||
ftpLets.put("ftpService", ftplet);
|
||||
serverFactory.setFtplets(ftpLets);
|
||||
// 6、读取用户的配置信息
|
||||
// 6.2、设置用信息
|
||||
serverFactory.setUserManager(userManager);
|
||||
serverFactory.setFileSystem(fileSystemFactory);
|
||||
// 7、实例化FTP Server
|
||||
FtpServer server = serverFactory.createServer();
|
||||
try {
|
||||
server.start();
|
||||
if (!server.isStopped()) {
|
||||
log.info("[FTP服务] 已启动, 端口: {}", ftpSetting.getPort());
|
||||
}
|
||||
} catch (FtpException e) {
|
||||
log.info("[FTP服务] 启动失败 ", e);
|
||||
}
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 配置文件 user-settings 映射的配置信息
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "ftp", ignoreInvalidFields = true)
|
||||
@Order(0)
|
||||
@Data
|
||||
public class FtpSetting {
|
||||
|
||||
private Boolean enable = Boolean.FALSE;
|
||||
|
||||
private int port = 21;
|
||||
private String passivePorts = "10000-10500";
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.event.FtpUploadEvent;
|
||||
import org.apache.ftpserver.ftplet.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@Component
|
||||
public class Ftplet extends DefaultFtplet {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(Ftplet.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@Override
|
||||
public FtpletResult onUploadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
|
||||
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
|
||||
if (file == null) {
|
||||
return super.onUploadEnd(session, request);
|
||||
}
|
||||
sendEvent(file.getAbsolutePath());
|
||||
return super.onUploadUniqueEnd(session, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpletResult onAppendEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
|
||||
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
|
||||
if (file == null) {
|
||||
return super.onUploadEnd(session, request);
|
||||
}
|
||||
sendEvent(file.getAbsolutePath());
|
||||
return super.onUploadUniqueEnd(session, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpletResult onUploadUniqueEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
|
||||
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
|
||||
if (file == null) {
|
||||
return super.onUploadEnd(session, request);
|
||||
}
|
||||
sendEvent(file.getAbsolutePath());
|
||||
return super.onUploadUniqueEnd(session, request);
|
||||
}
|
||||
|
||||
private void sendEvent(String filePath){
|
||||
FtpUploadEvent event = new FtpUploadEvent(this);
|
||||
logger.info("[文件已上传]: {}", filePath);
|
||||
event.setFileName(filePath);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.ftpserver.ftplet.*;
|
||||
import org.apache.ftpserver.usermanager.UsernamePasswordAuthentication;
|
||||
import org.apache.ftpserver.usermanager.impl.BaseUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class UserManager implements org.apache.ftpserver.ftplet.UserManager {
|
||||
|
||||
private static final String PREFIX = "VMP_FTP_USER_";
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
|
||||
@Override
|
||||
public User getUserByName(String username) throws FtpException {
|
||||
return (BaseUser)redisTemplate.opsForValue().get(PREFIX + username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAllUserNames() throws FtpException {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String username) throws FtpException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(User user) throws FtpException {}
|
||||
|
||||
@Override
|
||||
public boolean doesExist(String username) throws FtpException {
|
||||
return redisTemplate.opsForValue().get(PREFIX + username) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(Authentication authentication) throws AuthenticationFailedException {
|
||||
UsernamePasswordAuthentication usernamePasswordAuthentication = (UsernamePasswordAuthentication) authentication;
|
||||
BaseUser user = (BaseUser)redisTemplate.opsForValue().get(PREFIX + usernamePasswordAuthentication.getUsername());
|
||||
if (user != null && usernamePasswordAuthentication.getPassword().equals(user.getPassword())) {
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAdminName() throws FtpException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdmin(String username) throws FtpException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BaseUser getRandomUser(){
|
||||
BaseUser use = new BaseUser();
|
||||
use.setName(RandomStringUtils.randomAlphabetic(6).toLowerCase());
|
||||
use.setPassword(RandomStringUtils.randomAlphabetic(6).toLowerCase());
|
||||
use.setEnabled(true);
|
||||
use.setHomeDirectory("/");
|
||||
List<Authority> authorities = new ArrayList<>();
|
||||
authorities.add(new FtpAuthority());
|
||||
use.setAuthorities(authorities);
|
||||
String key = PREFIX + use.getName();
|
||||
|
||||
// 随机用户信息十分钟自动失效
|
||||
Duration duration = Duration.ofMinutes(10);
|
||||
redisTemplate.opsForValue().set(key, use, duration);
|
||||
return use;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import lombok.Setter;
|
||||
import org.apache.ftpserver.ftplet.FtpFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class VirtualFtpFile implements FtpFile {
|
||||
|
||||
@Setter
|
||||
private String name;
|
||||
|
||||
@Setter
|
||||
private boolean hidden = false;
|
||||
|
||||
@Setter
|
||||
private boolean directory = false;
|
||||
|
||||
@Setter
|
||||
private String ownerName;
|
||||
|
||||
private Long lastModified = null;
|
||||
|
||||
@Setter
|
||||
private long size = 0;
|
||||
|
||||
@Setter
|
||||
private OutputStream outputStream;
|
||||
|
||||
public static VirtualFtpFile getFile(String name) {
|
||||
VirtualFtpFile virtualFtpFile = new VirtualFtpFile();
|
||||
virtualFtpFile.setName(name);
|
||||
return virtualFtpFile;
|
||||
}
|
||||
|
||||
public static VirtualFtpFile getDir(String name) {
|
||||
if (name.endsWith("/")) {
|
||||
name = name.replaceAll("/", "");
|
||||
}
|
||||
VirtualFtpFile virtualFtpFile = new VirtualFtpFile();
|
||||
virtualFtpFile.setName(name);
|
||||
virtualFtpFile.setDirectory(true);
|
||||
return virtualFtpFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAbsolutePath() {
|
||||
return FtpFileSystemView.HOME_PATH + "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile() {
|
||||
return !directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesExist() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemovable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOwnerName() {
|
||||
return ownerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupName() {
|
||||
return "root";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLinkCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified() {
|
||||
if (lastModified == null) {
|
||||
lastModified = System.currentTimeMillis();
|
||||
}
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLastModified(long time) {
|
||||
lastModified = time;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPhysicalFile() {
|
||||
System.err.println("getPhysicalFile");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdir() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean move(FtpFile destination) {
|
||||
this.name = destination.getName();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends FtpFile> listFiles() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream createOutputStream(long offset) throws IOException {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream createInputStream(long offset) throws IOException {
|
||||
System.out.println("createInputStream----");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.redis;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.service.redisMsg.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.listener.PatternTopic;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
|
||||
|
||||
/**
|
||||
* @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
||||
* @author: swwheihei
|
||||
* @date: 2019年5月30日 上午10:58:25
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(value=1)
|
||||
public class RedisMsgListenConfig {
|
||||
|
||||
@Autowired
|
||||
private RedisGpsMsgListener redisGPSMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisAlarmMsgListener redisAlarmMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisPushStreamListMsgListener pushStreamListMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisGroupMsgListener groupMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisGroupChangeListener groupChangeListener;
|
||||
|
||||
@Autowired
|
||||
private RedisCloseStreamMsgListener redisCloseStreamMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisRpcConfig redisRpcConfig;
|
||||
|
||||
@Autowired
|
||||
private RedisPushStreamResponseListener redisPushStreamCloseResponseListener;
|
||||
|
||||
|
||||
/**
|
||||
* redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
|
||||
* 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
|
||||
*
|
||||
* @param connectionFactory
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
|
||||
|
||||
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
container.setConnectionFactory(connectionFactory);
|
||||
container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS));
|
||||
container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
|
||||
container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
|
||||
container.addMessageListener(pushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE));
|
||||
container.addMessageListener(redisCloseStreamMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE));
|
||||
container.addMessageListener(redisRpcConfig, new PatternTopic(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY));
|
||||
container.addMessageListener(redisPushStreamCloseResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE));
|
||||
container.addMessageListener(groupMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GROUP_LIST_RESPONSE));
|
||||
container.addMessageListener(groupChangeListener, new PatternTopic(VideoManagerConstants.VM_MSG_GROUP_LIST_CHANGE));
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
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.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;
|
||||
import org.springframework.data.redis.connection.Message;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RedisRpcConfig implements MessageListener {
|
||||
|
||||
public final static String REDIS_REQUEST_CHANNEL_KEY = "WVP_REDIS_REQUEST_CHANNEL_KEY";
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Qualifier("taskExecutor")
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
|
||||
private final static Map<String, RedisRpcClassHandler> protocolHash = new HashMap<>();
|
||||
|
||||
public void addHandler(String path, RedisRpcClassHandler handler) {
|
||||
protocolHash.put(path, handler);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void run(String... args) throws Exception {
|
||||
// List<Class<?>> classList = ClassUtil.getClassList("com.genersoft.iot.vmp.service.redisMsg.control", RedisRpcController.class);
|
||||
// for (Class<?> handlerClass : classList) {
|
||||
// String controllerPath = handlerClass.getAnnotation(RedisRpcController.class).value();
|
||||
// Object bean = ClassUtil.getBean(controllerPath, handlerClass);
|
||||
// // 扫描其下的方法
|
||||
// Method[] methods = handlerClass.getDeclaredMethods();
|
||||
// for (Method method : methods) {
|
||||
// RedisRpcMapping annotation = method.getAnnotation(RedisRpcMapping.class);
|
||||
// if (annotation != null) {
|
||||
// String methodPath = annotation.value();
|
||||
// if (methodPath != null) {
|
||||
// protocolHash.put(controllerPath + "/" + methodPath, new RedisRpcClassHandler(bean, method));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// for (String s : protocolHash.keySet()) {
|
||||
// System.out.println(s);
|
||||
// }
|
||||
// if (log.isDebugEnabled()) {
|
||||
// log.debug("消息ID缓存表 protocolHash:{}", protocolHash);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message, byte[] pattern) {
|
||||
boolean isEmpty = taskQueue.isEmpty();
|
||||
taskQueue.offer(message);
|
||||
if (isEmpty) {
|
||||
taskExecutor.execute(() -> {
|
||||
while (!taskQueue.isEmpty()) {
|
||||
Message msg = taskQueue.poll();
|
||||
try {
|
||||
RedisRpcMessage redisRpcMessage = JSON.parseObject(new String(msg.getBody()), RedisRpcMessage.class);
|
||||
if (redisRpcMessage.getRequest() != null) {
|
||||
handlerRequest(redisRpcMessage.getRequest());
|
||||
} else if (redisRpcMessage.getResponse() != null){
|
||||
handlerResponse(redisRpcMessage.getResponse());
|
||||
} else {
|
||||
log.error("[redis-rpc]解析失败 {}", JSON.toJSONString(redisRpcMessage));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[redis-rpc]解析异常 {}",new String(msg.getBody()), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void handlerResponse(RedisRpcResponse response) {
|
||||
if (userSetting.getServerId().equals(response.getToId())) {
|
||||
return;
|
||||
}
|
||||
log.info("[redis-rpc] << {}", response);
|
||||
response(response);
|
||||
}
|
||||
|
||||
private void handlerRequest(RedisRpcRequest request) {
|
||||
try {
|
||||
if (userSetting.getServerId().equals(request.getFromId())) {
|
||||
return;
|
||||
}
|
||||
log.info("[redis-rpc] << {}", request);
|
||||
RedisRpcClassHandler redisRpcClassHandler = protocolHash.get(request.getUri());
|
||||
if (redisRpcClassHandler == null) {
|
||||
log.error("[redis-rpc] 路径: {}不存在", request.getUri());
|
||||
return;
|
||||
}
|
||||
RpcController controller = redisRpcClassHandler.getController();
|
||||
Method method = redisRpcClassHandler.getMethod();
|
||||
// 没有携带目标ID的可以理解为哪个wvp有结果就哪个回复,携带目标ID,但是如果是不存在的uri则直接回复404
|
||||
if (userSetting.getServerId().equals(request.getToId())) {
|
||||
if (method == null) {
|
||||
// 回复404结果
|
||||
RedisRpcResponse response = request.getResponse();
|
||||
response.setStatusCode(ErrorCode.ERROR404.getCode());
|
||||
sendResponse(response);
|
||||
return;
|
||||
}
|
||||
RedisRpcResponse response = (RedisRpcResponse)method.invoke(controller, request);
|
||||
if(response != null) {
|
||||
sendResponse(response);
|
||||
}
|
||||
}else {
|
||||
if (method == null) {
|
||||
// 回复404结果
|
||||
RedisRpcResponse response = request.getResponse();
|
||||
response.setStatusCode(ErrorCode.ERROR404.getCode());
|
||||
sendResponse(response);
|
||||
return;
|
||||
}
|
||||
RedisRpcResponse response = (RedisRpcResponse)method.invoke(controller, request);
|
||||
if (response != null) {
|
||||
sendResponse(response);
|
||||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error("[redis-rpc ] 处理请求失败 ", e);
|
||||
RedisRpcResponse response = request.getResponse();
|
||||
response.setStatusCode(ErrorCode.ERROR100.getCode());
|
||||
sendResponse(response);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendResponse(RedisRpcResponse response){
|
||||
log.info("[redis-rpc] >> {}", response);
|
||||
response.setToId(userSetting.getServerId());
|
||||
RedisRpcMessage message = new RedisRpcMessage();
|
||||
message.setResponse(response);
|
||||
redisTemplate.convertAndSend(REDIS_REQUEST_CHANNEL_KEY, message);
|
||||
}
|
||||
|
||||
private void sendRequest(RedisRpcRequest request){
|
||||
log.info("[redis-rpc] >> {}", request);
|
||||
RedisRpcMessage message = new RedisRpcMessage();
|
||||
message.setRequest(request);
|
||||
redisTemplate.convertAndSend(REDIS_REQUEST_CHANNEL_KEY, message);
|
||||
}
|
||||
|
||||
private final Map<Long, SynchronousQueue<RedisRpcResponse>> topicSubscribers = new ConcurrentHashMap<>();
|
||||
private final Map<Long, CommonCallback<RedisRpcResponse>> callbacks = new ConcurrentHashMap<>();
|
||||
|
||||
public RedisRpcResponse request(RedisRpcRequest request, long timeOut) {
|
||||
return request(request, timeOut, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public RedisRpcResponse request(RedisRpcRequest request, long timeOut, TimeUnit timeUnit) {
|
||||
request.setSn((long) random.nextInt(1000) + 1);
|
||||
SynchronousQueue<RedisRpcResponse> subscribe = subscribe(request.getSn());
|
||||
|
||||
try {
|
||||
sendRequest(request);
|
||||
return subscribe.poll(timeOut, timeUnit);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("[redis rpc timeout] uri: {}, sn: {}", request.getUri(), request.getSn(), e);
|
||||
RedisRpcResponse redisRpcResponse = new RedisRpcResponse();
|
||||
redisRpcResponse.setStatusCode(ErrorCode.ERROR486.getCode());
|
||||
return redisRpcResponse;
|
||||
} finally {
|
||||
this.unsubscribe(request.getSn());
|
||||
}
|
||||
}
|
||||
|
||||
public void request(RedisRpcRequest request, CommonCallback<RedisRpcResponse> callback) {
|
||||
request.setSn((long) random.nextInt(1000) + 1);
|
||||
setCallback(request.getSn(), callback);
|
||||
sendRequest(request);
|
||||
}
|
||||
|
||||
public Boolean response(RedisRpcResponse response) {
|
||||
SynchronousQueue<RedisRpcResponse> queue = topicSubscribers.get(response.getSn());
|
||||
CommonCallback<RedisRpcResponse> callback = callbacks.get(response.getSn());
|
||||
if (queue != null) {
|
||||
try {
|
||||
return queue.offer(response, 2, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("{}", e.getMessage(), e);
|
||||
}
|
||||
}else if (callback != null) {
|
||||
callback.run(response);
|
||||
callbacks.remove(response.getSn());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void unsubscribe(long key) {
|
||||
topicSubscribers.remove(key);
|
||||
}
|
||||
|
||||
|
||||
private SynchronousQueue<RedisRpcResponse> subscribe(long key) {
|
||||
SynchronousQueue<RedisRpcResponse> queue = null;
|
||||
if (!topicSubscribers.containsKey(key))
|
||||
topicSubscribers.put(key, queue = new SynchronousQueue<>());
|
||||
return queue;
|
||||
}
|
||||
|
||||
private void setCallback(long key, CommonCallback<RedisRpcResponse> callback) {
|
||||
// TODO 如果多个上级点播同一个通道会有问题
|
||||
callbacks.put(key, callback);
|
||||
}
|
||||
|
||||
public void removeCallback(long key) {
|
||||
callbacks.remove(key);
|
||||
}
|
||||
|
||||
|
||||
public int getCallbackCount(){
|
||||
return callbacks.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// @Scheduled(fixedRate = 1000) //每1秒执行一次
|
||||
// public void execute(){
|
||||
// logger.info("callbacks的长度: " + callbacks.size());
|
||||
// logger.info("队列的长度: " + topicSubscribers.size());
|
||||
// logger.info("HOOK监听的长度: " + hookSubscribe.size());
|
||||
// logger.info("");
|
||||
// }
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.redis;
|
||||
|
||||
import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
|
||||
// 使用fastJson序列化
|
||||
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
|
||||
// value值的序列化采用fastJsonRedisSerializer
|
||||
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
|
||||
|
||||
// key的序列化采用StringRedisSerializer
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, MobilePosition> getRedisTemplateForMobilePosition(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<String, MobilePosition> redisTemplate = new RedisTemplate<>();
|
||||
// 使用fastJson序列化
|
||||
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
|
||||
// value值的序列化采用fastJsonRedisSerializer
|
||||
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
|
||||
|
||||
// key的序列化采用StringRedisSerializer
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.redis.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.service.redisMsg.dto.RpcController;
|
||||
import lombok.Data;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@Data
|
||||
public class RedisRpcClassHandler {
|
||||
|
||||
private RpcController controller;
|
||||
private Method method;
|
||||
|
||||
public RedisRpcClassHandler(RpcController controller, Method method) {
|
||||
this.controller = controller;
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.redis.bean;
|
||||
|
||||
public class RedisRpcMessage {
|
||||
|
||||
private RedisRpcRequest request;
|
||||
|
||||
private RedisRpcResponse response;
|
||||
|
||||
public RedisRpcRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public void setRequest(RedisRpcRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public RedisRpcResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(RedisRpcResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.redis.bean;
|
||||
|
||||
/**
|
||||
* 通过redis发送请求
|
||||
*/
|
||||
public class RedisRpcRequest {
|
||||
|
||||
/**
|
||||
* 来自的WVP ID
|
||||
*/
|
||||
private String fromId;
|
||||
|
||||
|
||||
/**
|
||||
* 目标的WVP ID
|
||||
*/
|
||||
private String toId;
|
||||
|
||||
/**
|
||||
* 序列号
|
||||
*/
|
||||
private long sn;
|
||||
|
||||
/**
|
||||
* 访问的路径
|
||||
*/
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
private Object param;
|
||||
|
||||
public String getFromId() {
|
||||
return fromId;
|
||||
}
|
||||
|
||||
public void setFromId(String fromId) {
|
||||
this.fromId = fromId;
|
||||
}
|
||||
|
||||
public String getToId() {
|
||||
return toId;
|
||||
}
|
||||
|
||||
public void setToId(String toId) {
|
||||
this.toId = toId;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public Object getParam() {
|
||||
return param;
|
||||
}
|
||||
|
||||
public void setParam(Object param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public long getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public void setSn(long sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RedisRpcRequest{" +
|
||||
"uri='" + uri + '\'' +
|
||||
", fromId='" + fromId + '\'' +
|
||||
", toId='" + toId + '\'' +
|
||||
", sn=" + sn +
|
||||
", param=" + param +
|
||||
'}';
|
||||
}
|
||||
|
||||
public RedisRpcResponse getResponse() {
|
||||
RedisRpcResponse response = new RedisRpcResponse();
|
||||
response.setFromId(fromId);
|
||||
response.setToId(toId);
|
||||
response.setSn(sn);
|
||||
response.setUri(uri);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.redis.bean;
|
||||
|
||||
/**
|
||||
* 通过redis发送回复
|
||||
*/
|
||||
public class RedisRpcResponse {
|
||||
|
||||
/**
|
||||
* 来自的WVP ID
|
||||
*/
|
||||
private String fromId;
|
||||
|
||||
|
||||
/**
|
||||
* 目标的WVP ID
|
||||
*/
|
||||
private String toId;
|
||||
|
||||
|
||||
/**
|
||||
* 序列号
|
||||
*/
|
||||
private long sn;
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private int statusCode;
|
||||
|
||||
/**
|
||||
* 访问的路径
|
||||
*/
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
private Object body;
|
||||
|
||||
public String getFromId() {
|
||||
return fromId;
|
||||
}
|
||||
|
||||
public void setFromId(String fromId) {
|
||||
this.fromId = fromId;
|
||||
}
|
||||
|
||||
public String getToId() {
|
||||
return toId;
|
||||
}
|
||||
|
||||
public void setToId(String toId) {
|
||||
this.toId = toId;
|
||||
}
|
||||
|
||||
public long getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public void setSn(long sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public void setStatusCode(int statusCode) {
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public Object getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(Object body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RedisRpcResponse{" +
|
||||
"uri='" + uri + '\'' +
|
||||
", fromId='" + fromId + '\'' +
|
||||
", toId='" + toId + '\'' +
|
||||
", sn=" + sn +
|
||||
", statusCode=" + statusCode +
|
||||
", body=" + body +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 处理匿名用户访问逻辑
|
||||
* @author lin
|
||||
*/
|
||||
@Component
|
||||
public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {
|
||||
String jwt = request.getHeader(JwtUtils.getHeader());
|
||||
JwtUser jwtUser = JwtUtils.verifyToken(jwt);
|
||||
String username = jwtUser.getUserName();
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() );
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("code", ErrorCode.ERROR401.getCode());
|
||||
jsonObject.put("msg", ErrorCode.ERROR401.getMsg());
|
||||
String logUri = "api/user/login";
|
||||
if (request.getRequestURI().contains(logUri)){
|
||||
jsonObject.put("msg", e.getMessage());
|
||||
}
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
try {
|
||||
response.getWriter().print(jsonObject.toJSONString());
|
||||
} catch (IOException ioException) {
|
||||
ioException.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户登录认证逻辑
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DefaultUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private IUserService userService;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
if (StringUtils.isBlank(username)) {
|
||||
log.info("登录用户:{} 不存在", username);
|
||||
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
|
||||
}
|
||||
|
||||
// 查出密码
|
||||
User user = userService.getUserByUsername(username);
|
||||
if (user == null) {
|
||||
log.info("登录用户:{} 不存在", username);
|
||||
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
|
||||
}
|
||||
String password = SecurityUtils.encryptPassword(user.getPassword());
|
||||
user.setPassword(password);
|
||||
return new LoginUser(user, LocalDateTime.now());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.Role;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* jwt token 过滤器
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private final static String WSHeader = "sec-websocket-protocol";
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(servletRequest);
|
||||
// 忽略登录请求的token验证
|
||||
String requestURI = request.getRequestURI();
|
||||
if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestURI.equalsIgnoreCase("/api/user/login")) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userSetting.getInterfaceAuthentication()) {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String jwt = request.getHeader(JwtUtils.getHeader());
|
||||
// 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的
|
||||
// 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口
|
||||
|
||||
// websocket 鉴权信息默认存储在这里
|
||||
String secWebsocketProtocolHeader = request.getHeader(WSHeader);
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
|
||||
if (secWebsocketProtocolHeader != null) {
|
||||
jwt = secWebsocketProtocolHeader;
|
||||
response.setHeader(WSHeader, secWebsocketProtocolHeader);
|
||||
}else {
|
||||
jwt = request.getParameter(JwtUtils.getHeader());
|
||||
}
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
jwt = request.getHeader(JwtUtils.getApiKeyHeader());
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JwtUser jwtUser = JwtUtils.verifyToken(jwt);
|
||||
String username = jwtUser.getUserName();
|
||||
// TODO 处理各个状态
|
||||
switch (jwtUser.getStatus()){
|
||||
case EXPIRED:
|
||||
response.setStatus(401);
|
||||
chain.doFilter(request, response);
|
||||
// 异常
|
||||
return;
|
||||
case EXCEPTION:
|
||||
// 过期
|
||||
response.setStatus(400);
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
case EXPIRING_SOON:
|
||||
// 即将过期
|
||||
// return;
|
||||
default:
|
||||
}
|
||||
// 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
|
||||
User user = new User();
|
||||
user.setId(jwtUser.getUserId());
|
||||
user.setUsername(jwtUser.getUserName());
|
||||
user.setPassword(jwtUser.getPassword());
|
||||
Role role = new Role();
|
||||
role.setId(jwtUser.getRoleId());
|
||||
user.setRole(role);
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, jwtUser.getPassword(), new ArrayList<>() );
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,274 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import com.genersoft.iot.vmp.service.IUserApiKeyService;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jose4j.jwk.JsonWebKey;
|
||||
import org.jose4j.jwk.JsonWebKeySet;
|
||||
import org.jose4j.jwk.RsaJsonWebKey;
|
||||
import org.jose4j.jwk.RsaJwkGenerator;
|
||||
import org.jose4j.jws.AlgorithmIdentifiers;
|
||||
import org.jose4j.jws.JsonWebSignature;
|
||||
import org.jose4j.jwt.JwtClaims;
|
||||
import org.jose4j.jwt.NumericDate;
|
||||
import org.jose4j.jwt.consumer.ErrorCodes;
|
||||
import org.jose4j.jwt.consumer.InvalidJwtException;
|
||||
import org.jose4j.jwt.consumer.JwtConsumer;
|
||||
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class JwtUtils implements InitializingBean {
|
||||
|
||||
public static final String HEADER = "access-token";
|
||||
|
||||
public static final String API_KEY_HEADER = "api-key";
|
||||
|
||||
private static final String AUDIENCE = "Audience";
|
||||
|
||||
private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
|
||||
|
||||
/**
|
||||
* token过期时间(分钟)
|
||||
*/
|
||||
public static final long EXPIRATION_TIME = 30;
|
||||
|
||||
private static RsaJsonWebKey rsaJsonWebKey;
|
||||
|
||||
private static IUserService userService;
|
||||
|
||||
private static IUserApiKeyService userApiKeyService;
|
||||
|
||||
private static UserSetting userSetting;
|
||||
|
||||
public static String getApiKeyHeader() {
|
||||
return API_KEY_HEADER;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserService(IUserService userService) {
|
||||
JwtUtils.userService = userService;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserApiKeyService(IUserApiKeyService userApiKeyService) {
|
||||
JwtUtils.userApiKeyService = userApiKeyService;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserSetting(UserSetting userSetting) {
|
||||
JwtUtils.userSetting = userSetting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
try {
|
||||
rsaJsonWebKey = generateRsaJsonWebKey();
|
||||
} catch (JoseException e) {
|
||||
log.error("生成RsaJsonWebKey报错。", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建密钥对
|
||||
*
|
||||
* @throws JoseException JoseException
|
||||
*/
|
||||
private RsaJsonWebKey generateRsaJsonWebKey() throws JoseException {
|
||||
RsaJsonWebKey rsaJsonWebKey = null;
|
||||
try {
|
||||
String jwkFile = userSetting.getJwkFile();
|
||||
InputStream inputStream = null;
|
||||
if (jwkFile.startsWith("classpath:")){
|
||||
String filePath = jwkFile.substring("classpath:".length());
|
||||
ClassPathResource civilCodeFile = new ClassPathResource(filePath);
|
||||
if (civilCodeFile.exists()) {
|
||||
inputStream = civilCodeFile.getInputStream();
|
||||
}
|
||||
}else {
|
||||
File civilCodeFile = new File(userSetting.getCivilCodeFile());
|
||||
if (civilCodeFile.exists()) {
|
||||
inputStream = Files.newInputStream(civilCodeFile.toPath());
|
||||
}
|
||||
|
||||
}
|
||||
if (inputStream == null ) {
|
||||
log.warn("[API AUTH] 读取jwk.json失败,文件不存在,将使用新生成的随机RSA密钥对");
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
return rsaJsonWebKey;
|
||||
}
|
||||
BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
int index = -1;
|
||||
String line;
|
||||
StringBuilder content = new StringBuilder();
|
||||
while ((line = inputStreamReader.readLine()) != null) {
|
||||
content.append(line);
|
||||
index ++;
|
||||
if (index == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
inputStreamReader.close();
|
||||
inputStream.close();
|
||||
|
||||
|
||||
String jwkJson = content.toString();
|
||||
JsonWebKeySet jsonWebKeySet = new JsonWebKeySet(jwkJson);
|
||||
List<JsonWebKey> jsonWebKeys = jsonWebKeySet.getJsonWebKeys();
|
||||
if (!jsonWebKeys.isEmpty()) {
|
||||
JsonWebKey jsonWebKey = jsonWebKeys.get(0);
|
||||
if (jsonWebKey instanceof RsaJsonWebKey) {
|
||||
rsaJsonWebKey = (RsaJsonWebKey) jsonWebKey;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
if (rsaJsonWebKey == null) {
|
||||
log.warn("[API AUTH] 读取jwk.json失败,获取内容失败,将使用新生成的随机RSA密钥对");
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
}else {
|
||||
log.info("[API AUTH] 读取jwk.json成功");
|
||||
}
|
||||
return rsaJsonWebKey;
|
||||
}
|
||||
|
||||
public static String createToken(String username, Long expirationTime, Map<String, Object> extra) {
|
||||
try {
|
||||
/*
|
||||
* “iss” (issuer) 发行人
|
||||
* “sub” (subject) 主题
|
||||
* “aud” (audience) 接收方 用户
|
||||
* “exp” (expiration time) 到期时间
|
||||
* “nbf” (not before) 在此之前不可用
|
||||
* “iat” (issued at) jwt的签发时间
|
||||
*/
|
||||
JwtClaims claims = new JwtClaims();
|
||||
claims.setGeneratedJwtId();
|
||||
claims.setIssuedAtToNow();
|
||||
// 令牌将过期的时间 分钟
|
||||
if (expirationTime != null) {
|
||||
claims.setExpirationTimeMinutesInTheFuture(expirationTime);
|
||||
}
|
||||
claims.setNotBeforeMinutesInThePast(0);
|
||||
claims.setSubject("login");
|
||||
claims.setAudience(AUDIENCE);
|
||||
//添加自定义参数,必须是字符串类型
|
||||
claims.setClaim("userName", username);
|
||||
if (extra != null) {
|
||||
extra.forEach(claims::setClaim);
|
||||
}
|
||||
//jws
|
||||
JsonWebSignature jws = new JsonWebSignature();
|
||||
//签名算法RS256
|
||||
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
|
||||
jws.setKeyIdHeaderValue(keyId);
|
||||
jws.setPayload(claims.toJson());
|
||||
|
||||
jws.setKey(rsaJsonWebKey.getPrivateKey());
|
||||
|
||||
//get token
|
||||
return jws.getCompactSerialization();
|
||||
} catch (JoseException e) {
|
||||
log.error("[Token生成失败]: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String createToken(String username, Long expirationTime) {
|
||||
return createToken(username, expirationTime, null);
|
||||
}
|
||||
|
||||
public static String createToken(String username) {
|
||||
return createToken(username, userSetting.getLoginTimeout());
|
||||
}
|
||||
|
||||
public static String getHeader() {
|
||||
return HEADER;
|
||||
}
|
||||
|
||||
public static JwtUser verifyToken(String token) {
|
||||
|
||||
JwtUser jwtUser = new JwtUser();
|
||||
|
||||
try {
|
||||
JwtConsumer consumer = new JwtConsumerBuilder()
|
||||
//.setRequireExpirationTime()
|
||||
//.setMaxFutureValidityInMinutes(5256000)
|
||||
.setAllowedClockSkewInSeconds(30)
|
||||
.setRequireSubject()
|
||||
//.setExpectedIssuer("")
|
||||
.setExpectedAudience(AUDIENCE)
|
||||
.setVerificationKey(rsaJsonWebKey.getPublicKey())
|
||||
.build();
|
||||
|
||||
JwtClaims claims = consumer.processToClaims(token);
|
||||
NumericDate expirationTime = claims.getExpirationTime();
|
||||
if (expirationTime != null) {
|
||||
// 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
|
||||
// 剩余时间 (秒)
|
||||
long timeRemaining = expirationTime.getValue() - LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
|
||||
Long apiKeyId = claims.getClaimValue("apiKeyId", Long.class);
|
||||
if (apiKeyId != null) {
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(apiKeyId.intValue());
|
||||
if (userApiKey == null || !userApiKey.isEnable()) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
}
|
||||
}
|
||||
|
||||
String username = (String) claims.getClaimValue("userName");
|
||||
User user = userService.getUserByUsername(username);
|
||||
|
||||
jwtUser.setUserName(username);
|
||||
jwtUser.setPassword(user.getPassword());
|
||||
jwtUser.setRoleId(user.getRole().getId());
|
||||
jwtUser.setUserId(user.getId());
|
||||
|
||||
return jwtUser;
|
||||
} catch (InvalidJwtException e) {
|
||||
if (e.hasErrorCode(ErrorCodes.EXPIRED)) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION);
|
||||
}
|
||||
return jwtUser;
|
||||
} catch (Exception e) {
|
||||
log.error("[Token解析失败]: {}", e.getMessage());
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
return jwtUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 退出登录成功
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LogoutHandler implements LogoutSuccessHandler {
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
|
||||
String username = request.getParameter("username");
|
||||
log.info("[退出登录成功] - [{}]", username);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
import javax.security.sasl.AuthenticationException;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SecurityUtils {
|
||||
|
||||
/**
|
||||
* 描述根据账号密码进行调用security进行认证授权 主动调
|
||||
* 用AuthenticationManager的authenticate方法实现
|
||||
* 授权成功后将用户信息存入SecurityContext当中
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @param authenticationManager 认证授权管理器,
|
||||
* @see AuthenticationManager
|
||||
* @return UserInfo 用户信息
|
||||
*/
|
||||
public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException {
|
||||
//使用security框架自带的验证token生成器 也可以自定义。
|
||||
UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password);
|
||||
//认证 如果失败,这里会自动异常后返回,所以这里不需要判断返回值是否为空,确定是否登录成功
|
||||
Authentication authenticate = authenticationManager.authenticate(token);
|
||||
LoginUser user = (LoginUser) authenticate.getPrincipal();
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录的所有认证信息
|
||||
* @return
|
||||
*/
|
||||
public static Authentication getAuthentication(){
|
||||
SecurityContext context = SecurityContextHolder.getContext();
|
||||
return context.getAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
* @return
|
||||
*/
|
||||
public static LoginUser getUserInfo(){
|
||||
Authentication authentication = getAuthentication();
|
||||
if(authentication!=null){
|
||||
Object principal = authentication.getPrincipal();
|
||||
if(principal!=null && !"anonymousUser".equals(principal.toString())){
|
||||
|
||||
User user = (User) principal;
|
||||
return new LoginUser(user, LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户ID
|
||||
* @return
|
||||
*/
|
||||
public static int getUserId(){
|
||||
LoginUser user = getUserInfo();
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成BCryptPasswordEncoder密码
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 加密字符串
|
||||
*/
|
||||
public static String encryptPassword(String password) {
|
||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
return passwordEncoder.encode(password);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.CorsUtils;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 配置Spring Security
|
||||
*
|
||||
* @author lin
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Order(1)
|
||||
@Slf4j
|
||||
public class WebSecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private DefaultUserDetailsServiceImpl userDetailsService;
|
||||
/**
|
||||
* 登出成功的处理
|
||||
*/
|
||||
@Autowired
|
||||
private LogoutHandler logoutHandler;
|
||||
/**
|
||||
* 未登录的处理
|
||||
*/
|
||||
@Autowired
|
||||
private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint;
|
||||
@Autowired
|
||||
private JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||
return config.getAuthenticationManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationProvider authProvider() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
// 设置不隐藏 未找到用户异常
|
||||
provider.setHideUserNotFoundExceptions(true);
|
||||
// 用户认证service - 查询数据库的逻辑
|
||||
provider.setUserDetailsService(userDetailsService);
|
||||
// 设置密码加密算法
|
||||
provider.setPasswordEncoder(passwordEncoder());
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
List<String> defaultExcludes = new ArrayList<>();
|
||||
defaultExcludes.add("/");
|
||||
defaultExcludes.add("/#/**");
|
||||
defaultExcludes.add("/static/**");
|
||||
|
||||
defaultExcludes.add("/swagger-ui.html");
|
||||
defaultExcludes.add("/swagger-ui/**");
|
||||
defaultExcludes.add("/swagger-resources/**");
|
||||
defaultExcludes.add("/doc.html");
|
||||
defaultExcludes.add("/doc.html#/**");
|
||||
defaultExcludes.add("/v3/api-docs/**");
|
||||
|
||||
defaultExcludes.add("/index.html");
|
||||
defaultExcludes.add("/webjars/**");
|
||||
|
||||
defaultExcludes.add("/js/**");
|
||||
defaultExcludes.add("/api/device/query/snap/**");
|
||||
defaultExcludes.add("/record_proxy/*/**");
|
||||
defaultExcludes.add("/api/emit");
|
||||
defaultExcludes.add("/favicon.ico");
|
||||
defaultExcludes.add("/api/user/login");
|
||||
defaultExcludes.add("/index/hook/**");
|
||||
defaultExcludes.add("/api/device/query/snap/**");
|
||||
defaultExcludes.add("/index/hook/abl/**");
|
||||
defaultExcludes.add("/api/jt1078/playback/download");
|
||||
defaultExcludes.add("/api/jt1078/snap");
|
||||
|
||||
if (userSetting.getInterfaceAuthentication() && !userSetting.getInterfaceAuthenticationExcludes().isEmpty()) {
|
||||
defaultExcludes.addAll(userSetting.getInterfaceAuthenticationExcludes());
|
||||
}
|
||||
|
||||
http
|
||||
.headers(headers -> headers.contentTypeOptions(contentType -> contentType.disable()))
|
||||
.cors(cors -> cors.configurationSource(configurationSource()))
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// 配置拦截规则
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
|
||||
.requestMatchers(defaultExcludes.toArray(new String[0])).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
// 异常处理器
|
||||
.exceptionHandling(exception -> exception.authenticationEntryPoint(anonymousAuthenticationEntryPoint))
|
||||
.logout(logout -> logout.logoutUrl("/api/user/logout")
|
||||
.permitAll()
|
||||
.logoutSuccessHandler(logoutHandler));
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
CorsConfigurationSource configurationSource() {
|
||||
// 配置跨域
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList("*"));
|
||||
corsConfiguration.setMaxAge(3600L);
|
||||
if (userSetting.getAllowedOrigins() != null && !userSetting.getAllowedOrigins().isEmpty()) {
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
|
||||
} else {
|
||||
// 在SpringBoot 2.4及以上版本处理跨域时,遇到错误提示:当allowCredentials为true时,allowedOrigins不能包含特殊值"*"。
|
||||
// 解决方法是明确指定allowedOrigins或使用allowedOriginPatterns。
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
corsConfiguration.addAllowedOriginPattern(CorsConfiguration.ALL); // 默认全部允许所有跨域
|
||||
}
|
||||
|
||||
corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader()));
|
||||
|
||||
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
|
||||
url.registerCorsConfiguration("/**", corsConfiguration);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述: 密码加密算法 BCrypt 推荐使用
|
||||
**/
|
||||
public BCryptPasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security.dto;
|
||||
|
||||
public class JwtUser {
|
||||
|
||||
public enum TokenStatus{
|
||||
/**
|
||||
* 正常的使用状态
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* 过期而失效
|
||||
*/
|
||||
EXPIRED,
|
||||
/**
|
||||
* 即将过期
|
||||
*/
|
||||
EXPIRING_SOON,
|
||||
/**
|
||||
* 异常
|
||||
*/
|
||||
EXCEPTION
|
||||
}
|
||||
|
||||
private int userId;
|
||||
private String userName;
|
||||
|
||||
private String password;
|
||||
|
||||
private int roleId;
|
||||
|
||||
private TokenStatus status;
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public TokenStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(TokenStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(int roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.security.dto;
|
||||
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.Role;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.security.core.CredentialsContainer;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
|
||||
public class LoginUser implements UserDetails, CredentialsContainer {
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*/
|
||||
private User user;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String accessToken;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private String serverId;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
private LocalDateTime loginTime;
|
||||
|
||||
public LoginUser(User user, LocalDateTime loginTime) {
|
||||
this.user = user;
|
||||
this.loginTime = loginTime;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户是否未过期,过期无法验证
|
||||
*/
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户是否解锁,锁定的用户无法进行身份验证
|
||||
* <p>
|
||||
* 密码锁定
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
|
||||
*/
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否被启用或禁用。禁用的用户无法进行身份验证。
|
||||
*/
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证完成后,擦除密码
|
||||
*/
|
||||
@Override
|
||||
public void eraseCredentials() {
|
||||
user.setPassword(null);
|
||||
}
|
||||
|
||||
|
||||
public int getId() {
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
public Role getRole() {
|
||||
return user.getRole();
|
||||
}
|
||||
|
||||
public String getPushKey() {
|
||||
return user.getPushKey();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.webLog;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@ServerEndpoint(value = "/channel/log")
|
||||
@Slf4j
|
||||
public class LogChannel {
|
||||
|
||||
public static final ConcurrentMap<String, LogChannel> CHANNELS = new ConcurrentHashMap<>();
|
||||
|
||||
private Session session;
|
||||
|
||||
@OnMessage(maxMessageSize = 1) // MaxMessage 1 byte
|
||||
public void onMessage(String message) {
|
||||
|
||||
try {
|
||||
this.session.close(new CloseReason(CloseReason.CloseCodes.TOO_BIG, "此节点不接收任何客户端信息"));
|
||||
} catch (IOException e) {
|
||||
log.error("[Web-Log] 连接关闭失败: id={}, err={}", this.session.getId(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, EndpointConfig endpointConfig) {
|
||||
this.session = session;
|
||||
this.session.setMaxIdleTimeout(0);
|
||||
CHANNELS.put(this.session.getId(), this);
|
||||
|
||||
log.info("[Web-Log] 连接已建立: id={}", this.session.getId());
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(CloseReason closeReason) {
|
||||
|
||||
log.info("[Web-Log] 连接已断开: id={}, err={}", this.session.getId(), closeReason);
|
||||
CHANNELS.remove(this.session.getId());
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Throwable throwable) throws IOException {
|
||||
log.info("[Web-Log] 连接错误: id={}, err= {}", this.session.getId(), throwable.getMessage());
|
||||
if (this.session.isOpen()) {
|
||||
this.session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, throwable.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push messages to all clients
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public static void push(String message) {
|
||||
CHANNELS.values().stream().forEach(endpoint -> {
|
||||
if (endpoint.session.isOpen()) {
|
||||
endpoint.session.getAsyncRemote().sendText(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.webLog;
|
||||
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class WebSocketAppender extends AppenderBase<ILoggingEvent> {
|
||||
|
||||
private PatternLayoutEncoder encoder;
|
||||
|
||||
@Override
|
||||
protected void append(ILoggingEvent loggingEvent) {
|
||||
byte[] data = this.encoder.encode(loggingEvent);
|
||||
// Push to client.
|
||||
// LogChannel.push(DateUtil.timestampMsTo_yyyy_MM_dd_HH_mm_ss(loggingEvent.getTimeStamp()) + " " + loggingEvent.getFormattedMessage());
|
||||
LogChannel.push(new String(data, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package com.genersoft.iot.vmp.conf.websocket;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.webLog.LogChannel;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter(){
|
||||
ServerEndpointExporter endpointExporter = new ServerEndpointExporter();
|
||||
|
||||
endpointExporter.setAnnotatedEndpointClasses(LogChannel.class);
|
||||
|
||||
return endpointExporter;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
import gov.nist.javax.sip.SipStackImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.*;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@Order(value=10)
|
||||
public class SipLayer implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private ISIPProcessorObserver sipProcessorObserver;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
|
||||
private final List<String> monitorIps = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
if (ObjectUtils.isEmpty(sipConfig.getIp())) {
|
||||
try {
|
||||
// 获得本机的所有网络接口
|
||||
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
|
||||
while (nifs.hasMoreElements()) {
|
||||
NetworkInterface nif = nifs.nextElement();
|
||||
// 获得与该网络接口绑定的 IP 地址,一般只有一个
|
||||
Enumeration<InetAddress> addresses = nif.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
InetAddress addr = addresses.nextElement();
|
||||
if (addr instanceof Inet4Address) {
|
||||
if (addr.getHostAddress().equals("127.0.0.1")){
|
||||
continue;
|
||||
}
|
||||
if (nif.getName().startsWith("docker")) {
|
||||
continue;
|
||||
}
|
||||
log.info("[自动配置SIP监听网卡] 网卡接口地址: {}", addr.getHostAddress());// 只关心 IPv4 地址
|
||||
monitorIps.add(addr.getHostAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error("[读取网卡信息失败]", e);
|
||||
}
|
||||
if (monitorIps.isEmpty()) {
|
||||
log.error("[自动配置SIP监听网卡信息失败], 请手动配置SIP.IP后重新启动");
|
||||
System.exit(1);
|
||||
}
|
||||
}else {
|
||||
// 使用逗号分割多个ip
|
||||
String separator = ",";
|
||||
if (sipConfig.getIp().indexOf(separator) > 0) {
|
||||
String[] split = sipConfig.getIp().split(separator);
|
||||
monitorIps.addAll(Arrays.asList(split));
|
||||
}else {
|
||||
monitorIps.add(sipConfig.getIp());
|
||||
}
|
||||
}
|
||||
sipConfig.setMonitorIps(monitorIps);
|
||||
if (ObjectUtils.isEmpty(sipConfig.getShowIp())){
|
||||
sipConfig.setShowIp(String.join(",", monitorIps));
|
||||
}
|
||||
SipFactory.getInstance().setPathName("gov.nist");
|
||||
if (!monitorIps.isEmpty()) {
|
||||
for (String monitorIp : monitorIps) {
|
||||
addListeningPoint(monitorIp, sipConfig.getPort());
|
||||
}
|
||||
if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addListeningPoint(String monitorIp, int port){
|
||||
SipStackImpl sipStack;
|
||||
try {
|
||||
sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog(), userSetting.isSipCacheServerConnections()));
|
||||
sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
|
||||
} catch (PeerUnavailableException e) {
|
||||
log.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP");
|
||||
SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||
|
||||
tcpSipProvider.setDialogErrorsAutomaticallyHandled();
|
||||
tcpSipProvider.addSipListener(sipProcessorObserver);
|
||||
tcpSipProviderMap.put(monitorIp, tcpSipProvider);
|
||||
log.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port);
|
||||
} catch (TransportNotSupportedException
|
||||
| TooManyListenersException
|
||||
| ObjectInUseException
|
||||
| InvalidArgumentException e) {
|
||||
log.error("[SIP SERVER] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
|
||||
, monitorIp, port);
|
||||
}
|
||||
|
||||
try {
|
||||
ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP");
|
||||
|
||||
SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||
udpSipProvider.setDialogErrorsAutomaticallyHandled();
|
||||
udpSipProviderMap.put(monitorIp, udpSipProvider);
|
||||
|
||||
log.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port);
|
||||
} catch (TransportNotSupportedException
|
||||
| TooManyListenersException
|
||||
| ObjectInUseException
|
||||
| InvalidArgumentException e) {
|
||||
log.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
|
||||
, monitorIp, port);
|
||||
}
|
||||
}
|
||||
|
||||
public SipProviderImpl getUdpSipProvider(String ip) {
|
||||
if (udpSipProviderMap.size() == 1) {
|
||||
return udpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
if (ObjectUtils.isEmpty(ip)) {
|
||||
return null;
|
||||
}
|
||||
return udpSipProviderMap.get(ip);
|
||||
}
|
||||
|
||||
public SipProviderImpl getUdpSipProvider() {
|
||||
if (udpSipProviderMap.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return udpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
public SipProviderImpl getTcpSipProvider() {
|
||||
if (tcpSipProviderMap.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return tcpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
public SipProviderImpl getTcpSipProvider(String ip) {
|
||||
if (tcpSipProviderMap.size() == 1) {
|
||||
return tcpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
if (ObjectUtils.isEmpty(ip)) {
|
||||
return null;
|
||||
}
|
||||
return tcpSipProviderMap.get(ip);
|
||||
}
|
||||
|
||||
public String getLocalIp(String deviceLocalIp) {
|
||||
if (monitorIps.size() == 1) {
|
||||
return monitorIps.get(0);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(deviceLocalIp)) {
|
||||
return deviceLocalIp;
|
||||
}
|
||||
return getUdpSipProvider().getListeningPoint().getIPAddress();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* Conditions Of Use
|
||||
*
|
||||
* This software was developed by employees of the National Institute of
|
||||
* Standards and Technology (NIST), an agency of the Federal Government.
|
||||
* Pursuant to title 15 Untied States Code Section 105, works of NIST
|
||||
* employees are not subject to copyright protection in the United States
|
||||
* and are considered to be in the public domain. As a result, a formal
|
||||
* license is not needed to use the software.
|
||||
*
|
||||
* This software is provided by NIST as a service and is expressly
|
||||
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
|
||||
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
|
||||
* AND DATA ACCURACY. NIST does not warrant or make any representations
|
||||
* regarding the use of the software or the results thereof, including but
|
||||
* not limited to the correctness, accuracy, reliability or usefulness of
|
||||
* the software.
|
||||
*
|
||||
* Permission to use this software is contingent upon your acceptance
|
||||
* of the terms of this agreement
|
||||
*
|
||||
* .
|
||||
*
|
||||
*/
|
||||
package com.genersoft.iot.vmp.gb28181.auth;
|
||||
|
||||
import gov.nist.core.InternalErrorHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.sip.address.URI;
|
||||
import javax.sip.header.AuthorizationHeader;
|
||||
import javax.sip.header.HeaderFactory;
|
||||
import javax.sip.header.WWWAuthenticateHeader;
|
||||
import javax.sip.message.Request;
|
||||
import javax.sip.message.Response;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Instant;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Implements the HTTP digest authentication method server side functionality.
|
||||
*
|
||||
* @author M. Ranganathan
|
||||
* @author Marc Bednarek
|
||||
*/
|
||||
@Slf4j
|
||||
public class DigestServerAuthenticationHelper {
|
||||
|
||||
private final MessageDigest messageDigest;
|
||||
|
||||
public static final String DEFAULT_ALGORITHM = "MD5";
|
||||
public static final String DEFAULT_SCHEME = "Digest";
|
||||
|
||||
/** to hex converter */
|
||||
private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public DigestServerAuthenticationHelper()
|
||||
throws NoSuchAlgorithmException {
|
||||
messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
|
||||
}
|
||||
|
||||
public static String toHexString(byte[] b) {
|
||||
int pos = 0;
|
||||
char[] c = new char[b.length * 2];
|
||||
for (byte value : b) {
|
||||
c[pos++] = toHex[(value >> 4) & 0x0F];
|
||||
c[pos++] = toHex[value & 0x0f];
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the challenge string.
|
||||
*
|
||||
* @return a generated nonce.
|
||||
*/
|
||||
private String generateNonce() {
|
||||
long time = Instant.now().toEpochMilli();
|
||||
Random rand = new Random();
|
||||
long pad = rand.nextLong();
|
||||
String nonceString = Long.valueOf(time).toString()
|
||||
+ Long.valueOf(pad).toString();
|
||||
byte[] mdBytes = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdBytes);
|
||||
}
|
||||
|
||||
public Response generateChallenge(HeaderFactory headerFactory, Response response, String realm) {
|
||||
try {
|
||||
WWWAuthenticateHeader proxyAuthenticate = headerFactory
|
||||
.createWWWAuthenticateHeader(DEFAULT_SCHEME);
|
||||
proxyAuthenticate.setParameter("realm", realm);
|
||||
proxyAuthenticate.setParameter("qop", "auth");
|
||||
proxyAuthenticate.setParameter("nonce", generateNonce());
|
||||
proxyAuthenticate.setParameter("algorithm", DEFAULT_ALGORITHM);
|
||||
|
||||
response.setHeader(proxyAuthenticate);
|
||||
} catch (Exception ex) {
|
||||
InternalErrorHandler.handleException(ex);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* Authenticate the inbound request.
|
||||
*
|
||||
* @param request - the request to authenticate.
|
||||
* @param hashedPassword -- the MD5 hashed string of username:realm:plaintext password.
|
||||
*
|
||||
* @return true if authentication succeded and false otherwise.
|
||||
*/
|
||||
public boolean doAuthenticateHashedPassword(Request request, String hashedPassword) {
|
||||
AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
||||
if ( authHeader == null ) {
|
||||
return false;
|
||||
}
|
||||
String realm = authHeader.getRealm();
|
||||
String username = authHeader.getUsername();
|
||||
|
||||
if ( username == null || realm == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String nonce = authHeader.getNonce();
|
||||
URI uri = authHeader.getURI();
|
||||
if (uri == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
String HA1 = hashedPassword;
|
||||
|
||||
|
||||
byte[] mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
|
||||
String cnonce = authHeader.getCNonce();
|
||||
String KD = HA1 + ":" + nonce;
|
||||
if (cnonce != null) {
|
||||
KD += ":" + cnonce;
|
||||
}
|
||||
KD += ":" + HA2;
|
||||
mdbytes = messageDigest.digest(KD.getBytes());
|
||||
String mdString = toHexString(mdbytes);
|
||||
String response = authHeader.getResponse();
|
||||
|
||||
|
||||
return mdString.equals(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 鉴权
|
||||
*
|
||||
* A1 = username + ":" + realm + ":" + password
|
||||
* A2 = REGISTER:URI
|
||||
*
|
||||
* HA1 = md5(A1)
|
||||
* HA2 = md5(A2)
|
||||
*
|
||||
* KD = HA2:HA2:qop
|
||||
*
|
||||
* response = md5(KD)
|
||||
* @param request - the request to authenticate.
|
||||
* @param pass -- the plain text password.
|
||||
*
|
||||
* @return true if authentication succeded and false otherwise.
|
||||
*/
|
||||
public boolean doAuthenticatePlainTextPassword(Request request, String pass) {
|
||||
AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
||||
if ( authHeader == null || authHeader.getRealm() == null) {
|
||||
return false;
|
||||
}
|
||||
if ( authHeader.getUsername() == null || authHeader.getRealm() == null ) {
|
||||
return false;
|
||||
}
|
||||
String realm = authHeader.getRealm().trim();
|
||||
String username = authHeader.getUsername().trim();
|
||||
|
||||
String nonce = authHeader.getNonce();
|
||||
URI uri = authHeader.getURI();
|
||||
if (uri == null) {
|
||||
return false;
|
||||
}
|
||||
// qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略
|
||||
String qop = authHeader.getQop();
|
||||
|
||||
// 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。
|
||||
// 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护
|
||||
String cnonce = authHeader.getCNonce();
|
||||
|
||||
// nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
|
||||
int nc = authHeader.getNonceCount();
|
||||
String ncStr = String.format("%08x", nc).toUpperCase();
|
||||
|
||||
String A1 = username + ":" + realm + ":" + pass;
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
|
||||
byte[] mdbytes = messageDigest.digest(A1.getBytes());
|
||||
String HA1 = toHexString(mdbytes);
|
||||
log.debug("A1: {}", A1);
|
||||
log.debug("A2: {}", A2);
|
||||
mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
log.debug("HA1: {}", HA1);
|
||||
log.debug("HA2: {}", HA2);
|
||||
// String cnonce = authHeader.getCNonce();
|
||||
log.debug("nonce: {}", nonce);
|
||||
log.debug("nc: {}", ncStr);
|
||||
log.debug("cnonce: {}", cnonce);
|
||||
log.debug("qop: {}", qop);
|
||||
String KD = HA1 + ":" + nonce;
|
||||
|
||||
if (qop != null && qop.equalsIgnoreCase("auth") ) {
|
||||
if (nc != -1) {
|
||||
KD += ":" + ncStr;
|
||||
}
|
||||
if (cnonce != null) {
|
||||
KD += ":" + cnonce;
|
||||
}
|
||||
KD += ":" + qop;
|
||||
}
|
||||
KD += ":" + HA2;
|
||||
log.debug("KD: {}", KD);
|
||||
mdbytes = messageDigest.digest(KD.getBytes());
|
||||
String mdString = toHexString(mdbytes);
|
||||
log.debug("mdString: {}", mdString);
|
||||
String response = authHeader.getResponse();
|
||||
log.debug("response: {}", response);
|
||||
return mdString.equals(response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 通过redis分发报警消息
|
||||
*/
|
||||
@Data
|
||||
public class AlarmChannelMessage {
|
||||
/**
|
||||
* 通道国标编号
|
||||
*/
|
||||
private String gbId;
|
||||
|
||||
/**
|
||||
* 报警编号
|
||||
*/
|
||||
private int alarmSn;
|
||||
|
||||
/**
|
||||
* 告警类型
|
||||
*/
|
||||
private int alarmType;
|
||||
|
||||
/**
|
||||
* 报警描述
|
||||
*/
|
||||
private String alarmDescription;
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.AudioBroadcastEvent;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 缓存语音广播的状态
|
||||
* @author lin
|
||||
*/
|
||||
@Data
|
||||
public class AudioBroadcastCatch {
|
||||
|
||||
|
||||
public AudioBroadcastCatch(
|
||||
String deviceId,
|
||||
Integer channelId,
|
||||
MediaServer mediaServerItem,
|
||||
String app,
|
||||
String stream,
|
||||
AudioBroadcastEvent event,
|
||||
AudioBroadcastCatchStatus status,
|
||||
boolean isFromPlatform
|
||||
) {
|
||||
this.deviceId = deviceId;
|
||||
this.channelId = channelId;
|
||||
this.status = status;
|
||||
this.event = event;
|
||||
this.isFromPlatform = isFromPlatform;
|
||||
this.app = app;
|
||||
this.stream = stream;
|
||||
this.mediaServerItem = mediaServerItem;
|
||||
}
|
||||
|
||||
public AudioBroadcastCatch() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备编号
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 通道编号
|
||||
*/
|
||||
private Integer channelId;
|
||||
|
||||
/**
|
||||
* 流媒体信息
|
||||
*/
|
||||
private MediaServer mediaServerItem;
|
||||
|
||||
/**
|
||||
* 关联的流APP
|
||||
*/
|
||||
private String app;
|
||||
|
||||
/**
|
||||
* 关联的流STREAM
|
||||
*/
|
||||
private String stream;
|
||||
|
||||
/**
|
||||
* 是否是级联语音喊话
|
||||
*/
|
||||
private boolean isFromPlatform;
|
||||
|
||||
/**
|
||||
* 语音广播状态
|
||||
*/
|
||||
private AudioBroadcastCatchStatus status;
|
||||
|
||||
/**
|
||||
* 请求信息
|
||||
*/
|
||||
private SipTransactionInfo sipTransactionInfo;
|
||||
|
||||
/**
|
||||
* 请求结果回调
|
||||
*/
|
||||
private AudioBroadcastEvent event;
|
||||
|
||||
|
||||
public void setSipTransactionInfoByRequest(SIPResponse sipResponse) {
|
||||
this.sipTransactionInfo = new SipTransactionInfo(sipResponse);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
/**
|
||||
* 语音广播状态
|
||||
* @author lin
|
||||
*/
|
||||
public enum AudioBroadcastCatchStatus {
|
||||
|
||||
// 发送语音广播消息等待对方回复语音广播
|
||||
Ready,
|
||||
// 收到回复等待invite消息
|
||||
WaiteInvite,
|
||||
// 收到invite消息
|
||||
Ok,
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
public class BaiduPoint {
|
||||
|
||||
String bdLng;
|
||||
|
||||
String bdLat;
|
||||
|
||||
public String getBdLng() {
|
||||
return bdLng;
|
||||
}
|
||||
|
||||
public void setBdLng(String bdLng) {
|
||||
this.bdLng = bdLng;
|
||||
}
|
||||
|
||||
public String getBdLat() {
|
||||
return bdLat;
|
||||
}
|
||||
|
||||
public void setBdLat(String bdLat) {
|
||||
this.bdLat = bdLat;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 基础配置
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "基础配置")
|
||||
public class BasicParam {
|
||||
|
||||
@Schema(description = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
@Schema(description = "通道ID,如果时对设备配置直接设置同设备ID一样即可")
|
||||
private String channelId;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "注册过期时间")
|
||||
private String expiration;
|
||||
|
||||
@Schema(description = "心跳间隔时间")
|
||||
private Integer heartBeatInterval;
|
||||
|
||||
@Schema(description = "心跳超时次数")
|
||||
private Integer heartBeatCount;
|
||||
|
||||
@Schema(description = "定位功能支持情况。取值:0-不支持;1-支持 GPS定位;2-支持北斗定位(可选,默认取值为0)," +
|
||||
"用于接受配置查询结果, 基础配置时无效")
|
||||
private Integer positionCapability;
|
||||
|
||||
@Schema(description = "经度(可选),用于接受配置查询结果, 基础配置时无效")
|
||||
private Double longitude;
|
||||
|
||||
@Schema(description = "纬度(可选),用于接受配置查询结果, 基础配置时无效")
|
||||
private Double latitude;
|
||||
|
||||
public static BasicParam getInstance(String name, String expiration, Integer heartBeatInterval, Integer heartBeatCount) {
|
||||
BasicParam basicParam = new BasicParam();
|
||||
basicParam.setName(name);
|
||||
basicParam.setExpiration(expiration);
|
||||
basicParam.setHeartBeatInterval(heartBeatInterval);
|
||||
basicParam.setHeartBeatCount(heartBeatCount);
|
||||
return basicParam;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CatalogChannelEvent extends DeviceChannel{
|
||||
|
||||
private String event;
|
||||
|
||||
private DeviceChannel channel;
|
||||
|
||||
public static CatalogChannelEvent decode(Element element) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
Element eventElement = element.element("Event");
|
||||
CatalogChannelEvent catalogChannelEvent = new CatalogChannelEvent();
|
||||
if (eventElement != null) {
|
||||
catalogChannelEvent.setEvent(eventElement.getText());
|
||||
}else {
|
||||
catalogChannelEvent.setEvent(CatalogEvent.ADD);
|
||||
}
|
||||
DeviceChannel deviceChannel;
|
||||
if (CatalogEvent.ADD.equalsIgnoreCase(catalogChannelEvent.getEvent()) ||
|
||||
CatalogEvent.UPDATE.equalsIgnoreCase(catalogChannelEvent.getEvent()) ){
|
||||
deviceChannel = DeviceChannel.decode(element);
|
||||
}else {
|
||||
deviceChannel = DeviceChannel.decodeWithOnlyDeviceId(element);
|
||||
}
|
||||
catalogChannelEvent.setChannel(deviceChannel);
|
||||
return catalogChannelEvent;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Data
|
||||
public class CatalogData {
|
||||
/**
|
||||
* 命令序列号
|
||||
*/
|
||||
private int sn;
|
||||
private Integer total;
|
||||
private Instant time;
|
||||
private Device device;
|
||||
private String errorMsg;
|
||||
private Set<String> redisKeysForChannel = new HashSet<>();
|
||||
private Set<String> errorChannel = new HashSet<>();
|
||||
private Set<String> redisKeysForRegion = new HashSet<>();
|
||||
private Set<String> redisKeysForGroup = new HashSet<>();
|
||||
|
||||
public enum CatalogDataStatus{
|
||||
ready, runIng, end
|
||||
}
|
||||
private CatalogDataStatus status;
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
public class CmdType {
|
||||
|
||||
public static final String CATALOG = "Catalog";
|
||||
public static final String ALARM = "Alarm";
|
||||
public static final String MOBILE_POSITION = "MobilePosition";
|
||||
}
|
||||
|
|
@ -1,399 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "国标通道")
|
||||
public class CommonGBChannel {
|
||||
|
||||
@Schema(description = "国标-数据库自增ID")
|
||||
private int gbId;
|
||||
|
||||
@Schema(description = "国标-编码")
|
||||
private String gbDeviceId;
|
||||
|
||||
@Schema(description = "国标-名称")
|
||||
private String gbName;
|
||||
|
||||
@Schema(description = "国标-设备厂商")
|
||||
private String gbManufacturer;
|
||||
|
||||
@Schema(description = "国标-设备型号")
|
||||
private String gbModel;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-设备归属")
|
||||
private String gbOwner;
|
||||
|
||||
@Schema(description = "国标-行政区域")
|
||||
private String gbCivilCode;
|
||||
|
||||
@Schema(description = "国标-警区")
|
||||
private String gbBlock;
|
||||
|
||||
@Schema(description = "国标-安装地址")
|
||||
private String gbAddress;
|
||||
|
||||
@Schema(description = "国标-是否有子设备")
|
||||
private Integer gbParental;
|
||||
|
||||
@Schema(description = "国标-父节点ID")
|
||||
private String gbParentId;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-信令安全模式")
|
||||
private Integer gbSafetyWay;
|
||||
|
||||
@Schema(description = "国标-注册方式")
|
||||
private Integer gbRegisterWay;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-证书序列号")
|
||||
private String gbCertNum;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-证书有效标识")
|
||||
private Integer gbCertifiable;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-无效原因码(有证书且证书无效的设备必选)")
|
||||
private Integer gbErrCode;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-证书终止有效期(有证书且证书无效的设备必选)")
|
||||
private String gbEndTime;
|
||||
|
||||
@Schema(description = "国标-保密属性(必选)缺省为0;0-不涉密,1-涉密")
|
||||
private Integer gbSecrecy;
|
||||
|
||||
@Schema(description = "国标-设备/系统IPv4/IPv6地址")
|
||||
private String gbIpAddress;
|
||||
|
||||
@Schema(description = "国标-设备/系统端口")
|
||||
private Integer gbPort;
|
||||
|
||||
@Schema(description = "国标-设备口令")
|
||||
private String gbPassword;
|
||||
|
||||
@Schema(description = "国标-设备状态")
|
||||
private String gbStatus;
|
||||
|
||||
@Schema(description = "国标-经度 WGS-84坐标系")
|
||||
private Double gbLongitude;
|
||||
|
||||
@Schema(description = "国标-纬度 WGS-84坐标系")
|
||||
private Double gbLatitude;
|
||||
|
||||
private Double gpsAltitude;
|
||||
|
||||
private Double gpsSpeed;
|
||||
|
||||
private Double gpsDirection;
|
||||
|
||||
private String gpsTime;
|
||||
|
||||
@Schema(description = "国标-虚拟组织所属的业务分组ID")
|
||||
private String gbBusinessGroupId;
|
||||
|
||||
@Schema(description = "国标-摄像机结构类型,标识摄像机类型: 1-球机; 2-半球; 3-固定枪机; 4-遥控枪机;5-遥控半球;6-多目设备的全景/拼接通道;" +
|
||||
"7-多目设备的分割通道; 99-移动设备(非标)98-会议设备(非标)")
|
||||
private Integer gbPtzType;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "-摄像机位置类型扩展。1-省际检查站、2-党政机关、3-车站码头、4-中心广场、5-体育场馆、6-商业中心、7-宗教场所、" +
|
||||
"8-校园周边、9-治安复杂区域、10-交通干线。当目录项为摄像机时可选。")
|
||||
private Integer gbPositionType;
|
||||
|
||||
@Schema(description = "国标-摄像机安装位置室外、室内属性。1-室外、2-室内。")
|
||||
private Integer gbRoomType;
|
||||
|
||||
// 2016
|
||||
@Schema(description = "国标-用途属性")
|
||||
private Integer gbUseType;
|
||||
|
||||
@Schema(description = "国标-摄像机补光属性。1-无补光;2-红外补光;3-白光补光;4-激光补光;9-其他")
|
||||
private Integer gbSupplyLightType;
|
||||
|
||||
@Schema(description = "国标-摄像机监视方位(光轴方向)属性。1-东(西向东)、2-西(东向西)、3-南(北向南)、4-北(南向北)、" +
|
||||
"5-东南(西北到东南)、6-东北(西南到东北)、7-西南(东北到西南)、8-西北(东南到西北)")
|
||||
private Integer gbDirectionType;
|
||||
|
||||
@Schema(description = "国标-摄像机支持的分辨率,可多值")
|
||||
private String gbResolution;
|
||||
|
||||
@Schema(description = "国标-下载倍速(可选),可多值")
|
||||
private String gbDownloadSpeed;
|
||||
|
||||
@Schema(description = "国标-空域编码能力,取值0-不支持;1-1级增强(1个增强层);2-2级增强(2个增强层);3-3级增强(3个增强层)")
|
||||
private Integer gbSvcSpaceSupportMod;
|
||||
|
||||
@Schema(description = "国标-时域编码能力,取值0-不支持;1-1级增强;2-2级增强;3-3级增强(可选)")
|
||||
private Integer gbSvcTimeSupportMode;
|
||||
|
||||
@Schema(description = "二进制保存的录制计划, 每一位表示每个小时的前半个小时")
|
||||
private Long recordPLan;
|
||||
|
||||
@Schema(description = "关联的数据类型")
|
||||
private Integer dataType;
|
||||
|
||||
@Schema(description = "关联的设备ID")
|
||||
private Integer dataDeviceId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private String updateTime;
|
||||
|
||||
@Schema(description = "流唯一编号,存在表示正在直播")
|
||||
private String streamId;
|
||||
|
||||
@Schema(description = "是否支持对讲 1支持,0不支持")
|
||||
private Integer enableBroadcast;
|
||||
|
||||
@Schema(description = "抽稀后的图层层级")
|
||||
private Integer mapLevel;
|
||||
|
||||
public String encode(String serverDeviceId) {
|
||||
return encode(null, serverDeviceId);
|
||||
}
|
||||
|
||||
public String encode(String event,String serverDeviceId) {
|
||||
String content;
|
||||
if (event == null) {
|
||||
return getFullContent(null, serverDeviceId);
|
||||
}
|
||||
switch (event) {
|
||||
case CatalogEvent.DEL:
|
||||
case CatalogEvent.DEFECT:
|
||||
case CatalogEvent.VLOST:
|
||||
content = "<Item>\n" +
|
||||
"<DeviceID>" + this.getGbDeviceId() + "</DeviceID>\n" +
|
||||
"<Event>" + event + "</Event>\n" +
|
||||
"</Item>\n";
|
||||
break;
|
||||
case CatalogEvent.ON:
|
||||
case CatalogEvent.OFF:
|
||||
content = "<Item>\n" +
|
||||
"<DeviceID>" + this.getGbDeviceId() + "</DeviceID>\n" +
|
||||
"<Event>" + event + "</Event>\r\n" +
|
||||
"</Item>\n";
|
||||
break;
|
||||
case CatalogEvent.ADD:
|
||||
case CatalogEvent.UPDATE:
|
||||
content = getFullContent(event, serverDeviceId);
|
||||
break;
|
||||
default:
|
||||
content = null;
|
||||
break;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private String getFullContent(String event, String serverDeviceId) {
|
||||
StringBuilder content = new StringBuilder();
|
||||
// 行政区划目录项
|
||||
content.append("<Item>\n")
|
||||
.append("<DeviceID>" + this.getGbDeviceId() + "</DeviceID>\n")
|
||||
.append("<Name>" + this.getGbName() + "</Name>\n");
|
||||
|
||||
|
||||
if (this.getGbDeviceId().length() > 8) {
|
||||
|
||||
String type = this.getGbDeviceId().substring(10, 13);
|
||||
if (type.equals("200")) {
|
||||
// 业务分组目录项
|
||||
if (this.getGbManufacturer() != null) {
|
||||
content.append("<Manufacturer>" + this.getGbManufacturer() + "</Manufacturer>\n");
|
||||
}
|
||||
if (this.getGbModel() != null) {
|
||||
content.append("<Model>" + this.getGbModel() + "</Model>\n");
|
||||
}
|
||||
if (this.getGbOwner() != null) {
|
||||
content.append("<Owner>" + this.getGbOwner() + "</Owner>\n");
|
||||
}
|
||||
if (this.getGbCivilCode() != null) {
|
||||
content.append("<CivilCode>" + this.getGbCivilCode() + "</CivilCode>\n");
|
||||
}
|
||||
if (this.getGbAddress() != null) {
|
||||
content.append("<Address>" + this.getGbAddress() + "</Address>\n");
|
||||
}
|
||||
if (this.getGbRegisterWay() != null) {
|
||||
content.append("<RegisterWay>" + this.getGbRegisterWay() + "</RegisterWay>\n");
|
||||
}
|
||||
if (this.getGbSecrecy() != null) {
|
||||
content.append("<Secrecy>" + this.getGbSecrecy() + "</Secrecy>\n");
|
||||
}
|
||||
} else if (type.equals("215")) {
|
||||
// 业务分组
|
||||
if (this.getGbCivilCode() != null) {
|
||||
content.append("<CivilCode>" + this.getGbCivilCode() + "</CivilCode>\n");
|
||||
}
|
||||
content.append("<ParentID>" + serverDeviceId + "</ParentID>\n");
|
||||
} else if (type.equals("216")) {
|
||||
// 虚拟组织目录项
|
||||
if (this.getGbCivilCode() != null) {
|
||||
content.append("<CivilCode>" + this.getGbCivilCode() + "</CivilCode>\n");
|
||||
}
|
||||
if (this.getGbParentId() != null) {
|
||||
content.append("<ParentID>" + this.getGbParentId() + "</ParentID>\n");
|
||||
}
|
||||
content.append("<BusinessGroupID>" + this.getGbBusinessGroupId() + "</BusinessGroupID>\n");
|
||||
} else {
|
||||
if (this.getGbManufacturer() != null) {
|
||||
content.append("<Manufacturer>" + this.getGbManufacturer() + "</Manufacturer>\n");
|
||||
}
|
||||
if (this.getGbModel() != null) {
|
||||
content.append("<Model>" + this.getGbModel() + "</Model>\n");
|
||||
}
|
||||
if (this.getGbOwner() != null) {
|
||||
content.append("<Owner>" + this.getGbOwner() + "</Owner>\n");
|
||||
}
|
||||
if (this.getGbCivilCode() != null) {
|
||||
content.append("<CivilCode>" + this.getGbCivilCode() + "</CivilCode>\n");
|
||||
}
|
||||
if (this.getGbAddress() != null) {
|
||||
content.append("<Address>" + this.getGbAddress() + "</Address>\n");
|
||||
}
|
||||
if (this.getGbRegisterWay() != null) {
|
||||
content.append("<RegisterWay>" + this.getGbRegisterWay() + "</RegisterWay>\n");
|
||||
}
|
||||
if (this.getGbSecrecy() != null) {
|
||||
content.append("<Secrecy>" + this.getGbSecrecy() + "</Secrecy>\n");
|
||||
}
|
||||
if (this.getGbParentId() != null) {
|
||||
content.append("<ParentID>" + this.getGbParentId() + "</ParentID>\n");
|
||||
}
|
||||
if (this.getGbParental() != null) {
|
||||
content.append("<Parental>" + this.getGbParental() + "</Parental>\n");
|
||||
}
|
||||
if (this.getGbSafetyWay() != null) {
|
||||
content.append("<SafetyWay>" + this.getGbSafetyWay() + "</SafetyWay>\n");
|
||||
}
|
||||
if (this.getGbRegisterWay() != null) {
|
||||
content.append("<RegisterWay>" + this.getGbRegisterWay() + "</RegisterWay>\n");
|
||||
}
|
||||
if (this.getGbCertNum() != null) {
|
||||
content.append("<CertNum>" + this.getGbCertNum() + "</CertNum>\n");
|
||||
}
|
||||
if (this.getGbCertifiable() != null) {
|
||||
content.append("<Certifiable>" + this.getGbCertifiable() + "</Certifiable>\n");
|
||||
}
|
||||
if (this.getGbErrCode() != null) {
|
||||
content.append("<ErrCode>" + this.getGbErrCode() + "</ErrCode>\n");
|
||||
}
|
||||
if (this.getGbEndTime() != null) {
|
||||
content.append("<EndTime>" + this.getGbEndTime() + "</EndTime>\n");
|
||||
}
|
||||
if (this.getGbSecrecy() != null) {
|
||||
content.append("<Secrecy>" + this.getGbSecrecy() + "</Secrecy>\n");
|
||||
}
|
||||
if (this.getGbIpAddress() != null) {
|
||||
content.append("<IPAddress>" + this.getGbIpAddress() + "</IPAddress>\n");
|
||||
}
|
||||
if (this.getGbPort() != null) {
|
||||
content.append("<Port>" + this.getGbPort() + "</Port>\n");
|
||||
}
|
||||
if (this.getGbPassword() != null) {
|
||||
content.append("<Password>" + this.getGbPassword() + "</Password>\n");
|
||||
}
|
||||
if (this.getGbStatus() != null) {
|
||||
content.append("<Status>" + this.getGbStatus() + "</Status>\n");
|
||||
}
|
||||
if (this.getGbLongitude() != null) {
|
||||
content.append("<Longitude>" + this.getGbLongitude() + "</Longitude>\n");
|
||||
}
|
||||
if (this.getGbLatitude() != null) {
|
||||
content.append("<Latitude>" + this.getGbLatitude() + "</Latitude>\n");
|
||||
}
|
||||
content.append("<Info>\n");
|
||||
|
||||
if (this.getGbPtzType() != null) {
|
||||
content.append(" <PTZType>" + this.getGbPtzType() + "</PTZType>\n");
|
||||
}
|
||||
if (this.getGbPositionType() != null) {
|
||||
content.append(" <PositionType>" + this.getGbPositionType() + "</PositionType>\n");
|
||||
}
|
||||
if (this.getGbRoomType() != null) {
|
||||
content.append(" <RoomType>" + this.getGbRoomType() + "</RoomType>\n");
|
||||
}
|
||||
if (this.getGbUseType() != null) {
|
||||
content.append(" <UseType>" + this.getGbUseType() + "</UseType>\n");
|
||||
}
|
||||
if (this.getGbSupplyLightType() != null) {
|
||||
content.append(" <SupplyLightType>" + this.getGbSupplyLightType() + "</SupplyLightType>\n");
|
||||
}
|
||||
if (this.getGbDirectionType() != null) {
|
||||
content.append(" <DirectionType>" + this.getGbDirectionType() + "</DirectionType>\n");
|
||||
}
|
||||
if (this.getGbResolution() != null) {
|
||||
content.append(" <Resolution>" + this.getGbResolution() + "</Resolution>\n");
|
||||
}
|
||||
if (this.getGbBusinessGroupId() != null) {
|
||||
content.append(" <BusinessGroupID>" + this.getGbBusinessGroupId() + "</BusinessGroupID>\n");
|
||||
}
|
||||
if (this.getGbDownloadSpeed() != null) {
|
||||
content.append(" <DownloadSpeed>" + this.getGbDownloadSpeed() + "</DownloadSpeed>\n");
|
||||
}
|
||||
if (this.getGbSvcSpaceSupportMod() != null) {
|
||||
content.append(" <SVCSpaceSupportMode>" + this.getGbSvcSpaceSupportMod() + "</SVCSpaceSupportMode>\n");
|
||||
}
|
||||
if (this.getGbSvcTimeSupportMode() != null) {
|
||||
content.append(" <SVCTimeSupportMode>" + this.getGbSvcTimeSupportMode() + "</SVCTimeSupportMode>\n");
|
||||
}
|
||||
if (this.getEnableBroadcast() != null) {
|
||||
content.append(" <EnableBroadcast>" + this.getEnableBroadcast() + "</EnableBroadcast>\n");
|
||||
}
|
||||
content.append("</Info>\n");
|
||||
}
|
||||
}
|
||||
if (event != null) {
|
||||
content.append("<Event>" + event + "</Event>\n");
|
||||
}
|
||||
content.append("</Item>\n");
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static CommonGBChannel build(Group group) {
|
||||
GbCode gbCode = GbCode.decode(group.getDeviceId());
|
||||
CommonGBChannel channel = new CommonGBChannel();
|
||||
if (gbCode.getTypeCode().equals("215")) {
|
||||
// 业务分组
|
||||
channel.setGbName(group.getName());
|
||||
channel.setGbDeviceId(group.getDeviceId());
|
||||
channel.setGbCivilCode(group.getCivilCode());
|
||||
} else {
|
||||
// 虚拟组织
|
||||
channel.setGbName(group.getName());
|
||||
channel.setGbDeviceId(group.getDeviceId());
|
||||
channel.setGbParentId(group.getParentDeviceId());
|
||||
channel.setGbBusinessGroupId(group.getBusinessGroup());
|
||||
channel.setGbCivilCode(group.getCivilCode());
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
public static CommonGBChannel build(Platform platform) {
|
||||
CommonGBChannel commonGBChannel = new CommonGBChannel();
|
||||
commonGBChannel.setGbDeviceId(platform.getDeviceGBId());
|
||||
commonGBChannel.setGbName(platform.getName());
|
||||
commonGBChannel.setGbManufacturer(platform.getManufacturer());
|
||||
commonGBChannel.setGbModel(platform.getModel());
|
||||
commonGBChannel.setGbCivilCode(platform.getCivilCode());
|
||||
commonGBChannel.setGbAddress(platform.getAddress());
|
||||
commonGBChannel.setGbRegisterWay(platform.getRegisterWay());
|
||||
commonGBChannel.setGbSecrecy(platform.getSecrecy());
|
||||
commonGBChannel.setGbStatus(platform.isStatus() ? "ON" : "OFF");
|
||||
return commonGBChannel;
|
||||
}
|
||||
|
||||
public static CommonGBChannel build(Region region) {
|
||||
CommonGBChannel commonGBChannel = new CommonGBChannel();
|
||||
commonGBChannel.setGbDeviceId(region.getDeviceId());
|
||||
commonGBChannel.setGbName(region.getName());
|
||||
return commonGBChannel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CommonRecordInfo {
|
||||
|
||||
// 开始时间
|
||||
private String startTime;
|
||||
|
||||
// 结束时间
|
||||
private String endTime;
|
||||
|
||||
// 文件大小 单位byte
|
||||
private String fileSize;
|
||||
|
||||
}
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 国标设备/平台
|
||||
* @author lin
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "国标设备/平台")
|
||||
public class Device {
|
||||
|
||||
@Schema(description = "数据库自增ID")
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* 设备国标编号
|
||||
*/
|
||||
@Schema(description = "设备国标编号")
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 设备名
|
||||
*/
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 生产厂商
|
||||
*/
|
||||
@Schema(description = "生产厂商")
|
||||
private String manufacturer;
|
||||
|
||||
/**
|
||||
* 型号
|
||||
*/
|
||||
@Schema(description = "型号")
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
@Schema(description = "固件版本")
|
||||
private String firmware;
|
||||
|
||||
/**
|
||||
* 传输协议
|
||||
* UDP/TCP
|
||||
*/
|
||||
@Schema(description = "传输协议(UDP/TCP)")
|
||||
private String transport;
|
||||
|
||||
/**
|
||||
* 数据流传输模式
|
||||
* UDP:udp传输
|
||||
* TCP-ACTIVE:tcp主动模式
|
||||
* TCP-PASSIVE:tcp被动模式
|
||||
*/
|
||||
@Schema(description = "数据流传输模式")
|
||||
private String streamMode;
|
||||
|
||||
/**
|
||||
* wan地址_ip
|
||||
*/
|
||||
@Schema(description = "IP")
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* wan地址_port
|
||||
*/
|
||||
@Schema(description = "端口")
|
||||
private int port;
|
||||
|
||||
/**
|
||||
* wan地址
|
||||
*/
|
||||
@Schema(description = "wan地址")
|
||||
private String hostAddress;
|
||||
|
||||
/**
|
||||
* 在线
|
||||
*/
|
||||
@Schema(description = "是否在线,true为在线,false为离线")
|
||||
private boolean onLine;
|
||||
|
||||
|
||||
/**
|
||||
* 注册时间
|
||||
*/
|
||||
@Schema(description = "注册时间")
|
||||
private String registerTime;
|
||||
|
||||
|
||||
/**
|
||||
* 心跳时间
|
||||
*/
|
||||
@Schema(description = "心跳时间")
|
||||
private String keepaliveTime;
|
||||
|
||||
|
||||
/**
|
||||
* 心跳间隔
|
||||
*/
|
||||
@Schema(description = "心跳间隔")
|
||||
private Integer heartBeatInterval;
|
||||
|
||||
|
||||
/**
|
||||
* 心跳超时次数
|
||||
*/
|
||||
@Schema(description = "心跳超时次数")
|
||||
private Integer heartBeatCount;
|
||||
|
||||
|
||||
/**
|
||||
* 定位功能支持情况
|
||||
*/
|
||||
@Schema(description = "定位功能支持情况。取值:0-不支持;1-支持 GPS定位;2-支持北斗定位(可选,默认取值为0")
|
||||
private Integer positionCapability;
|
||||
|
||||
/**
|
||||
* 通道个数
|
||||
*/
|
||||
@Schema(description = "通道个数")
|
||||
private int channelCount;
|
||||
|
||||
/**
|
||||
* 注册有效期
|
||||
*/
|
||||
@Schema(description = "注册有效期")
|
||||
private int expires;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description = "更新时间")
|
||||
private String updateTime;
|
||||
|
||||
/**
|
||||
* 设备使用的媒体id, 默认为null
|
||||
*/
|
||||
@Schema(description = "设备使用的媒体id, 默认为null")
|
||||
private String mediaServerId;
|
||||
|
||||
/**
|
||||
* 字符集, 支持 UTF-8 与 GB2312
|
||||
*/
|
||||
@Schema(description = "符集, 支持 UTF-8 与 GB2312")
|
||||
private String charset ;
|
||||
|
||||
/**
|
||||
* 目录订阅周期,0为不订阅
|
||||
*/
|
||||
@Schema(description = "目录订阅周期,o为不订阅")
|
||||
private int subscribeCycleForCatalog;
|
||||
|
||||
/**
|
||||
* 移动设备位置订阅周期,0为不订阅
|
||||
*/
|
||||
@Schema(description = "移动设备位置订阅周期,0为不订阅")
|
||||
private int subscribeCycleForMobilePosition;
|
||||
|
||||
/**
|
||||
* 移动设备位置信息上报时间间隔,单位:秒,默认值5
|
||||
*/
|
||||
@Schema(description = "移动设备位置信息上报时间间隔,单位:秒,默认值5")
|
||||
private int mobilePositionSubmissionInterval = 5;
|
||||
|
||||
/**
|
||||
* 报警订阅周期,0为不订阅
|
||||
*/
|
||||
@Schema(description = "报警心跳时间订阅周期,0为不订阅")
|
||||
private int subscribeCycleForAlarm;
|
||||
|
||||
/**
|
||||
* 是否开启ssrc校验,默认关闭,开启可以防止串流
|
||||
*/
|
||||
@Schema(description = "是否开启ssrc校验,默认关闭,开启可以防止串流")
|
||||
private boolean ssrcCheck = false;
|
||||
|
||||
/**
|
||||
* 地理坐标系, 目前支持 WGS84,GCJ02, 此字段保留,暂无用
|
||||
*/
|
||||
@Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02")
|
||||
private String geoCoordSys;
|
||||
|
||||
@Schema(description = "密码")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "收流IP")
|
||||
private String sdpIp;
|
||||
|
||||
@Schema(description = "SIP交互IP(设备访问平台的IP)")
|
||||
private String localIp;
|
||||
|
||||
@Schema(description = "是否作为消息通道")
|
||||
private boolean asMessageChannel;
|
||||
|
||||
@Schema(description = "设备注册的事务信息")
|
||||
private SipTransactionInfo sipTransactionInfo;
|
||||
|
||||
@Schema(description = "控制语音对讲流程,释放收到ACK后发流")
|
||||
private boolean broadcastPushAfterAck;
|
||||
|
||||
@Schema(description = "所属服务Id")
|
||||
private String serverId;
|
||||
|
||||
public boolean checkWgs84() {
|
||||
return geoCoordSys.equalsIgnoreCase("WGS84");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Schema(description = "报警信息")
|
||||
@Data
|
||||
public class DeviceAlarm {
|
||||
|
||||
@Schema(description = "数据库id")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "设备的国标编号")
|
||||
private String deviceId;
|
||||
|
||||
@Schema(description = "设备名称")
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 通道Id
|
||||
*/
|
||||
@Schema(description = "通道的国标编号")
|
||||
private String channelId;
|
||||
|
||||
/**
|
||||
* 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情
|
||||
*/
|
||||
@Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情")
|
||||
private String alarmPriority;
|
||||
|
||||
@Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情")
|
||||
private String alarmPriorityDescription;
|
||||
|
||||
public String getAlarmPriorityDescription() {
|
||||
switch (alarmPriority) {
|
||||
case "1":
|
||||
return "一级警情";
|
||||
case "2":
|
||||
return "二级警情";
|
||||
case "3":
|
||||
return "三级警情";
|
||||
case "4":
|
||||
return "四级警情";
|
||||
default:
|
||||
return alarmPriority;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
||||
* 7其他报警;可以为直接组合如12为电话报警或 设备报警-
|
||||
*/
|
||||
@Schema(description = "报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,\n" +
|
||||
"\t * 7其他报警;可以为直接组合如12为电话报警或设备报警")
|
||||
private String alarmMethod;
|
||||
|
||||
|
||||
private String alarmMethodDescription;
|
||||
|
||||
public String getAlarmMethodDescription() {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
char[] charArray = alarmMethod.toCharArray();
|
||||
for (char c : charArray) {
|
||||
switch (c) {
|
||||
case '1':
|
||||
stringBuilder.append("-电话报警");
|
||||
break;
|
||||
case '2':
|
||||
stringBuilder.append("-设备报警");
|
||||
break;
|
||||
case '3':
|
||||
stringBuilder.append("-短信报警");
|
||||
break;
|
||||
case '4':
|
||||
stringBuilder.append("-GPS报警");
|
||||
break;
|
||||
case '5':
|
||||
stringBuilder.append("-视频报警");
|
||||
break;
|
||||
case '6':
|
||||
stringBuilder.append("-设备故障报警");
|
||||
break;
|
||||
case '7':
|
||||
stringBuilder.append("-其他报警");
|
||||
break;
|
||||
}
|
||||
}
|
||||
stringBuilder.delete(0, 1);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 报警时间
|
||||
*/
|
||||
@Schema(description = "报警时间")
|
||||
private String alarmTime;
|
||||
|
||||
/**
|
||||
* 报警内容描述
|
||||
*/
|
||||
@Schema(description = "报警内容描述")
|
||||
private String alarmDescription;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
@Schema(description = "经度")
|
||||
private double longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
@Schema(description = "纬度")
|
||||
private double latitude;
|
||||
|
||||
/**
|
||||
* 报警类型,
|
||||
* 报警方式为2时,不携带 AlarmType为默认的报警设备报警,
|
||||
* 携带 AlarmType取值及对应报警类型如下:
|
||||
* 1-视频丢失报警;
|
||||
* 2-设备防拆报警;
|
||||
* 3-存储设备磁盘满报警;
|
||||
* 4-设备高温报警;
|
||||
* 5-设备低温报警。
|
||||
* 报警方式为5时,取值如下:
|
||||
* 1-人工视频报警;
|
||||
* 2-运动目标检测报警;
|
||||
* 3-遗留物检测报警;
|
||||
* 4-物体移除检测报警;
|
||||
* 5-绊线检测报警;
|
||||
* 6-入侵检测报警;
|
||||
* 7-逆行检测报警;
|
||||
* 8-徘徊检测报警;
|
||||
* 9-流量统计报警;
|
||||
* 10-密度检测报警;
|
||||
* 11-视频异常检测报警;
|
||||
* 12-快速移动报警。
|
||||
* 报警方式为6时,取值下:
|
||||
* 1-存储设备磁盘故障报警;
|
||||
* 2-存储设备风扇故障报警。
|
||||
*/
|
||||
@Schema(description = "报警类型")
|
||||
private String alarmType;
|
||||
|
||||
public String getAlarmTypeDescription() {
|
||||
if (alarmType == null) {
|
||||
return "";
|
||||
}
|
||||
char[] charArray = alarmMethod.toCharArray();
|
||||
Set<String> alarmMethodSet = new HashSet<>();
|
||||
for (char c : charArray) {
|
||||
alarmMethodSet.add(Character.toString(c));
|
||||
}
|
||||
String result = alarmType;
|
||||
if (alarmMethodSet.contains("2")) {
|
||||
switch (alarmType) {
|
||||
case "1":
|
||||
result = "视频丢失报警";
|
||||
break;
|
||||
case "2":
|
||||
result = "设备防拆报警";
|
||||
break;
|
||||
case "3":
|
||||
result = "存储设备磁盘满报警";
|
||||
break;
|
||||
case "4":
|
||||
result = "设备高温报警";
|
||||
break;
|
||||
case "5":
|
||||
result = "设备低温报警";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alarmMethodSet.contains("5")) {
|
||||
switch (alarmType) {
|
||||
case "1":
|
||||
result = "人工视频报警";
|
||||
break;
|
||||
case "2":
|
||||
result = "运动目标检测报警";
|
||||
break;
|
||||
case "3":
|
||||
result = "遗留物检测报警";
|
||||
break;
|
||||
case "4":
|
||||
result = "物体移除检测报警";
|
||||
break;
|
||||
case "5":
|
||||
result = "绊线检测报警";
|
||||
break;
|
||||
case "6":
|
||||
result = "入侵检测报警";
|
||||
break;
|
||||
case "7":
|
||||
result = "逆行检测报警";
|
||||
break;
|
||||
case "8":
|
||||
result = "徘徊检测报警";
|
||||
break;
|
||||
case "9":
|
||||
result = "流量统计报警";
|
||||
break;
|
||||
case "10":
|
||||
result = "密度检测报警";
|
||||
break;
|
||||
case "11":
|
||||
result = "视频异常检测报警";
|
||||
break;
|
||||
case "12":
|
||||
result = "快速移动报警";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alarmMethodSet.contains("6")) {
|
||||
switch (alarmType) {
|
||||
case "1":
|
||||
result = "人工视频报警";
|
||||
break;
|
||||
case "2":
|
||||
result = "运动目标检测报警";
|
||||
break;
|
||||
case "3":
|
||||
result = "遗留物检测报警";
|
||||
break;
|
||||
case "4":
|
||||
result = "物体移除检测报警";
|
||||
break;
|
||||
case "5":
|
||||
result = "绊线检测报警";
|
||||
break;
|
||||
case "6":
|
||||
result = "入侵检测报警";
|
||||
break;
|
||||
case "7":
|
||||
result = "逆行检测报警";
|
||||
break;
|
||||
case "8":
|
||||
result = "徘徊检测报警";
|
||||
break;
|
||||
case "9":
|
||||
result = "流量统计报警";
|
||||
break;
|
||||
case "10":
|
||||
result = "密度检测报警";
|
||||
break;
|
||||
case "11":
|
||||
result = "视频异常检测报警";
|
||||
break;
|
||||
case "12":
|
||||
result = "快速移动报警";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Schema(description = "报警类型描述")
|
||||
private String alarmTypeDescription;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
/**
|
||||
* 报警方式
|
||||
* @author lin
|
||||
* 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
||||
* 7其他报警;可以为直接组合如12为电话报警或 设备报警-
|
||||
*/
|
||||
public enum DeviceAlarmMethod {
|
||||
// 1为电话报警
|
||||
Telephone(1),
|
||||
|
||||
// 2为设备报警
|
||||
Device(2),
|
||||
|
||||
// 3为短信报警
|
||||
SMS(3),
|
||||
|
||||
// 4为 GPS报警
|
||||
GPS(4),
|
||||
|
||||
// 5为视频报警
|
||||
Video(5),
|
||||
|
||||
// 6为设备故障报警
|
||||
DeviceFailure(6),
|
||||
|
||||
// 7其他报警
|
||||
Other(7);
|
||||
|
||||
private final int val;
|
||||
|
||||
DeviceAlarmMethod(int val) {
|
||||
this.val=val;
|
||||
}
|
||||
|
||||
public int getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询是否匹配类型
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public static DeviceAlarmMethod typeOf(int code) {
|
||||
for (DeviceAlarmMethod item : DeviceAlarmMethod.values()) {
|
||||
if (code==item.getVal()) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,265 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.MessageElementForCatalog;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dom4j.Element;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@Schema(description = "通道信息")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DeviceChannel extends CommonGBChannel {
|
||||
|
||||
@Schema(description = "数据库自增ID")
|
||||
private int id;
|
||||
|
||||
@Schema(description = "父设备编码")
|
||||
private String parentDeviceId;
|
||||
|
||||
@Schema(description = "父设备名称")
|
||||
private String parentName;
|
||||
|
||||
@MessageElementForCatalog("DeviceID")
|
||||
@Schema(description = "编码")
|
||||
private String deviceId;
|
||||
|
||||
@MessageElementForCatalog("Name")
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@MessageElementForCatalog("Manufacturer")
|
||||
@Schema(description = "设备厂商")
|
||||
private String manufacturer;
|
||||
|
||||
@MessageElementForCatalog("Model")
|
||||
@Schema(description = "设备型号")
|
||||
private String model;
|
||||
|
||||
// 2016
|
||||
@MessageElementForCatalog("Owner")
|
||||
@Schema(description = "设备归属")
|
||||
private String owner;
|
||||
|
||||
@MessageElementForCatalog("CivilCode")
|
||||
@Schema(description = "行政区域")
|
||||
private String civilCode;
|
||||
|
||||
@MessageElementForCatalog("Block")
|
||||
@Schema(description = "警区")
|
||||
private String block;
|
||||
|
||||
@MessageElementForCatalog("Address")
|
||||
@Schema(description = "安装地址")
|
||||
private String address;
|
||||
|
||||
@MessageElementForCatalog("Parental")
|
||||
@Schema(description = "是否有子设备(必选)1有,0没有")
|
||||
private Integer parental;
|
||||
|
||||
|
||||
@MessageElementForCatalog("ParentID")
|
||||
@Schema(description = "父节点ID")
|
||||
private String parentId;
|
||||
|
||||
// 2016
|
||||
@MessageElementForCatalog("SafetyWay")
|
||||
@Schema(description = "信令安全模式")
|
||||
private Integer safetyWay;
|
||||
|
||||
@MessageElementForCatalog("RegisterWay")
|
||||
@Schema(description = "注册方式")
|
||||
private Integer registerWay;
|
||||
|
||||
// 2016
|
||||
@MessageElementForCatalog("CertNum")
|
||||
@Schema(description = "证书序列号")
|
||||
private String certNum;
|
||||
|
||||
// 2016
|
||||
@MessageElementForCatalog("Certifiable")
|
||||
@Schema(description = "证书有效标识, 缺省为0;证书有效标识:0:无效 1:有效")
|
||||
private Integer certifiable;
|
||||
|
||||
// 2016
|
||||
@MessageElementForCatalog("ErrCode")
|
||||
@Schema(description = "无效原因码(有证书且证书无效的设备必选)")
|
||||
private Integer errCode;
|
||||
|
||||
// 2016
|
||||
@MessageElementForCatalog("EndTime")
|
||||
@Schema(description = "证书终止有效期(有证书且证书无效的设备必选)")
|
||||
private String endTime;
|
||||
|
||||
@MessageElementForCatalog("Secrecy")
|
||||
@Schema(description = "保密属性(必选)缺省为0;0-不涉密,1-涉密")
|
||||
private Integer secrecy;
|
||||
|
||||
@MessageElementForCatalog("IPAddress")
|
||||
@Schema(description = "设备/系统IPv4/IPv6地址")
|
||||
private String ipAddress;
|
||||
|
||||
@MessageElementForCatalog("Port")
|
||||
@Schema(description = "设备/系统端口")
|
||||
private Integer port;
|
||||
|
||||
@MessageElementForCatalog("Password")
|
||||
@Schema(description = "设备口令")
|
||||
private String password;
|
||||
|
||||
@MessageElementForCatalog("Status")
|
||||
@Schema(description = "设备状态")
|
||||
private String status;
|
||||
|
||||
@MessageElementForCatalog("Longitude")
|
||||
@Schema(description = "经度 WGS-84坐标系")
|
||||
private Double longitude;
|
||||
|
||||
@MessageElementForCatalog("Latitude")
|
||||
@Schema(description = ",纬度 WGS-84坐标系")
|
||||
private Double latitude;
|
||||
|
||||
@MessageElementForCatalog("Info.PTZType")
|
||||
@Schema(description = "摄像机结构类型,标识摄像机类型: 1-球机; 2-半球; 3-固定枪机; 4-遥控枪机;5-遥控半球;6-多目设备的全景/拼接通道;7-多目设备的分割通道")
|
||||
private Integer ptzType;
|
||||
|
||||
@MessageElementForCatalog("Info.PositionType")
|
||||
@Schema(description = "摄像机位置类型扩展。1-省际检查站、2-党政机关、3-车站码头、4-中心广场、5-体育场馆、" +
|
||||
"6-商业中心、7-宗教场所、8-校园周边、9-治安复杂区域、10-交通干线")
|
||||
private Integer positionType;
|
||||
|
||||
@MessageElementForCatalog("Info.RoomType")
|
||||
@Schema(description = "摄像机安装位置室外、室内属性。1-室外、2-室内。")
|
||||
private Integer roomType;
|
||||
|
||||
@MessageElementForCatalog("Info.UseType")
|
||||
@Schema(description = "用途属性, 1-治安、2-交通、3-重点。")
|
||||
private Integer useType;
|
||||
|
||||
@MessageElementForCatalog("Info.SupplyLightType")
|
||||
@Schema(description = "摄像机补光属性。1-无补光;2-红外补光;3-白光补光;4-激光补光;9-其他")
|
||||
private Integer supplyLightType;
|
||||
|
||||
@MessageElementForCatalog("Info.DirectionType")
|
||||
@Schema(description = "摄像机监视方位(光轴方向)属性。1-东(西向东)、2-西(东向西)、3-南(北向南)、4-北(南向北)、" +
|
||||
"5-东南(西北到东南)、6-东北(西南到东北)、7-西南(东北到西南)、8-西北(东南到西北)")
|
||||
private Integer directionType;
|
||||
|
||||
@MessageElementForCatalog("Info.Resolution")
|
||||
@Schema(description = "摄像机支持的分辨率,可多值")
|
||||
private String resolution;
|
||||
|
||||
@MessageElementForCatalog({"BusinessGroupID","Info.BusinessGroupID"})
|
||||
@Schema(description = "虚拟组织所属的业务分组ID")
|
||||
private String businessGroupId;
|
||||
|
||||
@MessageElementForCatalog("Info.DownloadSpeed")
|
||||
@Schema(description = "下载倍速(可选),可多值")
|
||||
private String downloadSpeed;
|
||||
|
||||
@MessageElementForCatalog("Info.SVCSpaceSupportMode")
|
||||
@Schema(description = "空域编码能力,取值0-不支持;1-1级增强(1个增强层);2-2级增强(2个增强层);3-3级增强(3个增强层)")
|
||||
private Integer svcSpaceSupportMod;
|
||||
|
||||
@MessageElementForCatalog("Info.SVCTimeSupportMode")
|
||||
@Schema(description = "时域编码能力,取值0-不支持;1-1级增强;2-2级增强;3-3级增强(可选)")
|
||||
private Integer svcTimeSupportMode;
|
||||
|
||||
@Schema(description = "云台类型描述字符串")
|
||||
private String ptzTypeText;
|
||||
|
||||
@Schema(description = "子设备数")
|
||||
private int subCount;
|
||||
|
||||
@Schema(description = "是否含有音频")
|
||||
private boolean hasAudio;
|
||||
|
||||
@Schema(description = "GPS的更新时间")
|
||||
private String gpsTime;
|
||||
|
||||
@Schema(description = "码流标识,优先级高于设备中码流标识," +
|
||||
"用于选择码流时组成码流标识。默认为null,不设置。可选值: stream/streamnumber/streamprofile/streamMode")
|
||||
private String streamIdentification;
|
||||
|
||||
@Schema(description = "通道类型, 默认0, 0: 普通通道,1 行政区划 2 业务分组/虚拟组织")
|
||||
private int channelType;
|
||||
|
||||
private Integer dataType = ChannelDataType.GB28181;
|
||||
|
||||
public void setPtzType(int ptzType) {
|
||||
this.ptzType = ptzType;
|
||||
switch (ptzType) {
|
||||
case 0:
|
||||
this.ptzTypeText = "未知";
|
||||
break;
|
||||
case 1:
|
||||
this.ptzTypeText = "球机";
|
||||
break;
|
||||
case 2:
|
||||
this.ptzTypeText = "半球";
|
||||
break;
|
||||
case 3:
|
||||
this.ptzTypeText = "固定枪机";
|
||||
break;
|
||||
case 4:
|
||||
this.ptzTypeText = "遥控枪机";
|
||||
break;
|
||||
case 5:
|
||||
this.ptzTypeText = "遥控半球";
|
||||
break;
|
||||
case 6:
|
||||
this.ptzTypeText = "多目设备的全景/拼接通道";
|
||||
break;
|
||||
case 7:
|
||||
this.ptzTypeText = "多目设备的分割通道";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static DeviceChannel decode(Element element) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
DeviceChannel deviceChannel = XmlUtil.elementDecode(element, DeviceChannel.class);
|
||||
if(deviceChannel.getCivilCode() != null ) {
|
||||
if (ObjectUtils.isEmpty(deviceChannel.getCivilCode())
|
||||
|| deviceChannel.getCivilCode().length() > 8 ){
|
||||
deviceChannel.setCivilCode(null);
|
||||
}
|
||||
// 此处对于不在wvp缓存中的行政区划,默认直接存储.保证即使出现wvp的行政区划缓存过老,也可以通过用户自主创建的方式正常使用系统
|
||||
}
|
||||
GbCode gbCode = GbCode.decode(deviceChannel.getDeviceId());
|
||||
if (gbCode != null && "138".equals(gbCode.getTypeCode())) {
|
||||
deviceChannel.setHasAudio(true);
|
||||
if (deviceChannel.getEnableBroadcast() == null && "138".equals(gbCode.getTypeCode())) {
|
||||
deviceChannel.setEnableBroadcast(1);
|
||||
}
|
||||
}
|
||||
|
||||
return deviceChannel;
|
||||
}
|
||||
|
||||
public static DeviceChannel decodeWithOnlyDeviceId(Element element) {
|
||||
Element deviceElement = element.element("DeviceID");
|
||||
DeviceChannel deviceChannel = new DeviceChannel();
|
||||
deviceChannel.setDeviceId(deviceElement.getText());
|
||||
deviceChannel.setDataType(ChannelDataType.GB28181);
|
||||
return deviceChannel;
|
||||
}
|
||||
|
||||
public CommonGBChannel buildCommonGBChannelForStatus() {
|
||||
CommonGBChannel commonGBChannel = new CommonGBChannel();
|
||||
commonGBChannel.setGbId(id);
|
||||
commonGBChannel.setGbDeviceId(deviceId);
|
||||
commonGBChannel.setGbName(name);
|
||||
commonGBChannel.setDataType(ChannelDataType.GB28181);
|
||||
commonGBChannel.setDataDeviceId(getDataDeviceId());
|
||||
return commonGBChannel;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
public class DeviceChannelInPlatform extends DeviceChannel{
|
||||
|
||||
private String platFormId;
|
||||
private String catalogId;
|
||||
|
||||
public String getPlatFormId() {
|
||||
return platFormId;
|
||||
}
|
||||
|
||||
public void setPlatFormId(String platFormId) {
|
||||
this.platFormId = platFormId;
|
||||
}
|
||||
|
||||
public String getCatalogId() {
|
||||
return catalogId;
|
||||
}
|
||||
|
||||
public void setCatalogId(String catalogId) {
|
||||
this.catalogId = catalogId;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.sip.Dialog;
|
||||
import java.util.EventObject;
|
||||
|
||||
@Data
|
||||
public class DeviceNotFoundEvent {
|
||||
|
||||
private String callId;
|
||||
|
||||
public DeviceNotFoundEvent(String callId) {
|
||||
this.callId = callId;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DeviceType implements Comparable<DeviceType>{
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 归属名称
|
||||
*/
|
||||
private String ownerName;
|
||||
public static DeviceType getInstance(DeviceTypeEnum typeEnum) {
|
||||
DeviceType deviceType = new DeviceType();
|
||||
deviceType.setName(typeEnum.getName());
|
||||
deviceType.setCode(typeEnum.getCode());
|
||||
deviceType.setOwnerName(typeEnum.getOwnerName());
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getOwnerName() {
|
||||
return ownerName;
|
||||
}
|
||||
|
||||
public void setOwnerName(String ownerName) {
|
||||
this.ownerName = ownerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull DeviceType deviceType) {
|
||||
return Integer.compare(Integer.parseInt(this.code), Integer.parseInt(deviceType.getCode()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
/**
|
||||
* 收录行业编码
|
||||
*/
|
||||
public enum DeviceTypeEnum {
|
||||
DVR("111", "DVR编码", "前端主设备"),
|
||||
VIDEO_SERVER("112", "视频服务器编码", "前端主设备"),
|
||||
ENCODER("113", "编码器编码", "前端主设备"),
|
||||
DECODER("114", "解码器编码", "前端主设备"),
|
||||
VIDEO_SWITCHING_MATRIX("115", "视频切换矩阵编码", "前端主设备"),
|
||||
AUDIO_SWITCHING_MATRIX("116", "音频切换矩阵编码", "前端主设备"),
|
||||
ALARM_CONTROLLER("117", "报警控制器编码", "前端主设备"),
|
||||
NVR("118", "网络视频录像机(NVR)编码", "前端主设备"),
|
||||
RESERVE("119", "预留", "前端主设备"),
|
||||
ONLINE_VIDEO_IMAGE_INFORMATION_ACQUISITION_SYSTEM("120", "在线视频图像信息采集系统编码", "前端主设备"),
|
||||
VIDEO_CHECKPOINT("121", "视频卡口编码", "前端主设备"),
|
||||
MULTI_CAMERA_DEVICE("122", "多目设备编码", "前端主设备"),
|
||||
PARKING_LOT_ENTRANCE_AND_EXIT_CONTROL_EQUIPMENT("123", "停车场出入口控制设备编码", "前端主设备"),
|
||||
PERSONNEL_ACCESS_CONTROL_EQUIPMENT("124", "人员出入口控制设备编码", "前端主设备"),
|
||||
SECURITY_INSPECTION_EQUIPMENT("125", "安检设备编码", "前端主设备"),
|
||||
HVR("130", "混合硬盘录像机(HVR)编码", "前端主设备"),
|
||||
CAMERA("131", "摄像机编码", "前端外围设备"),
|
||||
IPC("132", "网络摄像机(IPC)/在线视频图像信息采集设备编码", "前端外围设备"),
|
||||
MONITOR("133", "显示器编码", "前端外围设备"),
|
||||
ALARM_INPUT_DEVICE("134", "报警输入设备编码(如红外、烟感、门禁等报警设备)", "前端外围设备"),
|
||||
ALARM_OUTPUT_DEVICE("135", "报警输出设备编码(如警灯、警铃等设备)", "前端外围设备"),
|
||||
VOICE_INPUT_DEVICE("136", "语音输入设备编码", "前端外围设备"),
|
||||
VOICE_OUTPUT_DEVICE("137", "语音输出设备", "前端外围设备"),
|
||||
MOBILE_TRANSMISSION_EQUIPMENT("138", "移动传输设备编码", "前端外围设备"),
|
||||
OTHER_PERIPHERAL_DEVICES("139", "其他外围设备编码", "前端外围设备"),
|
||||
ALARM_OUTPUT_DEVICE2("140", "报警输出设备编码(如继电器或触发器控制的设备)", "前端外围设备"),
|
||||
BARRIER_GATE("141", "道闸(控制车辆通行)", "前端外围设备"),
|
||||
SMART_DOOR("142", "智能门(控制人员通行)", "前端外围设备"),
|
||||
VOUCHER_RECOGNITION_UNIT("143", "凭证识别单元", "前端外围设备"),
|
||||
CENTRAL_SIGNALING_CONTROL_SERVER("200", "中心信令控制服务器编码", "平台设备"),
|
||||
WEB_APPLICATION_SERVER("201", "Web应用服务器编码", "平台设备"),
|
||||
PROXY_SERVER("203", "代理服务器编码", "平台设备"),
|
||||
SECURITY_SERVER("204", "安全服务器编码", "平台设备"),
|
||||
ALARM_SERVER("205", "报警服务器编码", "平台设备"),
|
||||
DATABASE_SERVER("206", "数据库服务器编码", "平台设备"),
|
||||
GIS_SERVER("207", "GIS服务器编码", "平台设备"),
|
||||
MANAGER_SERVER("208", "管理服务器编码", "平台设备"),
|
||||
ACCESS_GATEWAY("209", "接入网关编码", "平台设备"),
|
||||
MEDIA_STORAGE_SERVER("210", "媒体存储服务器编码", "平台设备"),
|
||||
SIGNALING_SECURITY_ROUTING_GATEWAY("211", "信令安全路由网关编码", "平台设备"),
|
||||
BUSINESS_GROUP("215", "业务分组编码", "平台设备"),
|
||||
VIRTUAL_ORGANIZATION("216", "虚拟组织编码", "平台设备"),
|
||||
CENTRAL_USER("300", "中心用户", "中心用户"),
|
||||
END_USER("400", "终端用户", "终端用户"),
|
||||
VIDEO_IMAGE_INFORMATION_SYNTHESIS("500", "视频图像信息综合应用平台", "平台外接服务器"),
|
||||
VIDEO_IMAGE_INFORMATION_OPERATION_AND_MAINTENANCE_MANAGEMENT("501", "视频图像信息运维管理平台", "平台外接服务器"),
|
||||
VIDEO_IMAGE_ANALYSIS("502", "视频图像分析系统", "平台外接服务器"),
|
||||
VIDEO_IMAGE_INFORMATION_DATABASE("503", "视频图像信息数据库", "平台外接服务器"),
|
||||
VIDEO_IMAGE_ANALYSIS_EQUIPMENT("505", "视频图像分析设备", "平台外接服务器"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 归属名称
|
||||
*/
|
||||
private String ownerName;
|
||||
|
||||
DeviceTypeEnum(String code, String name, String ownerName) {
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
this.ownerName = ownerName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getOwnerName() {
|
||||
return ownerName;
|
||||
}
|
||||
|
||||
public void setOwnerName(String ownerName) {
|
||||
this.ownerName = ownerName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "拉框放大/缩小控制参数")
|
||||
public class DragZoomParam {
|
||||
|
||||
@MessageElement("Length")
|
||||
@Schema(description = "播放窗口长度像素值(必选)")
|
||||
protected Integer length;
|
||||
|
||||
@MessageElement("Width")
|
||||
@Schema(description = "播放窗口宽度像素值(必选)")
|
||||
protected Integer width;
|
||||
|
||||
@MessageElement("MidPointX")
|
||||
@Schema(description = "拉框中心的横轴坐标像素值(必选)")
|
||||
protected Integer midPointX;
|
||||
|
||||
@MessageElement("MidPointY")
|
||||
@Schema(description = "拉框中心的纵轴坐标像素值(必选)")
|
||||
protected Integer midPointY;
|
||||
|
||||
@MessageElement("LengthX")
|
||||
@Schema(description = "拉框长度像素值(必选)")
|
||||
protected Integer lengthX;
|
||||
|
||||
@MessageElement("LengthY")
|
||||
@Schema(description = "拉框宽度像素值(必选)")
|
||||
protected Integer lengthY;
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备信息查询响应
|
||||
*
|
||||
* @author Y.G
|
||||
* @version 1.0
|
||||
* @date 2022/6/28 14:55
|
||||
*/
|
||||
@Data
|
||||
public class DragZoomRequest {
|
||||
/**
|
||||
* 序列号
|
||||
*/
|
||||
@MessageElement("SN")
|
||||
private String sn;
|
||||
|
||||
@MessageElement("DeviceID")
|
||||
private String deviceId;
|
||||
|
||||
@MessageElement(value = "DragZoomIn")
|
||||
private DragZoomParam dragZoomIn;
|
||||
|
||||
@MessageElement(value = "DragZoomOut")
|
||||
private DragZoomParam dragZoomOut;
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class DrawThinProcess {
|
||||
|
||||
private double process;
|
||||
private String msg;
|
||||
|
||||
public DrawThinProcess(double process, String msg) {
|
||||
this.process = process;
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* 解析收到的前端控制指令
|
||||
*/
|
||||
@Data
|
||||
public class FrontEndCode {
|
||||
|
||||
|
||||
public static String encode(IFrontEndControlCode frontEndControlCode){
|
||||
return frontEndControlCode.encode();
|
||||
}
|
||||
|
||||
public static IFrontEndControlCode decode(@NotNull String cmdStr) {
|
||||
if (cmdStr.length() != 16) {
|
||||
return null;
|
||||
}
|
||||
String cmdCodeStr = cmdStr.substring(6, 8);
|
||||
int cmdCode = Integer.parseInt(cmdCodeStr, 16);
|
||||
if (cmdCode < 39) {
|
||||
// PTZ指令
|
||||
FrontEndControlCodeForPTZ codeForPTZ = new FrontEndControlCodeForPTZ();
|
||||
int zoomOut = cmdCode >> 5 & 1;
|
||||
if (zoomOut == 1) {
|
||||
codeForPTZ.setZoom(0);
|
||||
}
|
||||
int zoomIn = cmdCode >> 4 & 1;
|
||||
if (zoomIn == 1) {
|
||||
codeForPTZ.setZoom(1);
|
||||
}
|
||||
int tiltUp = cmdCode >> 3 & 1;
|
||||
if (tiltUp == 1) {
|
||||
codeForPTZ.setTilt(0);
|
||||
}
|
||||
int tiltDown = cmdCode >> 2 & 1;
|
||||
if (tiltDown == 1) {
|
||||
codeForPTZ.setTilt(1);
|
||||
}
|
||||
int panLeft = cmdCode >> 1 & 1;
|
||||
if (panLeft == 1) {
|
||||
codeForPTZ.setPan(0);
|
||||
}
|
||||
int panRight = cmdCode & 1;
|
||||
if (panRight == 1) {
|
||||
codeForPTZ.setPan(1);
|
||||
}
|
||||
String param1Str = cmdStr.substring(8, 10);
|
||||
codeForPTZ.setPanSpeed(Integer.parseInt(param1Str, 16));
|
||||
String param2Str = cmdStr.substring(10, 12);
|
||||
codeForPTZ.setTiltSpeed(Integer.parseInt(param2Str, 16));
|
||||
String param3Str = cmdStr.substring(12, 13);
|
||||
codeForPTZ.setZoomSpeed(Integer.parseInt(param3Str, 16));
|
||||
return codeForPTZ;
|
||||
}else if (cmdCode < 74) {
|
||||
// FI指令
|
||||
FrontEndControlCodeForFI codeForFI = new FrontEndControlCodeForFI();
|
||||
int irisOut = cmdCode >> 3 & 1;
|
||||
if (irisOut == 1) {
|
||||
codeForFI.setIris(0);
|
||||
}
|
||||
int irisIn = cmdCode >> 2 & 1;
|
||||
if (irisIn == 1) {
|
||||
codeForFI.setIris(1);
|
||||
}
|
||||
int focusNear = cmdCode >> 1 & 1;
|
||||
if (focusNear == 1) {
|
||||
codeForFI.setFocus(0);
|
||||
}
|
||||
int focusFar = cmdCode & 1;
|
||||
if (focusFar == 1) {
|
||||
codeForFI.setFocus(1);
|
||||
}
|
||||
|
||||
String param1Str = cmdStr.substring(8, 10);
|
||||
codeForFI.setFocusSpeed(Integer.parseInt(param1Str, 16));
|
||||
String param2Str = cmdStr.substring(10, 12);
|
||||
codeForFI.setIrisSpeed(Integer.parseInt(param2Str, 16));
|
||||
return codeForFI;
|
||||
}else if (cmdCode < 131) {
|
||||
// 预置位指令
|
||||
FrontEndControlCodeForPreset codeForPreset = new FrontEndControlCodeForPreset();
|
||||
switch (cmdCode) {
|
||||
case 0x81: // 设置预置位
|
||||
codeForPreset.setCode(1);
|
||||
break;
|
||||
case 0x82: // 调用预置位
|
||||
codeForPreset.setCode(2);
|
||||
break;
|
||||
case 0x83: // 删除预置位
|
||||
codeForPreset.setCode(3);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
// 预置位编号
|
||||
String param2Str = cmdStr.substring(10, 12);
|
||||
codeForPreset.setPresetId(Integer.parseInt(param2Str, 16));
|
||||
return codeForPreset;
|
||||
}else if (cmdCode < 136) {
|
||||
// 巡航指令
|
||||
FrontEndControlCodeForTour codeForTour = new FrontEndControlCodeForTour();
|
||||
String param3Str = cmdStr.substring(12, 13);
|
||||
switch (cmdCode) {
|
||||
case 0x84: // 加入巡航点
|
||||
codeForTour.setCode(1);
|
||||
break;
|
||||
case 0x85: // 删除一个巡航点
|
||||
codeForTour.setCode(2);
|
||||
break;
|
||||
case 0x86: // 设置巡航速度
|
||||
codeForTour.setCode(3);
|
||||
codeForTour.setTourSpeed(Integer.parseInt(param3Str, 16));
|
||||
break;
|
||||
case 0x87: // 设置巡航停留时间
|
||||
codeForTour.setCode(4);
|
||||
codeForTour.setTourTime(Integer.parseInt(param3Str, 16));
|
||||
break;
|
||||
case 0x88: // 开始巡航
|
||||
codeForTour.setCode(5);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
String param1Str = cmdStr.substring(8, 10);
|
||||
codeForTour.setTourId(Integer.parseInt(param1Str, 16));
|
||||
String param2Str = cmdStr.substring(10, 12);
|
||||
codeForTour.setPresetId(Integer.parseInt(param2Str, 16));
|
||||
return codeForTour;
|
||||
}else if (cmdCode < 138) {
|
||||
// 扫描指令
|
||||
FrontEndControlCodeForScan controlCodeForScan = new FrontEndControlCodeForScan();
|
||||
String param2Str = cmdStr.substring(10, 11);
|
||||
int param2Code = Integer.parseInt(param2Str, 16);
|
||||
switch (cmdCode) {
|
||||
case 0x89:
|
||||
switch (param2Code) {
|
||||
case 0x00: // 开始自动扫描
|
||||
controlCodeForScan.setCode(1);
|
||||
break;
|
||||
case 0x01: // 设置自动扫描左边界
|
||||
controlCodeForScan.setCode(2);
|
||||
break;
|
||||
case 0x02: // 设置自动扫描右边界
|
||||
controlCodeForScan.setCode(3);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x8A: // 删除一个巡航点
|
||||
controlCodeForScan.setCode(4);
|
||||
String param3Str = cmdStr.substring(12, 13);
|
||||
controlCodeForScan.setScanSpeed(Integer.parseInt(param3Str, 16));
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
String param1Str = cmdStr.substring(8, 10);
|
||||
controlCodeForScan.setScanId(Integer.parseInt(param1Str, 16));
|
||||
return controlCodeForScan;
|
||||
}else if (cmdCode < 141) {
|
||||
// 辅助开关
|
||||
FrontEndControlCodeForAuxiliary codeForAuxiliary = new FrontEndControlCodeForAuxiliary();
|
||||
switch (cmdCode) {
|
||||
case 0x8C: // 开
|
||||
codeForAuxiliary.setCode(1);
|
||||
break;
|
||||
case 0x8D: // 关
|
||||
codeForAuxiliary.setCode(2);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
// 预置位编号
|
||||
String param2Str = cmdStr.substring(10, 12);
|
||||
codeForAuxiliary.setAuxiliaryId(Integer.parseInt(param2Str, 16));
|
||||
return codeForAuxiliary;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForAuxiliary implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.AUXILIARY;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助开关控制指令: 1为开, 2为关
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 辅助开关编号
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer auxiliaryId;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForFI implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.FI;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 光圈,0为缩小 1为放大
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer iris;
|
||||
|
||||
/**
|
||||
* 聚焦 0 近, 1远
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer focus;
|
||||
|
||||
/**
|
||||
* 聚焦速度
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer focusSpeed;
|
||||
|
||||
/**
|
||||
* 光圈速度
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer irisSpeed;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForPTZ implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.PTZ;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 镜头变倍,0为缩小 1为放大
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer zoom;
|
||||
|
||||
/**
|
||||
* 云台垂直方向控制 0 为上, 1为下
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer tilt;
|
||||
|
||||
/**
|
||||
* 云台水平方向控制 0 为左, 1为右
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer pan;
|
||||
|
||||
/**
|
||||
* 水平控制速度相对值
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer panSpeed;
|
||||
|
||||
/**
|
||||
* 垂直控制速度相对值
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer tiltSpeed;
|
||||
|
||||
/**
|
||||
* 变倍控制速度相对值
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer zoomSpeed;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForPreset implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.PRESET;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预置位指令: 1为设置预置位, 2为调用预置位, 3为删除预置位
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 预置位编号
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer presetId;
|
||||
|
||||
/**
|
||||
* 预置位名称
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private String presetName;
|
||||
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForScan implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.SCAN;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预置位指令: 1为开始自动扫描, 2为设置自动扫描左边界, 3为设置自动扫描右边界, 4为设置自动扫描速度, 5为停止自动扫描
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 自动扫描速度
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer scanSpeed;
|
||||
|
||||
/**
|
||||
* 扫描组号
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer scanId;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForTour implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.TOUR;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 巡航指令: 1为加入巡航点, 2为删除一个巡航点, 3为设置巡航速度, 4为设置巡航停留时间, 5为开始巡航, 6为停止巡航
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 巡航点
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer tourId;
|
||||
|
||||
/**
|
||||
* 巡航停留时间
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer tourTime;
|
||||
|
||||
/**
|
||||
* 巡航速度
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer tourSpeed;
|
||||
|
||||
/**
|
||||
* 预置位编号
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer presetId;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForWiper implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.AUXILIARY;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助开关控制指令: 1为开, 2为关
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer code;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
public enum FrontEndControlType {
|
||||
|
||||
PTZ,FI,PRESET,TOUR,SCAN,AUXILIARY
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue