删除src文件

This commit is contained in:
孙小云 2025-12-06 09:51:35 +08:00
parent 474e3a671c
commit 14e0048e3b
755 changed files with 0 additions and 92795 deletions

View File

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

View File

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

View File

@ -1,5 +0,0 @@
package com.genersoft.iot.vmp.common;
public interface CommonCallback<T>{
public void run(T t);
}

View File

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

View File

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

View File

@ -1,11 +0,0 @@
package com.genersoft.iot.vmp.common;
/**
* 标识invite消息发出后的各个状态
* 收到ok钱停止invite发送cancel
* 收到200ok后发送BYE停止invite
*/
public enum InviteSessionStatus {
ready,
ok,
}

View File

@ -1,9 +0,0 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
PLAY,
PLAYBACK,
DOWNLOAD,
BROADCAST,
TALK
}

View File

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

View File

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

View File

@ -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 + '\'' +
'}';
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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:";
}

View File

@ -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 -> "未知";
};
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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-ACTIVEtcp主动模式 TCP-PASSIVEtcp被动模式
*/
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +0,0 @@
package com.genersoft.iot.vmp.conf.ftpServer;
import java.io.OutputStream;
public interface FileCallback {
OutputStream run(String path);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 +
'}';
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,15 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 语音广播状态
* @author lin
*/
public enum AudioBroadcastCatchStatus {
// 发送语音广播消息等待对方回复语音广播
Ready,
// 收到回复等待invite消息
WaiteInvite,
// 收到invite消息
Ok,
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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-ACTIVEtcp主动模式
* TCP-PASSIVEtcp被动模式
*/
@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");
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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