移除wvp项目

This commit is contained in:
iteaj
2025-05-30 09:56:01 +08:00
parent 25e61aa98e
commit 827075d4b6
337 changed files with 1 additions and 52771 deletions
+1 -2
View File
@@ -11,8 +11,7 @@
<packaging>pom</packaging>
<modules>
<!--gb28181基于开源项目[wvp-GB28181-pro]修改而来-->
<module>wvp-GB28181-pro</module>
</modules>
<name>iboot:tos</name>
-2
View File
@@ -1,2 +0,0 @@
* 同步时间[2023/12/13]
* gb28181项目是基于[wvp-GB28181-pro]修改而来. 感谢开源作者[https://gitee.com/pan648540858/wvp-GB28181-pro]
-146
View File
@@ -1,146 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.iteaj</groupId>
<version>${reversion}</version>
<artifactId>iboot-tos</artifactId>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wvp-GB28181-pro</artifactId>
<description>
gb28181项目是基于[wvp-GB28181-pro]修改而来. 感谢开源作者[https://gitee.com/pan648540858/wvp-GB28181-pro]
</description>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<optional>true</optional>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--在线文档 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.10</version>
</dependency>
<!--参数校验 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<!-- 日志相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- sip协议栈 -->
<dependency>
<groupId>javax.sip</groupId>
<artifactId>jain-sip-ri</artifactId>
<version>1.3.0-91</version>
</dependency>
<!-- xml解析库 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<!-- json解析库fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId>
<version>2.0.17</version>
</dependency>
<!-- okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>
<!-- okhttp 调试日志 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>4.10.0</version>
</dependency>
<!-- okhttp-digest -->
<dependency>
<groupId>io.github.rburgst</groupId>
<artifactId>okhttp-digest</artifactId>
<version>2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
<!-- <dependency>-->
<!-- <groupId>net.sf.kxml</groupId>-->
<!-- <artifactId>kxml2</artifactId>-->
<!-- <version>2.3.0</version>-->
<!-- </dependency>-->
<!-- jwt实现 -->
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
<version>0.9.3</version>
</dependency>
<!--反向代理-->
<dependency>
<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.12.1</version>
</dependency>
<!-- &lt;!&ndash; 检测文件编码 &ndash;&gt;-->
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/cpdetector/cpdetector &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>cpdetector</groupId>-->
<!-- <artifactId>cpdetector</artifactId>-->
<!-- <version>1.0.8</version>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>
</project>
@@ -1,26 +0,0 @@
package com.genersoft.iot.vmp;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.iteaj.framework.security.OrderFilterChainDefinition;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.Order;
@ComponentScan({"com.genersoft.iot.vmp"})
@ServletComponentScan("com.genersoft.iot.vmp.conf")
@MapperScan("com.genersoft.iot.vmp.storager.dao")
@EnableConfigurationProperties(MediaConfig.class)
public class GbsWvpAutoConfiguration {
/**
* @return
*/
@Bean
@Order(value = 18)
public OrderFilterChainDefinition gbsFilterChainDefinition() {
return new OrderFilterChainDefinition().addAnon("/gbs/zlm/hook/**");
}
}
@@ -1,198 +0,0 @@
package com.genersoft.iot.vmp.common;
/**
* 为API重命名, 方便向数据库记录数据的时候展示
* @author lin
*/
public class ApiSaveConstant {
public static String getVal(String key) {
String[] keyItemArray = key.split("/");
if (keyItemArray.length <= 1 || !"api".equals(keyItemArray[1])) {
return null;
}
if (keyItemArray.length >= 4) {
switch (keyItemArray[2]) {
case "alarm":
if ("delete".equals(keyItemArray[3])) {
return "删除报警";
}
break;
case "device":
switch (keyItemArray[3]) {
case "config":
if (keyItemArray.length >= 5 && "basicParam".equals(keyItemArray[4])) {
return "[设备配置] 基本配置设置命令";
}
break;
case "control":
switch (keyItemArray[4]) {
case "teleboot":
return "[设备控制] 远程启动";
case "record":
return "[设备控制] 录像控制";
case "guard":
return "[设备控制] 布防/撤防命令";
case "reset_alarm":
return "[设备控制] 报警复位";
case "i_frame":
return "[设备控制] 强制关键帧";
case "home_position":
return "[设备控制] 看守位控制";
default:
return "";
}
case "query":
if (keyItemArray.length <= 5) {
return null;
}
switch (keyItemArray[4]) {
case "devices":
if (keyItemArray.length < 7) {
return null;
}
switch (keyItemArray[6]) {
case "sync":
return "[设备查询] 同步设备通道";
case "delete":
return "[设备查询] 移除设备";
default:
return "";
}
case "channel":
return "[设备查询] 更新通道信息";
case "transport":
return "[设备查询] 修改数据流传输模式";
default:
return "";
}
default:
return "";
}
break;
case "gbStream":
switch (keyItemArray[3]) {
case "del":
return "移除通道与国标的关联";
case "add":
return "添加通道与国标的关联";
default:
return "";
}
case "media":
break;
case "position":
if ("subscribe".equals(keyItemArray[3])) {
return "订阅位置信息";
}
break;
case "platform":
switch (keyItemArray[3]) {
case "save":
return "添加上级平台";
case "delete":
return "移除上级平台";
case "update_channel_for_gb":
return "向上级平台添加国标通道";
case "del_channel_for_gb":
return "从上级平台移除国标通道";
default:
return "";
}
case "platform_gb_stream":
break;
case "play":
switch (keyItemArray[3]) {
case "start":
return "开始点播";
case "stop":
return "停止点播";
case "convert":
return "转码";
case "convertStop":
return "结束转码";
case "broadcast":
return "语音广播";
default:
return "";
}
case "download":
switch (keyItemArray[3]) {
case "start":
return "开始历史媒体下载";
case "stop":
return "停止历史媒体下载";
default:
return "";
}
case "playback":
switch (keyItemArray[3]) {
case "start":
return "开始视频回放";
case "stop":
return "停止视频回放";
default:
return "";
}
case "ptz":
switch (keyItemArray[3]) {
case "control":
return "云台控制";
case "front_end_command":
return "通用前端控制命令";
default:
return "";
}
case "gb_record":
break;
case "onvif":
break;
case "server":
if ("restart".equals(keyItemArray[3])) {
return "重启流媒体服务";
}
break;
case "proxy":
switch (keyItemArray[3]) {
case "save":
return "保存代理";
case "del":
return "移除代理";
case "start":
return "启用代理";
case "stop":
return "停用代理";
default:
return "";
}
case "push":
switch (keyItemArray[3]) {
case "save_to_gb":
return "将推流添加到国标";
case "remove_form_gb":
return "将推流移出到国标";
default:
return "";
}
case "user":
switch (keyItemArray[3]) {
case "login":
return "登录";
case "changePassword":
return "修改密码";
case "add":
return "添加用户";
case "delete":
return "删除用户";
default:
return "";
}
default:
return "";
}
}
return null;
}
}
@@ -1,42 +0,0 @@
package com.genersoft.iot.vmp.common;
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]);
civilCodePo.setParentCode(infoArray[2]);
return civilCodePo;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getParentCode() {
return parentCode;
}
public void setParentCode(String parentCode) {
this.parentCode = parentCode;
}
}
@@ -1,5 +0,0 @@
package com.genersoft.iot.vmp.common;
public interface CommonCallback<T>{
public void run(T t);
}
@@ -1,191 +0,0 @@
package com.genersoft.iot.vmp.common;
import io.swagger.v3.oas.annotations.media.Schema;
public class CommonGbChannel {
/**
* 国标字段:归属
*/
@Schema(description = "归属")
private String owner;
/**
* 国标字段:行政区划
*/
@Schema(description = "行政区划")
private String civilCode;
/**
* 国标字段:安装地址
*/
@Schema(description = "安装地址")
private String address;
/**
* 国标字段:经度
*/
@Schema(description = "经度")
private Double longitude;
/**
* 国标字段:纬度
*/
@Schema(description = "纬度")
private Double latitude;
/**
* 国标字段:摄像机类型:
* 1-球机;
* 2-半球;
* 3-固定枪机;
* 4-遥控枪机
*/
@Schema(description = "摄像机类型")
private Integer ptzType;
/**
* 国标字段:摄像机位置类型扩展。
* 1-省际检查站、
* 2-党政机关、
* 3-车站码头、
* 4-中心广场、
* 5-体育场馆、
* 6-商业中心、
* 7-宗教场所、
* 8-校园周边、
* 9-治安复杂区域、
* 10-交通干线
*/
@Schema(description = "摄像机位置类型扩展")
private Integer positionType;
/**
* 国标字段:安装位置室外、室内属性
* 1-室外、
* 2-室内
*/
@Schema(description = "安装位置室外、室内属性")
private Integer roomType;
/**
* 国标字段:用途
* 1-治安、
* 2-交通、
* 3-重点、
*/
@Schema(description = "用途")
private Integer useType;
/**
* 国标字段:补光属性
* 1-无补光、
* 2-红外补光、
* 3-白光补光
*/
@Schema(description = "补光属性")
private Integer supplyLightType;
/**
* 摄像机监视方位属性。
* 1-东、
* 2-西、
* 3-南、
* 4-北、
* 5-东南、
* 6-东北、
* 7-西南、
* 8-西北
*
*/
@Schema(description = "方位")
private Integer directionType;
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getCivilCode() {
return civilCode;
}
public void setCivilCode(String civilCode) {
this.civilCode = civilCode;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Integer getPtzType() {
return ptzType;
}
public void setPtzType(Integer ptzType) {
this.ptzType = ptzType;
}
public Integer getPositionType() {
return positionType;
}
public void setPositionType(Integer positionType) {
this.positionType = positionType;
}
public Integer getRoomType() {
return roomType;
}
public void setRoomType(Integer roomType) {
this.roomType = roomType;
}
public Integer getUseType() {
return useType;
}
public void setUseType(Integer useType) {
this.useType = useType;
}
public Integer getSupplyLightType() {
return supplyLightType;
}
public void setSupplyLightType(Integer supplyLightType) {
this.supplyLightType = supplyLightType;
}
public Integer getDirectionType() {
return directionType;
}
public void setDirectionType(Integer directionType) {
this.directionType = directionType;
}
}
@@ -1,5 +0,0 @@
package com.genersoft.iot.vmp.common;
public interface GeneralCallback<T>{
void run(int code, String msg, T data);
}
@@ -1,144 +0,0 @@
package com.genersoft.iot.vmp.common;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 记录每次发送invite消息的状态
*/
public class InviteInfo {
private String deviceId;
private String channelId;
private String stream;
private SSRCInfo ssrcInfo;
private String receiveIp;
private Integer receivePort;
private String streamMode;
private InviteSessionType type;
private InviteSessionStatus status;
private StreamInfo streamInfo;
public static InviteInfo getInviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo,
String receiveIp, Integer receivePort, String streamMode,
InviteSessionType type, InviteSessionStatus status) {
InviteInfo inviteInfo = new InviteInfo();
inviteInfo.setDeviceId(deviceId);
inviteInfo.setChannelId(channelId);
inviteInfo.setStream(stream);
inviteInfo.setSsrcInfo(ssrcInfo);
inviteInfo.setReceiveIp(receiveIp);
inviteInfo.setReceivePort(receivePort);
inviteInfo.setStreamMode(streamMode);
inviteInfo.setType(type);
inviteInfo.setStatus(status);
return inviteInfo;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public InviteSessionType getType() {
return type;
}
public void setType(InviteSessionType type) {
this.type = type;
}
public InviteSessionStatus getStatus() {
return status;
}
public void setStatus(InviteSessionStatus status) {
this.status = status;
}
public StreamInfo getStreamInfo() {
return streamInfo;
}
public void setStreamInfo(StreamInfo streamInfo) {
this.streamInfo = streamInfo;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public SSRCInfo getSsrcInfo() {
return ssrcInfo;
}
public void setSsrcInfo(SSRCInfo ssrcInfo) {
this.ssrcInfo = ssrcInfo;
}
public String getReceiveIp() {
return receiveIp;
}
public void setReceiveIp(String receiveIp) {
this.receiveIp = receiveIp;
}
public Integer getReceivePort() {
return receivePort;
}
public void setReceivePort(Integer receivePort) {
this.receivePort = receivePort;
}
public String getStreamMode() {
return streamMode;
}
public void setStreamMode(String streamMode) {
this.streamMode = streamMode;
}
/*=========================设备主子码流逻辑START====================*/
@Schema(description = "是否为子码流(true-是,false-主码流)")
private boolean subStream;
public boolean isSubStream() {
return subStream;
}
public void setSubStream(boolean subStream) {
this.subStream = subStream;
}
}
@@ -1,11 +0,0 @@
package com.genersoft.iot.vmp.common;
/**
* 标识invite消息发出后的各个状态,
* 收到ok钱停止invite发送cancel
* 收到200ok后发送BYE停止invite
*/
public enum InviteSessionStatus {
ready,
ok,
}
@@ -1,7 +0,0 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
PLAY,
PLAYBACK,
DOWNLOAD
}
@@ -1,609 +0,0 @@
package com.genersoft.iot.vmp.common;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.util.Objects;
@Schema(description = "流信息")
public class StreamInfo implements Serializable, Cloneable{
@Schema(description = "应用名")
private String app;
@Schema(description = "流ID")
private String stream;
@Schema(description = "设备编号")
private String deviceID;
@Schema(description = "通道编号")
private String channelId;
@Schema(description = "IP")
private String ip;
@Schema(description = "HTTP-FLV流地址")
private StreamURL flv;
@Schema(description = "HTTPS-FLV流地址")
private StreamURL https_flv;
@Schema(description = "Websocket-FLV流地址")
private StreamURL ws_flv;
@Schema(description = "Websockets-FLV流地址")
private StreamURL wss_flv;
@Schema(description = "HTTP-FMP4流地址")
private StreamURL fmp4;
@Schema(description = "HTTPS-FMP4流地址")
private StreamURL https_fmp4;
@Schema(description = "Websocket-FMP4流地址")
private StreamURL ws_fmp4;
@Schema(description = "Websockets-FMP4流地址")
private StreamURL wss_fmp4;
@Schema(description = "HLS流地址")
private StreamURL hls;
@Schema(description = "HTTPS-HLS流地址")
private StreamURL https_hls;
@Schema(description = "Websocket-HLS流地址")
private StreamURL ws_hls;
@Schema(description = "Websockets-HLS流地址")
private StreamURL wss_hls;
@Schema(description = "HTTP-TS流地址")
private StreamURL ts;
@Schema(description = "HTTPS-TS流地址")
private StreamURL https_ts;
@Schema(description = "Websocket-TS流地址")
private StreamURL ws_ts;
@Schema(description = "Websockets-TS流地址")
private StreamURL wss_ts;
@Schema(description = "RTMP流地址")
private StreamURL rtmp;
@Schema(description = "RTMPS流地址")
private StreamURL rtmps;
@Schema(description = "RTSP流地址")
private StreamURL rtsp;
@Schema(description = "RTSPS流地址")
private StreamURL rtsps;
@Schema(description = "RTC流地址")
private StreamURL rtc;
@Schema(description = "RTCS流地址")
private StreamURL rtcs;
@Schema(description = "流媒体ID")
private String mediaServerId;
@Schema(description = "流编码信息")
private Object tracks;
@Schema(description = "开始时间")
private String startTime;
@Schema(description = "结束时间")
private String endTime;
@Schema(description = "进度(录像下载使用)")
private double progress;
@Schema(description = "是否暂停(录像回放使用)")
private boolean pause;
public void setFlv(StreamURL flv) {
this.flv = flv;
}
public void setHttps_flv(StreamURL https_flv) {
this.https_flv = https_flv;
}
public void setWs_flv(StreamURL ws_flv) {
this.ws_flv = ws_flv;
}
public void setWss_flv(StreamURL wss_flv) {
this.wss_flv = wss_flv;
}
public void setFmp4(StreamURL fmp4) {
this.fmp4 = fmp4;
}
public void setHttps_fmp4(StreamURL https_fmp4) {
this.https_fmp4 = https_fmp4;
}
public void setWs_fmp4(StreamURL ws_fmp4) {
this.ws_fmp4 = ws_fmp4;
}
public void setWss_fmp4(StreamURL wss_fmp4) {
this.wss_fmp4 = wss_fmp4;
}
public void setHls(StreamURL hls) {
this.hls = hls;
}
public void setHttps_hls(StreamURL https_hls) {
this.https_hls = https_hls;
}
public void setWs_hls(StreamURL ws_hls) {
this.ws_hls = ws_hls;
}
public void setWss_hls(StreamURL wss_hls) {
this.wss_hls = wss_hls;
}
public void setTs(StreamURL ts) {
this.ts = ts;
}
public void setHttps_ts(StreamURL https_ts) {
this.https_ts = https_ts;
}
public void setWs_ts(StreamURL ws_ts) {
this.ws_ts = ws_ts;
}
public void setWss_ts(StreamURL wss_ts) {
this.wss_ts = wss_ts;
}
public void setRtmp(StreamURL rtmp) {
this.rtmp = rtmp;
}
public void setRtmps(StreamURL rtmps) {
this.rtmps = rtmps;
}
public void setRtsp(StreamURL rtsp) {
this.rtsp = rtsp;
}
public void setRtsps(StreamURL rtsps) {
this.rtsps = rtsps;
}
public void setRtc(StreamURL rtc) {
this.rtc = rtc;
}
public void setRtcs(StreamURL rtcs) {
this.rtcs = rtcs;
}
public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s%s", app, stream, callIdParam);
if (port > 0) {
this.rtmp = new StreamURL("rtmp", host, port, file);
}
if (sslPort > 0) {
this.rtmps = new StreamURL("rtmps", host, sslPort, file);
}
}
public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s%s", app, stream, callIdParam);
if (port > 0) {
this.rtsp = new StreamURL("rtsp", host, port, file);
}
if (sslPort > 0) {
this.rtsps = new StreamURL("rtsps", host, sslPort, file);
}
}
public void setFlv(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s.live.flv%s", app, stream, callIdParam);
if (port > 0) {
this.flv = new StreamURL("http", host, port, file);
}
this.ws_flv = new StreamURL("ws", host, port, file);
if (sslPort > 0) {
this.https_flv = new StreamURL("https", host, sslPort, file);
this.wss_flv = new StreamURL("wss", host, sslPort, file);
}
}
public void setFmp4(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s.live.mp4%s", app, stream, callIdParam);
if (port > 0) {
this.fmp4 = new StreamURL("http", host, port, file);
this.ws_fmp4 = new StreamURL("ws", host, port, file);
}
if (sslPort > 0) {
this.https_fmp4 = new StreamURL("https", host, sslPort, file);
this.wss_fmp4 = new StreamURL("wss", host, sslPort, file);
}
}
public void setHls(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
if (port > 0) {
this.hls = new StreamURL("http", host, port, file);
this.ws_hls = new StreamURL("ws", host, port, file);
}
if (sslPort > 0) {
this.https_hls = new StreamURL("https", host, sslPort, file);
this.wss_hls = new StreamURL("wss", host, sslPort, file);
}
}
public void setTs(String host, int port, int sslPort, String app, String stream, String callIdParam) {
String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
if (port > 0) {
this.ts = new StreamURL("http", host, port, file);
this.ws_ts = new StreamURL("ws", host, port, file);
}
if (sslPort > 0) {
this.https_ts = new StreamURL("https", host, sslPort, file);
this.wss_ts = new StreamURL("wss", host, sslPort, file);
}
}
public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam) {
if (callIdParam != null) {
callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
}
String file = String.format("index/api/webrtc?app=%s&stream=%s&type=play%s", app, stream, callIdParam);
if (port > 0) {
this.rtc = new StreamURL("http", host, port, file);
}
if (sslPort > 0) {
this.rtcs = new StreamURL("https", host, sslPort, file);
}
}
public void channgeStreamIp(String localAddr) {
if (this.flv != null) {
this.flv.setHost(localAddr);
}
if (this.ws_flv != null ){
this.ws_flv.setHost(localAddr);
}
if (this.hls != null ) {
this.hls.setHost(localAddr);
}
if (this.ws_hls != null ) {
this.ws_hls.setHost(localAddr);
}
if (this.ts != null ) {
this.ts.setHost(localAddr);
}
if (this.ws_ts != null ) {
this.ws_ts.setHost(localAddr);
}
if (this.fmp4 != null ) {
this.fmp4.setHost(localAddr);
}
if (this.ws_fmp4 != null ) {
this.ws_fmp4.setHost(localAddr);
}
if (this.rtc != null ) {
this.rtc.setHost(localAddr);
}
if (this.https_flv != null) {
this.https_flv.setHost(localAddr);
}
if (this.wss_flv != null) {
this.wss_flv.setHost(localAddr);
}
if (this.https_hls != null) {
this.https_hls.setHost(localAddr);
}
if (this.wss_hls != null) {
this.wss_hls.setHost(localAddr);
}
if (this.wss_ts != null) {
this.wss_ts.setHost(localAddr);
}
if (this.https_fmp4 != null) {
this.https_fmp4.setHost(localAddr);
}
if (this.wss_fmp4 != null) {
this.wss_fmp4.setHost(localAddr);
}
if (this.rtcs != null) {
this.rtcs.setHost(localAddr);
}
if (this.rtsp != null) {
this.rtsp.setHost(localAddr);
}
if (this.rtsps != null) {
this.rtsps.setHost(localAddr);
}
if (this.rtmp != null) {
this.rtmp.setHost(localAddr);
}
if (this.rtmps != null) {
this.rtmps.setHost(localAddr);
}
}
public static class TransactionInfo{
public String callId;
public String localTag;
public String remoteTag;
public String branch;
}
private TransactionInfo transactionInfo;
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getDeviceID() {
return deviceID;
}
public void setDeviceID(String deviceID) {
this.deviceID = deviceID;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public StreamURL getFlv() {
return flv;
}
public StreamURL getHttps_flv() {
return https_flv;
}
public StreamURL getWs_flv() {
return ws_flv;
}
public StreamURL getWss_flv() {
return wss_flv;
}
public StreamURL getFmp4() {
return fmp4;
}
public StreamURL getHttps_fmp4() {
return https_fmp4;
}
public StreamURL getWs_fmp4() {
return ws_fmp4;
}
public StreamURL getWss_fmp4() {
return wss_fmp4;
}
public StreamURL getHls() {
return hls;
}
public StreamURL getHttps_hls() {
return https_hls;
}
public StreamURL getWs_hls() {
return ws_hls;
}
public StreamURL getWss_hls() {
return wss_hls;
}
public StreamURL getTs() {
return ts;
}
public StreamURL getHttps_ts() {
return https_ts;
}
public StreamURL getWs_ts() {
return ws_ts;
}
public StreamURL getWss_ts() {
return wss_ts;
}
public StreamURL getRtmp() {
return rtmp;
}
public StreamURL getRtmps() {
return rtmps;
}
public StreamURL getRtsp() {
return rtsp;
}
public StreamURL getRtsps() {
return rtsps;
}
public StreamURL getRtc() {
return rtc;
}
public StreamURL getRtcs() {
return rtcs;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public Object getTracks() {
return tracks;
}
public void setTracks(Object tracks) {
this.tracks = tracks;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public double getProgress() {
return progress;
}
public void setProgress(double progress) {
this.progress = progress;
}
public boolean isPause() {
return pause;
}
public void setPause(boolean pause) {
this.pause = pause;
}
public TransactionInfo getTransactionInfo() {
return transactionInfo;
}
public void setTransactionInfo(TransactionInfo transactionInfo) {
this.transactionInfo = transactionInfo;
}
@Override
public StreamInfo clone() {
StreamInfo instance = null;
try{
instance = (StreamInfo)super.clone();
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;
}
/*=========================设备主子码流逻辑START====================*/
@Schema(description = "是否为子码流(true-是,false-主码流)")
private boolean subStream;
public boolean isSubStream() {
return subStream;
}
public void setSubStream(boolean subStream) {
this.subStream = subStream;
}
}
@@ -1,84 +0,0 @@
package com.genersoft.iot.vmp.common;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
@Schema(description = "流地址信息")
public class StreamURL implements Serializable,Cloneable {
@Schema(description = "协议")
private String protocol;
@Schema(description = "主机地址")
private String host;
@Schema(description = "端口")
private int port = -1;
@Schema(description = "定位位置")
private String file;
@Schema(description = "拼接后的地址")
private String url;
public StreamURL() {
}
public StreamURL(String protocol, String host, int port, String file) {
this.protocol = protocol;
this.host = host;
this.port = port;
this.file = file;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
public String getUrl() {
return this.toString();
}
@Override
public String toString() {
if (protocol != null && host != null && port != -1 ) {
return String.format("%s://%s:%s/%s", protocol, host, port, file);
}else {
return null;
}
}
@Override
public StreamURL clone() throws CloneNotSupportedException {
return (StreamURL) super.clone();
}
}
@@ -1,54 +0,0 @@
package com.genersoft.iot.vmp.common;
import java.util.List;
public class SystemAllInfo {
private List<Object> cpu;
private List<Object> mem;
private List<Object> net;
private long netTotal;
private Object disk;
public List<Object> getCpu() {
return cpu;
}
public void setCpu(List<Object> cpu) {
this.cpu = cpu;
}
public List<Object> getMem() {
return mem;
}
public void setMem(List<Object> mem) {
this.mem = mem;
}
public List<Object> getNet() {
return net;
}
public void setNet(List<Object> net) {
this.net = net;
}
public Object getDisk() {
return disk;
}
public void setDisk(Object disk) {
this.disk = disk;
}
public long getNetTotal() {
return netTotal;
}
public void setNetTotal(long netTotal) {
this.netTotal = netTotal;
}
}
@@ -1,149 +0,0 @@
package com.genersoft.iot.vmp.common;
import com.alibaba.fastjson2.annotation.JSONField;
public class VersionPo {
/**
* git的全版本号
*/
@JSONField(name="GIT_Revision")
private String GIT_Revision;
/**
* maven版本
*/
@JSONField(name = "Create_By")
private String Create_By;
/**
* git的分支
*/
@JSONField(name = "GIT_BRANCH")
private String GIT_BRANCH;
/**
* git的url
*/
@JSONField(name = "GIT_URL")
private String GIT_URL;
/**
* 构建日期
*/
@JSONField(name = "BUILD_DATE")
private String BUILD_DATE;
/**
* 构建日期
*/
@JSONField(name = "GIT_DATE")
private String GIT_DATE;
/**
* 项目名称 配合pom使用
*/
@JSONField(name = "artifactId")
private String artifactId;
/**
* git局部版本号
*/
@JSONField(name = "GIT_Revision_SHORT")
private String GIT_Revision_SHORT;
/**
* 项目的版本如2.0.1.0 配合pom使用
*/
@JSONField(name = "version")
private String version;
/**
* 子系统名称
*/
@JSONField(name = "project")
private String project;
/**
* jdk版本
*/
@JSONField(name="Build_Jdk")
private String Build_Jdk;
public void setGIT_Revision(String GIT_Revision) {
this.GIT_Revision = GIT_Revision;
}
public void setCreate_By(String create_By) {
Create_By = create_By;
}
public void setGIT_BRANCH(String GIT_BRANCH) {
this.GIT_BRANCH = GIT_BRANCH;
}
public void setGIT_URL(String GIT_URL) {
this.GIT_URL = GIT_URL;
}
public void setBUILD_DATE(String BUILD_DATE) {
this.BUILD_DATE = BUILD_DATE;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public void setGIT_Revision_SHORT(String GIT_Revision_SHORT) {
this.GIT_Revision_SHORT = GIT_Revision_SHORT;
}
public void setVersion(String version) {
this.version = version;
}
public void setProject(String project) {
this.project = project;
}
public void setBuild_Jdk(String build_Jdk) {
Build_Jdk = build_Jdk;
}
public String getGIT_Revision() {
return GIT_Revision;
}
public String getCreate_By() {
return Create_By;
}
public String getGIT_BRANCH() {
return GIT_BRANCH;
}
public String getGIT_URL() {
return GIT_URL;
}
public String getBUILD_DATE() {
return BUILD_DATE;
}
public String getArtifactId() {
return artifactId;
}
public String getGIT_Revision_SHORT() {
return GIT_Revision_SHORT;
}
public String getVersion() {
return version;
}
public String getProject() {
return project;
}
public String getBuild_Jdk() {
return Build_Jdk;
}
public String getGIT_DATE() {
return GIT_DATE;
}
public void setGIT_DATE(String GIT_DATE) {
this.GIT_DATE = GIT_DATE;
}
}
@@ -1,168 +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_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_";
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_";
public static final String DEVICE_PREFIX = "VMP_DEVICE_";
// 设备同步完成
public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_";
public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_";
public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_";
// TODO 此处多了一个_,暂不修改
public static final String INVITE_PREFIX = "VMP_INVITE";
public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_";
public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_";
public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_";
public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_";
public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_";
public static final String PLATFORM_REGISTER_PREFIX = "VMP_PLATFORM_REGISTER_";
public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_";
public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_";
public static final String EVENT_ONLINE_REGISTER = "1";
public static final String EVENT_ONLINE_MESSAGE = "3";
public static final String EVENT_OUTLINE_UNREGISTER = "1";
public static final String EVENT_OUTLINE_TIMEOUT = "2";
public static final String MEDIA_SSRC_USED_PREFIX = "VMP_MEDIA_USED_SSRC_";
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_";
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
public static final String SIP_SN_PREFIX = "VMP_SIP_SN_";
public static final String SIP_SUBSCRIBE_PREFIX = "VMP_SIP_SUBSCRIBE_";
public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_";
//************************** 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";
/**
* 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";
/**
* 移动位置订阅通知
*/
public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
/**
* 报警订阅的通知(收到报警向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:";
}
@@ -1,77 +0,0 @@
package com.genersoft.iot.vmp.common.enums;
import org.dom4j.Element;
import org.springframework.util.ObjectUtils;
/**
* @author gaofuwang
* @date 2023/01/18/ 10:09:00
* @since 1.0
*/
public enum DeviceControlType {
/**
* 云台控制
* 上下左右,预置位,扫描,辅助功能,巡航
*/
PTZ("PTZCmd","云台控制"),
/**
* 远程启动
*/
TELE_BOOT("TeleBoot","远程启动"),
/**
* 录像控制
*/
RECORD("RecordCmd","录像控制"),
/**
* 布防撤防
*/
GUARD("GuardCmd","布防撤防"),
/**
* 告警控制
*/
ALARM("AlarmCmd","告警控制"),
/**
* 强制关键帧
*/
I_FRAME("IFameCmd","强制关键帧"),
/**
* 拉框放大
*/
DRAG_ZOOM_IN("DragZoomIn","拉框放大"),
/**
* 拉框缩小
*/
DRAG_ZOOM_OUT("DragZoomOut","拉框缩小"),
/**
* 看守位
*/
HOME_POSITION("HomePosition","看守位");
private final String val;
private final String desc;
DeviceControlType(String val, String desc) {
this.val = val;
this.desc = desc;
}
public String getVal() {
return val;
}
public String getDesc() {
return desc;
}
public static DeviceControlType typeOf(Element rootElement) {
for (DeviceControlType item : DeviceControlType.values()) {
if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) {
return item;
}
}
return null;
}
}
@@ -1,104 +0,0 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.common.CivilCodePo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.file.Files;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 启动时读取行政区划表
*/
@Configuration
@Order(value=14)
public class CivilCodeFileConf implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(CivilCodeFileConf.class);
private final Map<String, CivilCodePo> civilCodeMap= new ConcurrentHashMap<>();
@Autowired
@Lazy
private UserSetting userSetting;
@Override
public void run(String... args) throws Exception {
if (ObjectUtils.isEmpty(userSetting.getCivilCodeFile())) {
logger.warn("[行政区划] 文件未设置,可能造成目录刷新结果不完整");
return;
}
InputStream inputStream;
if (userSetting.getCivilCodeFile().startsWith("classpath:")){
String filePath = userSetting.getCivilCodeFile().substring("classpath:".length());
ClassPathResource civilCodeFile = new ClassPathResource(filePath);
if (!civilCodeFile.exists()) {
logger.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
return;
}
inputStream = civilCodeFile.getInputStream();
}else {
File civilCodeFile = new File(userSetting.getCivilCodeFile());
if (!civilCodeFile.exists()) {
logger.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
return;
}
inputStream = Files.newInputStream(civilCodeFile.toPath());
}
BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(inputStream));
int index = -1;
String line;
while ((line = inputStreamReader.readLine()) != null) {
index ++;
if (index == 0) {
continue;
}
String[] infoArray = line.split(",");
CivilCodePo civilCodePo = CivilCodePo.getInstance(infoArray);
civilCodeMap.put(civilCodePo.getCode(), civilCodePo);
}
inputStreamReader.close();
inputStream.close();
if (civilCodeMap.size() == 0) {
logger.warn("[行政区划] 文件内容为空,可能造成目录刷新结果不完整");
}else {
logger.info("[行政区划] 加载成功,共加载数据{}条", civilCodeMap.size());
}
}
public CivilCodePo getParentCode(String code) {
if (code.length() > 8) {
return null;
}
if (code.length() == 8) {
String parentCode = code.substring(0, 6);
return civilCodeMap.get(parentCode);
}else {
CivilCodePo civilCodePo = civilCodeMap.get(code);
if (civilCodePo == null){
return null;
}
String parentCode = civilCodePo.getParentCode();
if (parentCode == null) {
return null;
}
return civilCodeMap.get(parentCode);
}
}
}
@@ -1,158 +0,0 @@
package com.genersoft.iot.vmp.conf;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.Instant;
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
*/
@Component
public class DynamicTask {
private final Logger logger = LoggerFactory.getLogger(DynamicTask.class);
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.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()) {
logger.debug("任务【{}】已存在但是关闭状态!!!", key);
} else {
logger.debug("任务【{}】已存在且已启动!!!", key);
return;
}
}
// scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period cycleForCatalog表示执行的间隔
future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog);
if (future != null){
futureMap.put(key, future);
runnableMap.put(key, task);
logger.debug("任务【{}】启动成功!!!", key);
}else {
logger.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()) {
logger.debug("任务【{}】已存在但是关闭状态!!!", key);
} else {
logger.debug("任务【{}】已存在且已启动!!!", key);
return;
}
}
// scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period cycleForCatalog表示执行的间隔
future = threadPoolTaskScheduler.schedule(task, startInstant);
if (future != null){
futureMap.put(key, future);
runnableMap.put(key, task);
logger.debug("任务【{}】启动成功!!!", key);
}else {
logger.debug("任务【{}】启动失败!!!", key);
}
}
public boolean stop(String key) {
if(ObjectUtils.isEmpty(key)) {
return false;
}
boolean result = false;
if (!ObjectUtils.isEmpty(futureMap.get(key)) && !futureMap.get(key).isCancelled() && !futureMap.get(key).isDone()) {
result = futureMap.get(key).cancel(false);
futureMap.remove(key);
runnableMap.remove(key);
}
return result;
}
public boolean contains(String key) {
if(ObjectUtils.isEmpty(key)) {
return false;
}
return futureMap.get(key) != null;
}
public Set<String> getAllKeys() {
return futureMap.keySet();
}
public Runnable get(String key) {
if(ObjectUtils.isEmpty(key)) {
return null;
}
return runnableMap.get(key);
}
/**
* 每五分钟检查失效的任务,并移除
*/
@Scheduled(cron="0 0/5 * * * ?")
public void execute(){
if (futureMap.size() > 0) {
for (String key : futureMap.keySet()) {
ScheduledFuture<?> future = futureMap.get(key);
if (future.isDone() || future.isCancelled()) {
futureMap.remove(key);
runnableMap.remove(key);
}
}
}
}
public boolean isAlive(String key) {
return futureMap.get(key) != null && !futureMap.get(key).isDone() && !futureMap.get(key).isCancelled();
}
}
@@ -1,326 +0,0 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
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;
@Order(0)
@ConfigurationProperties(prefix = "media")
public class MediaConfig{
private final static Logger logger = LoggerFactory.getLogger(MediaConfig.class);
// 修改必须配置,不再支持自动获取
private String id;
/**
* 流媒体ip
*/
private String ip;
/**
* 流媒体回调ip
*/
private String hookIp;
/**
* 回调地址前缀
*/
private String hookPrefix = "gbs/zlm/hook";
@Value("${sip.ip}")
private String sipIp;
@Value("${sip.domain}")
private String sipDomain;
private String sdpIp;
private String streamIp;
private Integer httpPort;
private Integer httpSSlPort = 0;
private Integer rtmpPort = 0;
private Integer rtmpSSlPort = 0;
@Value("${media.rtp-proxy-port:0}")
private Integer rtpProxyPort = 0;
@Value("${media.rtsp-port:0}")
private Integer rtspPort = 0;
@Value("${media.rtsp-ssl-port:0}")
private Integer rtspSSLPort = 0;
/**
* 自动配置
*/
private boolean autoConfig = true;
/**
* zlm服务器的 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;
public String getId() {
return id;
}
public String getIp() {
return ip;
}
public String getHookIp() {
if (ObjectUtils.isEmpty(hookIp)){
return sipIp.split(",")[0];
}else {
return hookIp;
}
}
public String getSipIp() {
if (sipIp == null) {
return this.ip;
}else {
return sipIp;
}
}
public int getHttpPort() {
return httpPort;
}
public int getHttpSSlPort() {
return httpSSlPort;
}
public int getRtmpPort() {
return rtmpPort;
}
public int getRtmpSSlPort() {
return rtmpSSlPort;
}
public int getRtpProxyPort() {
if (rtpProxyPort == null) {
return 0;
}else {
return rtpProxyPort;
}
}
public int getRtspPort() {
return rtspPort;
}
public int getRtspSSLPort() {
return rtspSSLPort;
}
public boolean isAutoConfig() {
return autoConfig;
}
public String getSecret() {
return secret;
}
public boolean isRtpEnable() {
return rtpEnable;
}
public String getRtpPortRange() {
return rtpPortRange;
}
public int getRecordAssistPort() {
return recordAssistPort;
}
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) {
logger.error("[获取SDP IP]: 域名解析失败");
}
return hostAddress;
}
}
}
public void setId(String id) {
this.id = id;
}
public void setIp(String ip) {
this.ip = ip;
}
public void setHookIp(String hookIp) {
this.hookIp = hookIp;
}
public void setHttpPort(Integer httpPort) {
this.httpPort = httpPort;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getStreamIp() {
if (ObjectUtils.isEmpty(streamIp)){
return ip;
}else {
return streamIp;
}
}
public String getSipDomain() {
return sipDomain;
}
public MediaServerItem getMediaSerItem(){
MediaServerItem mediaServerItem = new MediaServerItem();
mediaServerItem.setId(id);
mediaServerItem.setIp(ip);
mediaServerItem.setDefaultServer(true);
mediaServerItem.setHookIp(getHookIp());
mediaServerItem.setSdpIp(getSdpIp());
mediaServerItem.setStreamIp(getStreamIp());
mediaServerItem.setHttpPort(httpPort);
mediaServerItem.setHttpSSlPort(httpSSlPort);
mediaServerItem.setRtmpPort(rtmpPort);
mediaServerItem.setRtmpSSlPort(rtmpSSlPort);
mediaServerItem.setRtpProxyPort(getRtpProxyPort());
mediaServerItem.setRtspPort(rtspPort);
mediaServerItem.setRtspSSLPort(rtspSSLPort);
mediaServerItem.setAutoConfig(autoConfig);
mediaServerItem.setSecret(secret);
mediaServerItem.setRtpEnable(rtpEnable);
mediaServerItem.setRtpPortRange(rtpPortRange);
mediaServerItem.setSendRtpPortRange(rtpSendPortRange);
mediaServerItem.setRecordAssistPort(recordAssistPort);
mediaServerItem.setHookAliveInterval(30.00f);
mediaServerItem.setCreateTime(DateUtil.getNow());
mediaServerItem.setUpdateTime(DateUtil.getNow());
return mediaServerItem;
}
public String getRtpSendPortRange() {
return rtpSendPortRange;
}
public void setRtpSendPortRange(String rtpSendPortRange) {
this.rtpSendPortRange = rtpSendPortRange;
}
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;
}
public void setSipIp(String sipIp) {
this.sipIp = sipIp;
}
public void setSipDomain(String sipDomain) {
this.sipDomain = sipDomain;
}
public void setSdpIp(String sdpIp) {
this.sdpIp = sdpIp;
}
public void setStreamIp(String streamIp) {
this.streamIp = streamIp;
}
public void setHttpSSlPort(Integer httpSSlPort) {
this.httpSSlPort = httpSSlPort;
}
public void setRtmpPort(Integer rtmpPort) {
this.rtmpPort = rtmpPort;
}
public void setRtmpSSlPort(Integer rtmpSSlPort) {
this.rtmpSSlPort = rtmpSSlPort;
}
public void setRtpProxyPort(Integer rtpProxyPort) {
this.rtpProxyPort = rtpProxyPort;
}
public void setRtspPort(Integer rtspPort) {
this.rtspPort = rtspPort;
}
public void setRtspSSLPort(Integer rtspSSLPort) {
this.rtspSSLPort = rtspSSLPort;
}
public void setAutoConfig(boolean autoConfig) {
this.autoConfig = autoConfig;
}
public void setRtpEnable(boolean rtpEnable) {
this.rtpEnable = rtpEnable;
}
public void setRtpPortRange(String rtpPortRange) {
this.rtpPortRange = rtpPortRange;
}
public void setRecordAssistPort(Integer recordAssistPort) {
this.recordAssistPort = recordAssistPort;
}
public String getHookPrefix() {
return hookPrefix;
}
public void setHookPrefix(String hookPrefix) {
this.hookPrefix = hookPrefix;
}
}
@@ -1,303 +0,0 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.springframework.core.annotation.Order;
import org.mitre.dsmiley.httpproxy.ProxyServlet;
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.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.ConnectException;
/**
* @author lin
*/
@SuppressWarnings(value = {"rawtypes", "unchecked"})
@Configuration
@Order(1)
public class ProxyServletConfig {
private final static Logger logger = LoggerFactory.getLogger(ProxyServletConfig.class);
@Autowired
private IMediaServerService mediaServerService;
@Value("${server.port}")
private int serverPort;
@Bean
public ServletRegistrationBean zlmServletRegistrationBean(){
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZlmProxyServlet(),"/zlm/*");
servletRegistrationBean.setName("zlm_Proxy");
servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:6080");
servletRegistrationBean.addUrlMappings();
if (logger.isDebugEnabled()) {
servletRegistrationBean.addInitParameter("log", "true");
}
return servletRegistrationBean;
}
class ZlmProxyServlet extends ProxyServlet{
@Override
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
if (mediaInfo != null) {
if (!ObjectUtils.isEmpty(queryStr)) {
queryStr += "&secret=" + mediaInfo.getSecret();
}else {
queryStr = "secret=" + mediaInfo.getSecret();
}
}
return queryStr;
}
@Override
protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
HttpRequest proxyRequest) throws IOException {
HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);
response.removeHeaders("Access-Control-Allow-Origin");
response.setHeader("Access-Control-Allow-Credentials","true");
response.removeHeaders("Access-Control-Allow-Credentials");
return response;
}
/**
* 异常处理
*/
@Override
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){
try {
super.handleRequestException(proxyRequest, proxyResonse, e);
} catch (ServletException servletException) {
logger.error("zlm 代理失败: ", e);
} catch (IOException ioException) {
if (ioException instanceof ConnectException) {
logger.error("zlm 连接失败");
} else {
logger.error("zlm 代理失败: ", e);
}
} catch (RuntimeException exception){
logger.error("zlm 代理失败: ", e);
}
}
/**
* 对于为按照格式请求的可以直接返回404
*/
@Override
protected String getTargetUri(HttpServletRequest servletRequest) {
String requestURI = servletRequest.getRequestURI();
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
String uri = null;
if (mediaInfo != null) {
// String realRequestURI = requestURI.substring(requestURI.indexOf(mediaInfo.getId())+ mediaInfo.getId().length());
uri = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort());
}else {
uri = "http://127.0.0.1:" + serverPort +"/index/hook/null"; // 只是一个能返回404的请求而已, 其他的也可以
}
return uri;
}
/**
* 动态替换请求目标
*/
@Override
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
String requestURI = servletRequest.getRequestURI();
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
HttpHost host;
if (mediaInfo != null) {
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
}else {
host = new HttpHost("127.0.0.1", serverPort);
}
return host;
}
/**
* 根据uri获取流媒体信息
*/
MediaServerItem getMediaInfoByUri(String uri){
String[] split = uri.split("/");
String mediaServerId = split[2];
if ("default".equalsIgnoreCase(mediaServerId)) {
return mediaServerService.getDefaultMediaServer();
}else {
return mediaServerService.getOne(mediaServerId);
}
}
/**
* 去掉url中的标志信息
*/
@Override
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
String requestURI = servletRequest.getRequestURI();
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
String url = super.rewriteUrlFromRequest(servletRequest);
if (mediaInfo == null) {
logger.error("[ZLM服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
return url;
}
if (!ObjectUtils.isEmpty(mediaInfo.getId())) {
url = url.replace(mediaInfo.getId() + "/", "");
}
return url.replace("default/", "");
}
}
@Bean
public ServletRegistrationBean recordServletRegistrationBean(){
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new RecordProxyServlet(),"/record_proxy/*");
servletRegistrationBean.setName("record_proxy");
servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:18081");
servletRegistrationBean.addUrlMappings();
if (logger.isDebugEnabled()) {
servletRegistrationBean.addInitParameter("log", "true");
}
return servletRegistrationBean;
}
class RecordProxyServlet extends ProxyServlet{
@Override
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
if (mediaInfo == null) {
return null;
}
String remoteHost = String.format("http://%s:%s", mediaInfo.getStreamIp(), mediaInfo.getRecordAssistPort());
if (!ObjectUtils.isEmpty(queryStr)) {
queryStr += "&remoteHost=" + remoteHost;
}else {
queryStr = "remoteHost=" + remoteHost;
}
return queryStr;
}
@Override
protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
HttpRequest proxyRequest) throws IOException {
HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);
String origin = servletRequest.getHeader("origin");
response.setHeader("Access-Control-Allow-Origin",origin);
response.setHeader("Access-Control-Allow-Credentials","true");
return response;
}
/**
* 异常处理
*/
@Override
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResponse, Exception e){
try {
super.handleRequestException(proxyRequest, proxyResponse, e);
} catch (ServletException servletException) {
logger.error("录像服务 代理失败: ", e);
} catch (IOException ioException) {
if (ioException instanceof ConnectException) {
logger.error("录像服务 连接失败");
// }else if (ioException instanceof ClientAbortException) {
// /**
// * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常,
// * TODO 暂时去除异常处理。后续使用其他代理框架修改测试
// */
}else {
logger.error("录像服务 代理失败: ", e);
}
} catch (RuntimeException exception){
logger.error("录像服务 代理失败: ", e);
}
}
/**
* 对于为按照格式请求的可以直接返回404
*/
@Override
protected String getTargetUri(HttpServletRequest servletRequest) {
String requestURI = servletRequest.getRequestURI();
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
String uri = null;
if (mediaInfo != null) {
// String realRequestURI = requestURI.substring(requestURI.indexOf(mediaInfo.getId())+ mediaInfo.getId().length());
uri = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
}else {
uri = "http://127.0.0.1:" + serverPort +"/index/hook/null"; // 只是一个能返回404的请求而已, 其他的也可以
}
return uri;
}
/**
* 动态替换请求目标
*/
@Override
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
String requestURI = servletRequest.getRequestURI();
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
HttpHost host;
if (mediaInfo != null) {
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
}else {
host = new HttpHost("127.0.0.1", serverPort);
}
return host;
}
/**
* 根据uri获取流媒体信息
*/
MediaServerItem getMediaInfoByUri(String uri){
String[] split = uri.split("/");
String mediaServerId = split[2];
if ("default".equalsIgnoreCase(mediaServerId)) {
return mediaServerService.getDefaultMediaServer();
}else {
return mediaServerService.getOne(mediaServerId);
}
}
/**
* 去掉url中的标志信息
*/
@Override
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
String requestURI = servletRequest.getRequestURI();
MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
String url = super.rewriteUrlFromRequest(servletRequest);
if (mediaInfo == null) {
logger.error("[录像服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
return url;
}
if (!ObjectUtils.isEmpty(mediaInfo.getId())) {
url = url.replace(mediaInfo.getId() + "/", "");
}
return url.replace("default/", "");
}
}
}
@@ -1,30 +0,0 @@
package com.genersoft.iot.vmp.conf;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* "@Scheduled"是Spring框架提供的一种定时任务执行机制,默认情况下它是单线程的,在同时执行多个定时任务时可能会出现阻塞和性能问题。
* 为了解决这种单线程瓶颈问题,可以将定时任务的执行机制改为支持多线程
*/
//@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
public static final int cpuNum = Runtime.getRuntime().availableProcessors();
private static final int corePoolSize = cpuNum;
private static final String threadNamePrefix = "scheduled-task-pool-%d";
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern(threadNamePrefix).daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy()));
}
}
@@ -1,110 +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 = "sip", ignoreInvalidFields = true)
@Order(0)
public class SipConfig {
private String ip;
private String showIp;
private Integer port;
private String domain;
private String id;
private String password;
Integer ptzSpeed = 50;
Integer registerTimeInterval = 120;
private boolean alarm;
public void setIp(String ip) {
this.ip = ip;
}
public void setPort(Integer port) {
this.port = port;
}
public void setDomain(String domain) {
this.domain = domain;
}
public void setId(String id) {
this.id = id;
}
public void setPassword(String password) {
this.password = password;
}
public void setPtzSpeed(Integer ptzSpeed) {
this.ptzSpeed = ptzSpeed;
}
public void setRegisterTimeInterval(Integer registerTimeInterval) {
this.registerTimeInterval = registerTimeInterval;
}
public String getIp() {
return ip;
}
public Integer getPort() {
return port;
}
public String getDomain() {
return domain;
}
public String getId() {
return id;
}
public String getPassword() {
return password;
}
public Integer getPtzSpeed() {
return ptzSpeed;
}
public Integer getRegisterTimeInterval() {
return registerTimeInterval;
}
public boolean isAlarm() {
return alarm;
}
public void setAlarm(boolean alarm) {
this.alarm = alarm;
}
public String getShowIp() {
if (this.showIp == null) {
return this.ip;
}
return showIp;
}
public void setShowIp(String showIp) {
this.showIp = showIp;
}
}
@@ -1,72 +0,0 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 系统启动时控制上级平台重新注册
* @author lin
*/
@Component
@Order(value=13)
public class SipPlatformRunner implements CommandLineRunner {
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IPlatformService platformService;
@Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform;
private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
@Override
public void run(String... args) throws Exception {
// 获取所有启用的平台
List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true);
for (ParentPlatform parentPlatform : parentPlatforms) {
ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
// 更新缓存
ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch();
parentPlatformCatch.setParentPlatform(parentPlatform);
parentPlatformCatch.setId(parentPlatform.getServerGBId());
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
if (parentPlatformCatchOld != null) {
// 取消订阅
try {
sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
platformService.login(parentPlatform);
});
} catch (Exception e) {
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
platformService.offline(parentPlatform, true);
continue;
}
}
// 设置所有平台离线
platformService.offline(parentPlatform, false);
}
}
}
@@ -1,70 +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 = cpuNum;
/**
* 最大线程数
*/
private static final int maxPoolSize = cpuNum*2;
/**
* 允许线程空闲时间(单位:默认为秒)
*/
private static final int keepAliveTime = 30;
/**
* 缓冲队列大小
*/
private static final int queueCapacity = 10000;
/**
* 线程池名前缀
*/
private static final String threadNamePrefix = "wvp-";
/**
*
* @return
*/
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveTime);
executor.setThreadNamePrefix(threadNamePrefix);
// 线程池对拒绝任务的处理策略
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
executor.initialize();
return executor;
}
}
@@ -1,318 +0,0 @@
package com.genersoft.iot.vmp.conf;
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)
public class UserSetting {
private Boolean savePositionHistory = Boolean.FALSE;
private Boolean autoApplyPlay = Boolean.FALSE;
private Boolean seniorSdp = Boolean.FALSE;
private Integer playTimeout = 18000;
private int platformPlayTimeout = 60000;
private Boolean interfaceAuthentication = Boolean.TRUE;
private Boolean recordPushLive = Boolean.TRUE;
private Boolean recordSip = Boolean.TRUE;
private Boolean logInDatabase = Boolean.TRUE;
private Boolean usePushingAsStatus = Boolean.TRUE;
private Boolean useSourceIpAsStreamIp = Boolean.FALSE;
private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE;
private Boolean streamOnDemand = Boolean.TRUE;
private Boolean pushAuthority = Boolean.TRUE;
private Boolean syncChannelOnDeviceOnline = Boolean.TRUE;
private Boolean sipLog = Boolean.FALSE;
private Boolean sqlLog = Boolean.FALSE;
private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE;
private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE;
private Boolean deviceStatusNotify = Boolean.FALSE;
private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
private String serverId = "000000";
private String recordPath = null;
private String thirdPartyGBIdReg = "[\\s\\S]*";
private String civilCodeFile = "classpath:civilCode.csv";
private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
private List<String> allowedOrigins = new ArrayList<>();
private int maxNotifyCountQueue = 10000;
private int registerAgainAfterTime = 60;
private boolean registerKeepIntDialog = false;
public Boolean getSavePositionHistory() {
return savePositionHistory;
}
public Boolean isSavePositionHistory() {
return savePositionHistory;
}
public Boolean isAutoApplyPlay() {
return autoApplyPlay;
}
public Boolean isSeniorSdp() {
return seniorSdp;
}
public Integer getPlayTimeout() {
return playTimeout;
}
public Boolean isInterfaceAuthentication() {
return interfaceAuthentication;
}
public Boolean isRecordPushLive() {
return recordPushLive;
}
public List<String> getInterfaceAuthenticationExcludes() {
return interfaceAuthenticationExcludes;
}
public void setSavePositionHistory(Boolean savePositionHistory) {
this.savePositionHistory = savePositionHistory;
}
public void setAutoApplyPlay(Boolean autoApplyPlay) {
this.autoApplyPlay = autoApplyPlay;
}
public void setSeniorSdp(Boolean seniorSdp) {
this.seniorSdp = seniorSdp;
}
public void setPlayTimeout(Integer playTimeout) {
this.playTimeout = playTimeout;
}
public void setInterfaceAuthentication(boolean interfaceAuthentication) {
this.interfaceAuthentication = interfaceAuthentication;
}
public void setRecordPushLive(Boolean recordPushLive) {
this.recordPushLive = recordPushLive;
}
public void setInterfaceAuthenticationExcludes(List<String> interfaceAuthenticationExcludes) {
this.interfaceAuthenticationExcludes = interfaceAuthenticationExcludes;
}
public Boolean getLogInDatabase() {
return logInDatabase;
}
public void setLogInDatabase(Boolean logInDatabase) {
this.logInDatabase = logInDatabase;
}
public String getServerId() {
return serverId;
}
public void setServerId(String serverId) {
this.serverId = serverId;
}
public String getThirdPartyGBIdReg() {
return thirdPartyGBIdReg;
}
public void setThirdPartyGBIdReg(String thirdPartyGBIdReg) {
this.thirdPartyGBIdReg = thirdPartyGBIdReg;
}
public Boolean getRecordSip() {
return recordSip;
}
public void setRecordSip(Boolean recordSip) {
this.recordSip = recordSip;
}
public int getPlatformPlayTimeout() {
return platformPlayTimeout;
}
public void setPlatformPlayTimeout(int platformPlayTimeout) {
this.platformPlayTimeout = platformPlayTimeout;
}
public Boolean isUsePushingAsStatus() {
return usePushingAsStatus;
}
public void setUsePushingAsStatus(Boolean usePushingAsStatus) {
this.usePushingAsStatus = usePushingAsStatus;
}
public Boolean getStreamOnDemand() {
return streamOnDemand;
}
public void setStreamOnDemand(Boolean streamOnDemand) {
this.streamOnDemand = streamOnDemand;
}
public Boolean getUseSourceIpAsStreamIp() {
return useSourceIpAsStreamIp;
}
public void setUseSourceIpAsStreamIp(Boolean useSourceIpAsStreamIp) {
this.useSourceIpAsStreamIp = useSourceIpAsStreamIp;
}
public Boolean getPushAuthority() {
return pushAuthority;
}
public void setPushAuthority(Boolean pushAuthority) {
this.pushAuthority = pushAuthority;
}
public Boolean getSyncChannelOnDeviceOnline() {
return syncChannelOnDeviceOnline;
}
public void setSyncChannelOnDeviceOnline(Boolean syncChannelOnDeviceOnline) {
this.syncChannelOnDeviceOnline = syncChannelOnDeviceOnline;
}
public Boolean getSipUseSourceIpAsRemoteAddress() {
return sipUseSourceIpAsRemoteAddress;
}
public void setSipUseSourceIpAsRemoteAddress(Boolean sipUseSourceIpAsRemoteAddress) {
this.sipUseSourceIpAsRemoteAddress = sipUseSourceIpAsRemoteAddress;
}
public Boolean getSipLog() {
return sipLog;
}
public void setSipLog(Boolean sipLog) {
this.sipLog = sipLog;
}
public List<String> getAllowedOrigins() {
return allowedOrigins;
}
public void setAllowedOrigins(List<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
public Boolean getSendToPlatformsWhenIdLost() {
return sendToPlatformsWhenIdLost;
}
public void setSendToPlatformsWhenIdLost(Boolean sendToPlatformsWhenIdLost) {
this.sendToPlatformsWhenIdLost = sendToPlatformsWhenIdLost;
}
public Boolean getRefuseChannelStatusChannelFormNotify() {
return refuseChannelStatusChannelFormNotify;
}
public void setRefuseChannelStatusChannelFormNotify(Boolean refuseChannelStatusChannelFormNotify) {
this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify;
}
public String getRecordPath() {
return recordPath;
}
public void setRecordPath(String recordPath) {
this.recordPath = recordPath;
}
public int getMaxNotifyCountQueue() {
return maxNotifyCountQueue;
}
public void setMaxNotifyCountQueue(int maxNotifyCountQueue) {
this.maxNotifyCountQueue = maxNotifyCountQueue;
}
public Boolean getDeviceStatusNotify() {
return deviceStatusNotify;
}
public void setDeviceStatusNotify(Boolean deviceStatusNotify) {
this.deviceStatusNotify = deviceStatusNotify;
}
public Boolean getUseCustomSsrcForParentInvite() {
return useCustomSsrcForParentInvite;
}
public void setUseCustomSsrcForParentInvite(Boolean useCustomSsrcForParentInvite) {
this.useCustomSsrcForParentInvite = useCustomSsrcForParentInvite;
}
public Boolean getSqlLog() {
return sqlLog;
}
public void setSqlLog(Boolean sqlLog) {
this.sqlLog = sqlLog;
}
public String getCivilCodeFile() {
return civilCodeFile;
}
public void setCivilCodeFile(String civilCodeFile) {
this.civilCodeFile = civilCodeFile;
}
public int getRegisterAgainAfterTime() {
return registerAgainAfterTime;
}
public void setRegisterAgainAfterTime(int registerAgainAfterTime) {
this.registerAgainAfterTime = registerAgainAfterTime;
}
public boolean isRegisterKeepIntDialog() {
return registerKeepIntDialog;
}
public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
this.registerKeepIntDialog = registerKeepIntDialog;
}
}
@@ -1,33 +0,0 @@
package com.genersoft.iot.vmp.conf;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.service.IMediaServerService;
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;
@Component
public class WVPTimerTask {
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IMediaServerService mediaServerService;
@Value("${server.port}")
private int serverPort;
@Autowired
private SipConfig sipConfig;
@Scheduled(fixedRate = 2 * 1000) //每3秒执行一次
public void execute(){
JSONObject jsonObject = new JSONObject();
jsonObject.put("ip", sipConfig.getIp());
jsonObject.put("port", serverPort);
redisCatchStorage.updateWVPInfo(jsonObject, 3);
}
}
@@ -1,37 +0,0 @@
package com.genersoft.iot.vmp.conf.exception;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
/**
* 自定义异常,controller出现错误时直接抛出异常由全局异常捕获并返回结果
*/
public class ControllerException extends RuntimeException{
private int code;
private String msg;
public ControllerException(int code, String msg) {
this.code = code;
this.msg = msg;
}
public ControllerException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.msg = errorCode.getMsg();
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
@@ -1,49 +0,0 @@
package com.genersoft.iot.vmp.conf.exception;
/**
* @author lin
*/
public class SsrcTransactionNotFoundException extends Exception{
private String deviceId;
private String channelId;
private String callId;
private String stream;
public SsrcTransactionNotFoundException(String deviceId, String channelId, String callId, String stream) {
this.deviceId = deviceId;
this.channelId = channelId;
this.callId = callId;
this.stream = stream;
}
public String getDeviceId() {
return deviceId;
}
public String getChannelId() {
return channelId;
}
public String getCallId() {
return callId;
}
public String getStream() {
return stream;
}
@Override
public String getMessage() {
StringBuffer msg = new StringBuffer();
msg.append(String.format("缓存事务信息未找到,device%s channel: %s ", deviceId, channelId));
if (callId != null) {
msg.append(",callId: " + callId);
}
if (stream != null) {
msg.append(",stream: " + stream);
}
return msg.toString();
}
}
@@ -1,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 RedisStreamMsgListener redisStreamMsgListener;
@Autowired
private RedisGbPlayMsgListener redisGbPlayMsgListener;
@Autowired
private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
@Autowired
private RedisPushStreamStatusListMsgListener redisPushStreamListMsgListener;
@Autowired
private RedisPushStreamResponseListener redisPushStreamResponseListener;
@Autowired
private RedisCloseStreamMsgListener redisCloseStreamMsgListener;
@Autowired
private RedisPushStreamCloseResponseListener 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(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH"));
container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY));
container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
container.addMessageListener(redisPushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE));
container.addMessageListener(redisPushStreamResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE));
container.addMessageListener(redisCloseStreamMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE));
container.addMessageListener(redisPushStreamCloseResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE_REQUESTED));
return container;
}
}
@@ -1,141 +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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.util.*;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Order(value=10)
public class SipLayer implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
@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<>();
@Override
public void run(String... args) {
List<String> monitorIps = new ArrayList<>();
// 使用逗号分割多个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());
}
SipFactory.getInstance().setPathName("gov.nist");
if (monitorIps.size() > 0) {
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()));
sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
} catch (PeerUnavailableException e) {
logger.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);
logger.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port);
} catch (TransportNotSupportedException
| TooManyListenersException
| ObjectInUseException
| InvalidArgumentException e) {
logger.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);
udpSipProviderMap.put(monitorIp, udpSipProvider);
logger.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port);
} catch (TransportNotSupportedException
| TooManyListenersException
| ObjectInUseException
| InvalidArgumentException e) {
logger.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
, monitorIp, port);
}
}
public SipProviderImpl getUdpSipProvider(String ip) {
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 (ObjectUtils.isEmpty(ip)) {
return null;
}
return tcpSipProviderMap.get(ip);
}
public String getLocalIp(String deviceLocalIp) {
if (!ObjectUtils.isEmpty(deviceLocalIp)) {
return deviceLocalIp;
}
return getUdpSipProvider().getListeningPoint().getIPAddress();
}
}
@@ -1,241 +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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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
*/
public class DigestServerAuthenticationHelper {
private Logger logger = LoggerFactory.getLogger(DigestServerAuthenticationHelper.class);
private 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.
* @throws NoSuchAlgorithmException
*/
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 (int i = 0; i < b.length; i++) {
c[pos++] = toHex[(b[i] >> 4) & 0x0F];
c[pos++] = toHex[b[i] & 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);
}
/**
* Authenticate the inbound request given plain text password.
*
* @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;
}
String realm = authHeader.getRealm().trim();
String username = authHeader.getUsername().trim();
if ( username == null || realm == null ) {
return false;
}
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 ncStr = new DecimalFormat("00000000").format(nc);
// String ncStr = new DecimalFormat("00000000").format(Integer.parseInt(nc + "", 16));
String A1 = username + ":" + realm + ":" + pass;
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
byte mdbytes[] = messageDigest.digest(A1.getBytes());
String HA1 = toHexString(mdbytes);
logger.debug("A1: " + A1);
logger.debug("A2: " + A2);
mdbytes = messageDigest.digest(A2.getBytes());
String HA2 = toHexString(mdbytes);
logger.debug("HA1: " + HA1);
logger.debug("HA2: " + HA2);
// String cnonce = authHeader.getCNonce();
logger.debug("nonce: " + nonce);
logger.debug("nc: " + ncStr);
logger.debug("cnonce: " + cnonce);
logger.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;
logger.debug("KD: " + KD);
mdbytes = messageDigest.digest(KD.getBytes());
String mdString = toHexString(mdbytes);
logger.debug("mdString: " + mdString);
String response = authHeader.getResponse();
logger.debug("response: " + response);
return mdString.equals(response);
}
}
@@ -1,57 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 通过redis分发报警消息
*/
public class AlarmChannelMessage {
/**
* 国标编号
*/
private String gbId;
/**
* 报警编号
*/
private int alarmSn;
/**
* 告警类型
*/
private int alarmType;
/**
* 报警描述
*/
private String alarmDescription;
public String getGbId() {
return gbId;
}
public void setGbId(String gbId) {
this.gbId = gbId;
}
public int getAlarmSn() {
return alarmSn;
}
public void setAlarmSn(int alarmSn) {
this.alarmSn = alarmSn;
}
public int getAlarmType() {
return alarmType;
}
public void setAlarmType(int alarmType) {
this.alarmType = alarmType;
}
public String getAlarmDescription() {
return alarmDescription;
}
public void setAlarmDescription(String alarmDescription) {
this.alarmDescription = alarmDescription;
}
}
@@ -1,24 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class BaiduPoint {
String bdLng;
String bdLat;
public String getBdLng() {
return bdLng;
}
public void setBdLng(String bdLng) {
this.bdLng = bdLng;
}
public String getBdLat() {
return bdLat;
}
public void setBdLat(String bdLat) {
this.bdLat = bdLat;
}
}
@@ -1,81 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import java.time.Instant;
import java.util.List;
/**
* @author lin
*/
public class CatalogData {
/**
* 命令序列号
*/
private int sn;
private int total;
private List<DeviceChannel> channelList;
private Instant lastTime;
private Device device;
private String errorMsg;
public enum CatalogDataStatus{
ready, runIng, end
}
private CatalogDataStatus status;
public int getSn() {
return sn;
}
public void setSn(int sn) {
this.sn = sn;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List<DeviceChannel> getChannelList() {
return channelList;
}
public void setChannelList(List<DeviceChannel> channelList) {
this.channelList = channelList;
}
public Instant getLastTime() {
return lastTime;
}
public void setLastTime(Instant lastTime) {
this.lastTime = lastTime;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public CatalogDataStatus getStatus() {
return status;
}
public void setStatus(CatalogDataStatus status) {
this.status = status;
}
}
@@ -1,23 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 国标类型编码,国标编码中11-13位为类型编码
* 详见 附 录 D 编码规则 A
* @author lin
*/
public class ChannelIdType {
/**
* 中心信令控制服务器编码
*/
public final static String CENTRAL_SIGNALING_CONTROL_SERVER = "200";
/**
* 业务分组编码
*/
public final static String BUSINESS_GROUP = "215";
/**
* 虚拟组织编码
*/
public final static String VIRTUAL_ORGANIZATION = "216";
}
@@ -1,8 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class CmdType {
public static final String CATALOG = "Catalog";
public static final String ALARM = "Alarm";
public static final String MOBILE_POSITION = "MobilePosition";
}
@@ -1,480 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.iteaj.framework.Entity;
import io.swagger.v3.oas.annotations.media.Schema;
import java.beans.Transient;
/**
* 国标设备/平台
* @author lin
*/
@TableName("wvp_device")
@Schema(description = "国标设备/平台")
public class Device implements Entity<Long> {
@TableId(type = IdType.AUTO)
private Long id;
/**
* 设备国标编号
*/
private String deviceId;
/**
* 设备名
*/
private String name;
/**
* 生产厂商
*/
private String manufacturer;
/**
* 型号
*/
private String model;
/**
* 固件版本
*/
private String firmware;
/**
* 传输协议
* UDP/TCP
*/
private String transport;
/**
* 数据流传输模式
* UDP:udp传输
* TCP-ACTIVEtcp主动模式
* TCP-PASSIVEtcp被动模式
*/
private String streamMode;
/**
* wan地址_ip
*/
private String ip;
/**
* wan地址_port
*/
private Integer port;
/**
* wan地址
*/
private String hostAddress;
/**
* 是否在线,true为在线,false为离线
*/
private Boolean onLine;
/**
* 注册时间
*/
private String registerTime;
/**
* 心跳时间
*/
private String keepaliveTime;
/**
* 心跳间隔
*/
private Integer keepaliveIntervalTime;
/**
* 通道个数
*/
@TableField(exist = false)
private Integer channelCount;
/**
* 注册有效期
*/
private Integer expires;
/**
* 创建时间
*/
private String createTime;
/**
* 更新时间
*/
private String updateTime;
/**
* 设备使用的媒体id, 默认为null
*/
private String mediaServerId;
/**
* 字符集, 支持 UTF-8 与 GB2312
*/
private String charset ;
/**
* 目录订阅周期,0为不订阅
*/
private int subscribeCycleForCatalog;
/**
* 移动设备位置订阅周期,0为不订阅
*/
private int subscribeCycleForMobilePosition;
/**
* 移动设备位置信息上报时间间隔,单位:秒,默认值5
*/
private int mobilePositionSubmissionInterval = 5;
/**
* 报警订阅周期,0为不订阅
*/
private int subscribeCycleForAlarm;
/**
* 是否开启ssrc校验,默认关闭,开启可以防止串流
*/
private Boolean ssrcCheck = false;
/**
* 地理坐标系, 目前支持 WGS84,GCJ02
*/
private String geoCoordSys;
/**
* 密码
*/
private String password;
/**
* 收流IP
*/
private String sdpIp;
/**
* SIP交互IP(设备访问平台的IP)
*/
private String localIp;
/**
* 是否作为消息通道
*/
private Boolean asMessageChannel;
/**
* 设备注册的事务信息
*/
@TableField(exist = false)
private SipTransactionInfo sipTransactionInfo;
/*======================设备主子码流逻辑START=========================*/
/**
* 开启主子码流切换的开关(false-不开启,true-开启)
*/
private Boolean switchPrimarySubStream;
@Override
public Long getId() {
return id;
}
@Override
public void setId(Long id) {
this.id = id;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getFirmware() {
return firmware;
}
public void setFirmware(String firmware) {
this.firmware = firmware;
}
public String getTransport() {
return transport;
}
public void setTransport(String transport) {
this.transport = transport;
}
public String getStreamMode() {
return streamMode;
}
@JsonIgnore
public Integer getStreamModeForParam() {
if (streamMode == null) {
return 0;
}
if (streamMode.equalsIgnoreCase("UDP")) {
return 0;
}else if (streamMode.equalsIgnoreCase("TCP-PASSIVE")) {
return 1;
}else if (streamMode.equalsIgnoreCase("TCP-ACTIVE")) {
return 2;
}
return 0;
}
public void setStreamMode(String streamMode) {
this.streamMode = streamMode;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getHostAddress() {
return hostAddress;
}
public void setHostAddress(String hostAddress) {
this.hostAddress = hostAddress;
}
public Boolean isOnLine() {
return onLine;
}
public void setOnLine(Boolean onLine) {
this.onLine = onLine;
}
public Integer getChannelCount() {
return channelCount;
}
public void setChannelCount(Integer channelCount) {
this.channelCount = channelCount;
}
public String getRegisterTime() {
return registerTime;
}
public void setRegisterTime(String registerTime) {
this.registerTime = registerTime;
}
public String getKeepaliveTime() {
return keepaliveTime;
}
public void setKeepaliveTime(String keepaliveTime) {
this.keepaliveTime = keepaliveTime;
}
public Integer getExpires() {
return expires;
}
public void setExpires(Integer expires) {
this.expires = expires;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
public Integer getSubscribeCycleForCatalog() {
return subscribeCycleForCatalog;
}
public void setSubscribeCycleForCatalog(Integer subscribeCycleForCatalog) {
this.subscribeCycleForCatalog = subscribeCycleForCatalog;
}
public Integer getSubscribeCycleForMobilePosition() {
return subscribeCycleForMobilePosition;
}
public void setSubscribeCycleForMobilePosition(Integer subscribeCycleForMobilePosition) {
this.subscribeCycleForMobilePosition = subscribeCycleForMobilePosition;
}
public Integer getMobilePositionSubmissionInterval() {
return mobilePositionSubmissionInterval;
}
public void setMobilePositionSubmissionInterval(Integer mobilePositionSubmissionInterval) {
this.mobilePositionSubmissionInterval = mobilePositionSubmissionInterval;
}
public Integer getSubscribeCycleForAlarm() {
return subscribeCycleForAlarm;
}
public void setSubscribeCycleForAlarm(Integer subscribeCycleForAlarm) {
this.subscribeCycleForAlarm = subscribeCycleForAlarm;
}
public Boolean isSsrcCheck() {
return ssrcCheck;
}
public void setSsrcCheck(Boolean ssrcCheck) {
this.ssrcCheck = ssrcCheck;
}
public String getGeoCoordSys() {
return geoCoordSys;
}
public void setGeoCoordSys(String geoCoordSys) {
this.geoCoordSys = geoCoordSys;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSdpIp() {
return sdpIp;
}
public void setSdpIp(String sdpIp) {
this.sdpIp = sdpIp;
}
public String getLocalIp() {
return localIp;
}
public void setLocalIp(String localIp) {
this.localIp = localIp;
}
public Integer getKeepaliveIntervalTime() {
return keepaliveIntervalTime;
}
public void setKeepaliveIntervalTime(int keepaliveIntervalTime) {
this.keepaliveIntervalTime = keepaliveIntervalTime;
}
public Boolean isAsMessageChannel() {
return asMessageChannel;
}
public void setAsMessageChannel(Boolean asMessageChannel) {
this.asMessageChannel = asMessageChannel;
}
public SipTransactionInfo getSipTransactionInfo() {
return sipTransactionInfo;
}
public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
this.sipTransactionInfo = sipTransactionInfo;
}
public Boolean isSwitchPrimarySubStream() {
return switchPrimarySubStream;
}
public void setSwitchPrimarySubStream(Boolean switchPrimarySubStream) {
this.switchPrimarySubStream = switchPrimarySubStream;
}
/*======================设备主子码流逻辑END=========================*/
}
@@ -1,212 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* @author lin
*/
@TableName("wvp_device_alarm")
@Schema(description = "报警信息")
public class DeviceAlarm {
/**
* 数据库id
*/
@Schema(description = "数据库id")
private String id;
/**
* 设备Id
*/
@Schema(description = "设备的国标编号")
private String deviceId;
/**
* 通道Id
*/
@Schema(description = "通道的国标编号")
private String channelId;
/**
* 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情
*/
@Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情")
private String 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;
/**
* 报警时间
*/
@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;
@Schema(description = "创建时间")
private String createTime;
@TableField(exist = false)
private String startTime;
@TableField(exist = false)
private String endTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getAlarmPriority() {
return alarmPriority;
}
public void setAlarmPriority(String alarmPriority) {
this.alarmPriority = alarmPriority;
}
public String getAlarmMethod() {
return alarmMethod;
}
public void setAlarmMethod(String alarmMethod) {
this.alarmMethod = alarmMethod;
}
public String getAlarmTime() {
return alarmTime;
}
public void setAlarmTime(String alarmTime) {
this.alarmTime = alarmTime;
}
public String getAlarmDescription() {
return alarmDescription;
}
public void setAlarmDescription(String alarmDescription) {
this.alarmDescription = alarmDescription;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public String getAlarmType() {
return alarmType;
}
public void setAlarmType(String alarmType) {
this.alarmType = alarmType;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
@@ -1,54 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 报警方式
* @author lin
* 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
* 7其他报警;可以为直接组合如12为电话报警或 设备报警-
*/
public enum DeviceAlarmMethod {
// 1为电话报警
Telephone(1),
// 2为设备报警
Device(2),
// 3为短信报警
SMS(3),
// 4为 GPS报警
GPS(4),
// 5为视频报警
Video(5),
// 6为设备故障报警
DeviceFailure(6),
// 7其他报警
Other(7);
private final int val;
DeviceAlarmMethod(int val) {
this.val=val;
}
public int getVal() {
return val;
}
/**
* 查询是否匹配类型
* @param code
* @return
*/
public static DeviceAlarmMethod typeOf(int code) {
for (DeviceAlarmMethod item : DeviceAlarmMethod.values()) {
if (code==item.getVal()) {
return item;
}
}
return null;
}
}
@@ -1,563 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.iteaj.framework.Entity;
import io.swagger.v3.oas.annotations.media.Schema;
@TableName("wvp_device_channel")
@Schema(description = "通道信息")
public class DeviceChannel implements Entity<Long> {
/**
* 数据库自增ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 通道国标编号
*/
private String channelId;
/**
* 设备国标编号
*/
private String deviceId;
/**
* 通道名
*/
private String name;
/**
* 生产厂商
*/
private String manufacture;
/**
* 型号
*/
private String model;
/**
* 设备归属
*/
private String owner;
/**
* 行政区域
*/
private String civilCode;
/**
* 警区
*/
private String block;
/**
* 安装地址
*/
private String address;
/**
* 是否有子设备 1有, 0没有
*/
private Integer parental;
/**
* 父级id
*/
private String parentId;
/**
* 信令安全模式 缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式
*/
private Integer safetyWay;
/**
* 注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式
*/
private Integer registerWay;
/**
* 证书序列号
*/
private String certNum;
/**
* 证书有效标识 缺省为0;证书有效标识:0:无效1: 有效
*/
private Integer certifiable;
/**
* 证书无效原因码
*/
private Integer errCode;
/**
* 证书终止有效期
*/
private String endTime;
/**
* 保密属性 缺省为0; 0:不涉密, 1:涉密
*/
private String secrecy;
/**
* IP地址
*/
private String ipAddress;
/**
* 端口号
*/
private Integer port;
/**
* 密码
*/
private String password;
/**
* 云台类型
*/
private Integer ptzType;
private Integer customPtzType;
/**
* 云台类型描述字符串
*/
@TableField(exist = false)
private String ptzTypeText;
/**
* 创建时间
*/
private String createTime;
/**
* 更新时间
*/
private String updateTime;
/**
* 在线/离线
* 1在线,0离线
* 默认在线
* 信令:
* <Status>ON</Status>
* <Status>OFF</Status>
* 遇到过NVR下的IPC下发信令可以推流, 但是 Status 响应 OFF
*/
private Boolean status;
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* GCJ02坐标系经度
*/
private Double longitudeGcj02;
/**
* 纬度 GCJ02
*/
private Double latitudeGcj02;
/**
* 经度 WGS84
*/
private Double longitudeWgs84;
/**
* 纬度 WGS84
*/
private Double latitudeWgs84;
/**
* 子设备数
*/
private Integer subCount;
/**
* 流唯一编号,存在表示正在直播
*/
private String streamId;
/**
* 是否含有音频
*/
private Boolean hasAudio;
/**
* 标记通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
*/
@TableField(exist = false)
private Integer channelType;
/**
* 业务分组
*/
private String businessGroupId;
/**
* GPS的更新时间
*/
private String gpsTime;
@Override
public Long getId() {
return id;
}
@Override
public void setId(Long id) {
this.id = id;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
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;
}
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getManufacture() {
return manufacture;
}
public void setManufacture(String manufacture) {
this.manufacture = manufacture;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getCivilCode() {
return civilCode;
}
public void setCivilCode(String civilCode) {
this.civilCode = civilCode;
}
public String getBlock() {
return block;
}
public void setBlock(String block) {
this.block = block;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getParental() {
return parental;
}
public void setParental(Integer parental) {
this.parental = parental;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public Integer getSafetyWay() {
return safetyWay;
}
public void setSafetyWay(Integer safetyWay) {
this.safetyWay = safetyWay;
}
public Integer getRegisterWay() {
return registerWay;
}
public void setRegisterWay(Integer registerWay) {
this.registerWay = registerWay;
}
public String getCertNum() {
return certNum;
}
public void setCertNum(String certNum) {
this.certNum = certNum;
}
public Integer getCertifiable() {
return certifiable;
}
public void setCertifiable(Integer certifiable) {
this.certifiable = certifiable;
}
public Integer getErrCode() {
return errCode;
}
public void setErrCode(Integer errCode) {
this.errCode = errCode;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public String getSecrecy() {
return secrecy;
}
public void setSecrecy(String secrecy) {
this.secrecy = secrecy;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getPtzType() {
return ptzType;
}
public void setPtzType(Integer ptzType) {
this.ptzType = ptzType;
}
public Integer getCustomPtzType() {
return customPtzType;
}
public void setCustomPtzType(Integer customPtzType) {
this.customPtzType = customPtzType;
}
public String getPtzTypeText() {
return ptzTypeText;
}
public void setPtzTypeText(String ptzTypeText) {
this.ptzTypeText = ptzTypeText;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public Boolean isStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitudeGcj02() {
return longitudeGcj02;
}
public void setLongitudeGcj02(Double longitudeGcj02) {
this.longitudeGcj02 = longitudeGcj02;
}
public Double getLatitudeGcj02() {
return latitudeGcj02;
}
public void setLatitudeGcj02(Double latitudeGcj02) {
this.latitudeGcj02 = latitudeGcj02;
}
public Double getLongitudeWgs84() {
return longitudeWgs84;
}
public void setLongitudeWgs84(Double longitudeWgs84) {
this.longitudeWgs84 = longitudeWgs84;
}
public Double getLatitudeWgs84() {
return latitudeWgs84;
}
public void setLatitudeWgs84(Double latitudeWgs84) {
this.latitudeWgs84 = latitudeWgs84;
}
public Integer getSubCount() {
return subCount;
}
public void setSubCount(Integer subCount) {
this.subCount = subCount;
}
public String getStreamId() {
return streamId;
}
public void setStreamId(String streamId) {
this.streamId = streamId;
}
public Boolean isHasAudio() {
return hasAudio;
}
public void setHasAudio(Boolean hasAudio) {
this.hasAudio = hasAudio;
}
public Integer getChannelType() {
return channelType;
}
public void setChannelType(Integer channelType) {
this.channelType = channelType;
}
public String getBusinessGroupId() {
return businessGroupId;
}
public void setBusinessGroupId(String businessGroupId) {
this.businessGroupId = businessGroupId;
}
public String getGpsTime() {
return gpsTime;
}
public void setGpsTime(String gpsTime) {
this.gpsTime = gpsTime;
}
}
@@ -1,23 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class DeviceChannelInPlatform extends DeviceChannel{
private String platFormId;
private String catalogId;
public String getPlatFormId() {
return platFormId;
}
public void setPlatFormId(String platFormId) {
this.platFormId = platFormId;
}
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
}
@@ -1,27 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import javax.sip.Dialog;
import java.util.EventObject;
public class DeviceNotFoundEvent extends EventObject {
private String callId;
/**
* Constructs a prototypical Event.
*
* @param dialog
* @throws IllegalArgumentException if source is null.
*/
public DeviceNotFoundEvent(Dialog dialog) {
super(dialog);
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
}
@@ -1,143 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
/**
* 设备信息查询响应
*
* @author Y.G
* @version 1.0
* @date 2022/6/28 14:55
*/
public class DragZoomRequest {
/**
* 序列号
*/
@MessageElement("SN")
private String sn;
@MessageElement("DeviceID")
private String deviceId;
@MessageElement(value = "DragZoomIn")
private DragZoom dragZoomIn;
@MessageElement(value = "DragZoomOut")
private DragZoom dragZoomOut;
/**
* 基本参数
*/
public static class DragZoom {
/**
* 播放窗口长度像素值
*/
@MessageElement("Length")
protected Integer length;
/**
* 播放窗口宽度像素值
*/
@MessageElement("Width")
protected Integer width;
/**
* 拉框中心的横轴坐标像素值
*/
@MessageElement("MidPointX")
protected Integer midPointX;
/**
* 拉框中心的纵轴坐标像素值
*/
@MessageElement("MidPointY")
protected Integer midPointY;
/**
* 拉框长度像素值
*/
@MessageElement("LengthX")
protected Integer lengthX;
/**
* 拉框宽度像素值
*/
@MessageElement("LengthY")
protected Integer lengthY;
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getMidPointX() {
return midPointX;
}
public void setMidPointX(Integer midPointX) {
this.midPointX = midPointX;
}
public Integer getMidPointY() {
return midPointY;
}
public void setMidPointY(Integer midPointY) {
this.midPointY = midPointY;
}
public Integer getLengthX() {
return lengthX;
}
public void setLengthX(Integer lengthX) {
this.lengthX = lengthX;
}
public Integer getLengthY() {
return lengthY;
}
public void setLengthY(Integer lengthY) {
this.lengthY = lengthY;
}
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public DragZoom getDragZoomIn() {
return dragZoomIn;
}
public void setDragZoomIn(DragZoom dragZoomIn) {
this.dragZoomIn = dragZoomIn;
}
public DragZoom getDragZoomOut() {
return dragZoomOut;
}
public void setDragZoomOut(DragZoom dragZoomOut) {
this.dragZoomOut = dragZoomOut;
}
}
@@ -1,457 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.core.CommonLogger;
import gov.nist.core.Host;
import gov.nist.core.HostNameParser;
import gov.nist.core.StackLogger;
import gov.nist.javax.sip.SIPConstants;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.GenericURI;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.address.TelephoneNumber;
import gov.nist.javax.sip.header.*;
import gov.nist.javax.sip.message.SIPMessage;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.parser.*;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
public class GBStringMsgParser implements MessageParser {
protected static boolean computeContentLengthFromMessage = false;
private static StackLogger logger = CommonLogger.getLogger(StringMsgParser.class);
/**
* @since v0.9
*/
public GBStringMsgParser() {
super();
}
/**
* Parse a buffer containing a single SIP Message where the body is an array
* of un-interpreted bytes. This is intended for parsing the message from a
* memory buffer when the buffer. Incorporates a bug fix for a bug that was
* noted by Will Sullin of Callcast
*
* @param msgBuffer
* a byte buffer containing the messages to be parsed. This can
* consist of multiple SIP Messages concatenated together.
* @return a SIPMessage[] structure (request or response) containing the
* parsed SIP message.
* @exception ParseException
* is thrown when an illegal message has been encountered
* (and the rest of the buffer is discarded).
* @see ParseExceptionListener
*/
public SIPMessage parseSIPMessage(byte[] msgBuffer, boolean readBody, boolean strict, ParseExceptionListener parseExceptionListener) throws ParseException {
if (msgBuffer == null || msgBuffer.length == 0)
return null;
int i = 0;
// Squeeze out any leading control character.
try {
while (msgBuffer[i] < 0x20)
i++;
}
catch (ArrayIndexOutOfBoundsException e) {
// Array contains only control char, return null.
if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
logger.logDebug("handled only control char so returning null");
}
return null;
}
// Iterate thru the request/status line and headers.
String currentLine = null;
String currentHeader = null;
boolean isFirstLine = true;
SIPMessage message = null;
do
{
int lineStart = i;
// Find the length of the line.
try {
while (msgBuffer[i] != '\r' && msgBuffer[i] != '\n')
i++;
}
catch (ArrayIndexOutOfBoundsException e) {
// End of the message.
break;
}
int lineLength = i - lineStart;
// Make it a String.
try {
currentLine = new String(msgBuffer, lineStart, lineLength, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new ParseException("Bad message encoding!", 0);
}
currentLine = trimEndOfLine(currentLine);
if (currentLine.length() == 0) {
// Last header line, process the previous buffered header.
if (currentHeader != null && message != null) {
processHeader(currentHeader, message, parseExceptionListener, msgBuffer);
}
}
else {
if (isFirstLine) {
message = processFirstLine(currentLine, parseExceptionListener, msgBuffer);
} else {
char firstChar = currentLine.charAt(0);
if (firstChar == '\t' || firstChar == ' ') {
if (currentHeader == null)
throw new ParseException("Bad header continuation.", 0);
// This is a continuation, append it to the previous line.
currentHeader += currentLine.substring(1);
}
else {
if (currentHeader != null && message != null) {
processHeader(currentHeader, message, parseExceptionListener, msgBuffer);
}
currentHeader = currentLine;
}
}
}
if (msgBuffer[i] == '\r' && msgBuffer.length > i+1 && msgBuffer[i+1] == '\n')
i++;
i++;
isFirstLine = false;
} while (currentLine.length() > 0); // End do - while
if (message == null) throw new ParseException("Bad message", 0);
message.setSize(i);
// Check for content legth header
if (readBody && message.getContentLength() != null ) {
if ( message.getContentLength().getContentLength() != 0) {
int bodyLength = msgBuffer.length - i;
byte[] body = new byte[bodyLength];
System.arraycopy(msgBuffer, i, body, 0, bodyLength);
message.setMessageContent(body,!strict,computeContentLengthFromMessage,message.getContentLength().getContentLength());
} else if (message.getCSeqHeader().getMethod().equalsIgnoreCase("MESSAGE")) {
int bodyLength = msgBuffer.length - i;
byte[] body = new byte[bodyLength];
System.arraycopy(msgBuffer, i, body, 0, bodyLength);
message.setMessageContent(body,!strict,computeContentLengthFromMessage,bodyLength);
}else if (!computeContentLengthFromMessage && strict) {
String last4Chars = new String(msgBuffer, msgBuffer.length - 4, 4);
if(!"\r\n\r\n".equals(last4Chars)) {
throw new ParseException("Extraneous characters at the end of the message ",i);
}
}
}
return message;
}
protected static String trimEndOfLine(String line) {
if (line == null)
return line;
int i = line.length() - 1;
while (i >= 0 && line.charAt(i) <= 0x20)
i--;
if (i == line.length() - 1)
return line;
if (i == -1)
return "";
return line.substring(0, i+1);
}
protected SIPMessage processFirstLine(String firstLine, ParseExceptionListener parseExceptionListener, byte[] msgBuffer) throws ParseException {
SIPMessage message;
if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) {
message = new SIPRequest();
try {
RequestLine requestLine = new RequestLineParser(firstLine + "\n")
.parse();
((SIPRequest) message).setRequestLine(requestLine);
} catch (ParseException ex) {
if (parseExceptionListener != null)
try {
parseExceptionListener.handleException(ex, message,
RequestLine.class, firstLine, new String(msgBuffer, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
else
throw ex;
}
} else {
message = new SIPResponse();
try {
StatusLine sl = new StatusLineParser(firstLine + "\n").parse();
((SIPResponse) message).setStatusLine(sl);
} catch (ParseException ex) {
if (parseExceptionListener != null) {
try {
parseExceptionListener.handleException(ex, message,
StatusLine.class, firstLine, new String(msgBuffer, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else
throw ex;
}
}
return message;
}
protected void processHeader(String header, SIPMessage message, ParseExceptionListener parseExceptionListener, byte[] rawMessage) throws ParseException {
if (header == null || header.length() == 0)
return;
HeaderParser headerParser = null;
try {
headerParser = ParserFactory.createParser(header + "\n");
} catch (ParseException ex) {
// https://java.net/jira/browse/JSIP-456
if (parseExceptionListener != null) {
parseExceptionListener.handleException(ex, message, null,
header, null);
return;
} else {
throw ex;
}
}
try {
SIPHeader sipHeader = headerParser.parse();
message.attachHeader(sipHeader, false);
} catch (ParseException ex) {
if (parseExceptionListener != null) {
String headerName = Lexer.getHeaderName(header);
Class headerClass = NameMap.getClassFromName(headerName);
if (headerClass == null) {
headerClass = ExtensionHeaderImpl.class;
}
try {
parseExceptionListener.handleException(ex, message,
headerClass, header, new String(rawMessage, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
/**
* Parse an address (nameaddr or address spec) and return and address
* structure.
*
* @param address
* is a String containing the address to be parsed.
* @return a parsed address structure.
* @since v1.0
* @exception ParseException
* when the address is badly formatted.
*/
public AddressImpl parseAddress(String address) throws ParseException {
AddressParser addressParser = new AddressParser(address);
return addressParser.address(true);
}
/**
* Parse a host:port and return a parsed structure.
*
* @param hostport
* is a String containing the host:port to be parsed
* @return a parsed address structure.
* @since v1.0
* @exception throws
* a ParseException when the address is badly formatted.
*
public HostPort parseHostPort(String hostport) throws ParseException {
Lexer lexer = new Lexer("charLexer", hostport);
return new HostNameParser(lexer).hostPort();
}
*/
/**
* Parse a host name and return a parsed structure.
*
* @param host
* is a String containing the host name to be parsed
* @return a parsed address structure.
* @since v1.0
* @exception ParseException
* a ParseException when the hostname is badly formatted.
*/
public Host parseHost(String host) throws ParseException {
Lexer lexer = new Lexer("charLexer", host);
return new HostNameParser(lexer).host();
}
/**
* Parse a telephone number return a parsed structure.
*
* @param telephone_number
* is a String containing the telephone # to be parsed
* @return a parsed address structure.
* @since v1.0
* @exception ParseException
* a ParseException when the address is badly formatted.
*/
public TelephoneNumber parseTelephoneNumber(String telephone_number)
throws ParseException {
// Bug fix contributed by Will Scullin
return new URLParser(telephone_number).parseTelephoneNumber(true);
}
/**
* Parse a SIP url from a string and return a URI structure for it.
*
* @param url
* a String containing the URI structure to be parsed.
* @return A parsed URI structure
* @exception ParseException
* if there was an error parsing the message.
*/
public SipUri parseSIPUrl(String url) throws ParseException {
try {
return new URLParser(url).sipURL(true);
} catch (ClassCastException ex) {
throw new ParseException(url + " Not a SIP URL ", 0);
}
}
/**
* Parse a uri from a string and return a URI structure for it.
*
* @param url
* a String containing the URI structure to be parsed.
* @return A parsed URI structure
* @exception ParseException
* if there was an error parsing the message.
*/
public GenericURI parseUrl(String url) throws ParseException {
return new URLParser(url).parse();
}
/**
* Parse an individual SIP message header from a string.
*
* @param header
* String containing the SIP header.
* @return a SIPHeader structure.
* @exception ParseException
* if there was an error parsing the message.
*/
public static SIPHeader parseSIPHeader(String header) throws ParseException {
int start = 0;
int end = header.length() - 1;
try {
// Squeeze out any leading control character.
while (header.charAt(start) <= 0x20)
start++;
// Squeeze out any trailing control character.
while (header.charAt(end) <= 0x20)
end--;
}
catch (ArrayIndexOutOfBoundsException e) {
// Array contains only control char.
throw new ParseException("Empty header.", 0);
}
StringBuilder buffer = new StringBuilder(end + 1);
int i = start;
int lineStart = start;
boolean endOfLine = false;
while (i <= end) {
char c = header.charAt(i);
if (c == '\r' || c == '\n') {
if (!endOfLine) {
buffer.append(header.substring(lineStart, i));
endOfLine = true;
}
}
else {
if (endOfLine) {
endOfLine = false;
if (c == ' ' || c == '\t') {
buffer.append(' ');
lineStart = i + 1;
}
else {
lineStart = i;
}
}
}
i++;
}
buffer.append(header.substring(lineStart, i));
buffer.append('\n');
HeaderParser hp = ParserFactory.createParser(buffer.toString());
if (hp == null)
throw new ParseException("could not create parser", 0);
return hp.parse();
}
/**
* Parse the SIP Request Line
*
* @param requestLine
* a String containing the request line to be parsed.
* @return a RequestLine structure that has the parsed RequestLine
* @exception ParseException
* if there was an error parsing the requestLine.
*/
public RequestLine parseSIPRequestLine(String requestLine)
throws ParseException {
requestLine += "\n";
return new RequestLineParser(requestLine).parse();
}
/**
* Parse the SIP Response message status line
*
* @param statusLine
* a String containing the Status line to be parsed.
* @return StatusLine class corresponding to message
* @exception ParseException
* if there was an error parsing
* @see StatusLine
*/
public StatusLine parseSIPStatusLine(String statusLine)
throws ParseException {
statusLine += "\n";
return new StatusLineParser(statusLine).parse();
}
public static void setComputeContentLengthFromMessage(
boolean computeContentLengthFromMessage) {
GBStringMsgParser.computeContentLengthFromMessage = computeContentLengthFromMessage;
}
}
@@ -1,46 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import javax.sdp.SessionDescription;
/**
* 28181 的SDP解析器
*/
public class Gb28181Sdp {
private SessionDescription baseSdb;
private String ssrc;
private String mediaDescription;
public static Gb28181Sdp getInstance(SessionDescription baseSdb, String ssrc, String mediaDescription) {
Gb28181Sdp gb28181Sdp = new Gb28181Sdp();
gb28181Sdp.setBaseSdb(baseSdb);
gb28181Sdp.setSsrc(ssrc);
gb28181Sdp.setMediaDescription(mediaDescription);
return gb28181Sdp;
}
public SessionDescription getBaseSdb() {
return baseSdb;
}
public void setBaseSdb(SessionDescription baseSdb) {
this.baseSdb = baseSdb;
}
public String getSsrc() {
return ssrc;
}
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
public String getMediaDescription() {
return mediaDescription;
}
public void setMediaDescription(String mediaDescription) {
this.mediaDescription = mediaDescription;
}
}
@@ -1,149 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.core.InternalErrorHandler;
import gov.nist.javax.sip.header.SIPDate;
import java.util.*;
/**
* 重写jain sip的SIPDate解决与国标时间格式不一致的问题
*/
public class GbSipDate extends SIPDate {
/**
*
*/
private static final long serialVersionUID = 1L;
private Calendar javaCal;
public GbSipDate(long timeMillis) {
this.javaCal = new GregorianCalendar(TimeZone.getDefault(), Locale.getDefault());
Date date = new Date(timeMillis);
this.javaCal.setTime(date);
this.wkday = this.javaCal.get(7);
switch(this.wkday) {
case 1:
this.sipWkDay = "Sun";
break;
case 2:
this.sipWkDay = "Mon";
break;
case 3:
this.sipWkDay = "Tue";
break;
case 4:
this.sipWkDay = "Wed";
break;
case 5:
this.sipWkDay = "Thu";
break;
case 6:
this.sipWkDay = "Fri";
break;
case 7:
this.sipWkDay = "Sat";
break;
default:
InternalErrorHandler.handleException("No date map for wkday " + this.wkday);
}
this.day = this.javaCal.get(5);
this.month = this.javaCal.get(2);
switch(this.month) {
case 0:
this.sipMonth = "Jan";
break;
case 1:
this.sipMonth = "Feb";
break;
case 2:
this.sipMonth = "Mar";
break;
case 3:
this.sipMonth = "Apr";
break;
case 4:
this.sipMonth = "May";
break;
case 5:
this.sipMonth = "Jun";
break;
case 6:
this.sipMonth = "Jul";
break;
case 7:
this.sipMonth = "Aug";
break;
case 8:
this.sipMonth = "Sep";
break;
case 9:
this.sipMonth = "Oct";
break;
case 10:
this.sipMonth = "Nov";
break;
case 11:
this.sipMonth = "Dec";
break;
default:
InternalErrorHandler.handleException("No date map for month " + this.month);
}
this.year = this.javaCal.get(1);
this.hour = this.javaCal.get(11);
this.minute = this.javaCal.get(12);
this.second = this.javaCal.get(13);
}
@Override
public StringBuilder encode(StringBuilder var1) {
String var2;
if (this.month < 9) {
var2 = "0" + (this.month + 1);
} else {
var2 = "" + (this.month + 1);
}
String var3;
if (this.day < 10) {
var3 = "0" + this.day;
} else {
var3 = "" + this.day;
}
String var4;
if (this.hour < 10) {
var4 = "0" + this.hour;
} else {
var4 = "" + this.hour;
}
String var5;
if (this.minute < 10) {
var5 = "0" + this.minute;
} else {
var5 = "" + this.minute;
}
String var6;
if (this.second < 10) {
var6 = "0" + this.second;
} else {
var6 = "" + this.second;
}
int var8 = this.javaCal.get(14);
String var7;
if (var8 < 10) {
var7 = "00" + var8;
} else if (var8 < 100) {
var7 = "0" + var8;
} else {
var7 = "" + var8;
}
return var1.append(this.year).append("-").append(var2).append("-").append(var3).append("T").append(var4).append(":").append(var5).append(":").append(var6).append(".").append(var7);
}
}
@@ -1,135 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 直播流关联国标上级平台
* @author lin
*/
@TableName("wvp_gb_stream")
@Schema(description = "直播流关联国标上级平台")
public class GbStream extends PlatformGbStream {
@Schema(description = "应用名")
private String app;
@Schema(description = "流ID")
private String stream;
@Schema(description = "国标ID")
private String gbId;
@Schema(description = "名称")
private String name;
@Schema(description = "流媒体ID")
private String mediaServerId;
@Schema(description = "经度")
private double longitude;
@Schema(description = "纬度")
private double latitude;
@Schema(description = "流类型(拉流/推流)")
private String streamType;
@Schema(description = "状态")
private Boolean status;
@Schema(description = "创建时间")
private String createTime;
@TableField(exist = false)
private String query;
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public String getGbId() {
return gbId;
}
public void setGbId(String gbId) {
this.gbId = gbId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public String getStreamType() {
return streamType;
}
public void setStreamType(String streamType) {
this.streamType = streamType;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
}
@@ -1,22 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.javax.sip.parser.MessageParser;
import gov.nist.javax.sip.parser.MessageParserFactory;
import gov.nist.javax.sip.stack.SIPTransactionStack;
public class GbStringMsgParserFactory implements MessageParserFactory {
/**
* msg parser is completely stateless, reuse isntance for the whole stack
* fixes https://github.com/RestComm/jain-sip/issues/92
*/
private static GBStringMsgParser msgParser = new GBStringMsgParser();
/*
* (non-Javadoc)
* @see gov.nist.javax.sip.parser.MessageParserFactory#createMessageParser(gov.nist.javax.sip.stack.SIPTransactionStack)
*/
@Override
public MessageParser createMessageParser(SIPTransactionStack stack) {
return msgParser;
}
}
@@ -1,44 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import org.dom4j.Element;
import javax.sip.RequestEvent;
/**
* @author lin
*/
public class HandlerCatchData {
private RequestEvent evt;
private Device device;
private Element rootElement;
public HandlerCatchData(RequestEvent evt, Device device, Element rootElement) {
this.evt = evt;
this.device = device;
this.rootElement = rootElement;
}
public RequestEvent getEvt() {
return evt;
}
public void setEvt(RequestEvent evt) {
this.evt = evt;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public Element getRootElement() {
return rootElement;
}
public void setRootElement(Element rootElement) {
this.rootElement = rootElement;
}
}
@@ -1,94 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
/**
* 设备信息查询响应
*
* @author Y.G
* @version 1.0
* @date 2022/6/28 14:55
*/
public class HomePositionRequest {
/**
* 序列号
*/
@MessageElement("SN")
private String sn;
@MessageElement("DeviceID")
private String deviceId;
@MessageElement(value = "HomePosition")
private HomePosition homePosition;
/**
* 基本参数
*/
public static class HomePosition {
/**
* 播放窗口长度像素值
*/
@MessageElement("Enabled")
protected String enabled;
/**
* 播放窗口宽度像素值
*/
@MessageElement("ResetTime")
protected String resetTime;
/**
* 拉框中心的横轴坐标像素值
*/
@MessageElement("PresetIndex")
protected String presetIndex;
public String getEnabled() {
return enabled;
}
public void setEnabled(String enabled) {
this.enabled = enabled;
}
public String getResetTime() {
return resetTime;
}
public void setResetTime(String resetTime) {
this.resetTime = resetTime;
}
public String getPresetIndex() {
return presetIndex;
}
public void setPresetIndex(String presetIndex) {
this.presetIndex = presetIndex;
}
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public HomePosition getHomePosition() {
return homePosition;
}
public void setHomePosition(HomePosition homePosition) {
this.homePosition = homePosition;
}
}
@@ -1,35 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class Host {
private String ip;
private int port;
private String address;
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
@@ -1,5 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public interface InviteStreamCallback {
void call(InviteStreamInfo inviteStreamInfo);
}
@@ -1,61 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
public class InviteStreamInfo {
public InviteStreamInfo(MediaServerItem mediaServerItem, JSONObject response, String callId, String app, String stream) {
this.mediaServerItem = mediaServerItem;
this.response = response;
this.callId = callId;
this.app = app;
this.stream = stream;
}
private MediaServerItem mediaServerItem;
private JSONObject response;
private String callId;
private String app;
private String stream;
public MediaServerItem getMediaServerItem() {
return mediaServerItem;
}
public void setMediaServerItem(MediaServerItem mediaServerItem) {
this.mediaServerItem = mediaServerItem;
}
public JSONObject getResponse() {
return response;
}
public void setResponse(JSONObject response) {
this.response = response;
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
}
@@ -1,8 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public enum InviteStreamType {
PLAY,PLAYBACK,DOWNLOAD,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY
}
@@ -1,220 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.TableName;
import com.iteaj.framework.Entity;
/**
* @description: 移动位置bean
* @author: lawrencehj
* @date: 2021年1月23日
*/
@TableName("wvp_device_mobile_position")
public class MobilePosition implements Entity<Long> {
private Long id;
/**
* 设备Id
*/
private String deviceId;
/**
* 通道Id
*/
private String channelId;
/**
* 设备名称
*/
private String deviceName;
/**
* 通知时间
*/
private String time;
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* 海拔高度
*/
private Double altitude;
/**
* 速度
*/
private Double speed;
/**
* 方向
*/
private Double direction;
/**
* 位置信息上报来源(Mobile Position、GPS Alarm
*/
private String reportSource;
/**
* 国内坐标系:经度坐标
*/
private Double longitudeGcj02;
/**
* 国内坐标系:纬度坐标
*/
private Double latitudeGcj02;
/**
* 国内坐标系:经度坐标
*/
private Double longitudeWgs84;
/**
* 国内坐标系:纬度坐标
*/
private Double latitudeWgs84;
/**
* 创建时间
*/
private String createTime;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getAltitude() {
return altitude;
}
public void setAltitude(Double altitude) {
this.altitude = altitude;
}
public Double getSpeed() {
return speed;
}
public void setSpeed(Double speed) {
this.speed = speed;
}
public Double getDirection() {
return direction;
}
public void setDirection(Double direction) {
this.direction = direction;
}
public String getReportSource() {
return reportSource;
}
public void setReportSource(String reportSource) {
this.reportSource = reportSource;
}
public Double getLongitudeGcj02() {
return longitudeGcj02;
}
public void setLongitudeGcj02(Double longitudeGcj02) {
this.longitudeGcj02 = longitudeGcj02;
}
public Double getLatitudeGcj02() {
return latitudeGcj02;
}
public void setLatitudeGcj02(Double latitudeGcj02) {
this.latitudeGcj02 = latitudeGcj02;
}
public Double getLongitudeWgs84() {
return longitudeWgs84;
}
public void setLongitudeWgs84(Double longitudeWgs84) {
this.longitudeWgs84 = longitudeWgs84;
}
public Double getLatitudeWgs84() {
return latitudeWgs84;
}
public void setLatitudeWgs84(Double latitudeWgs84) {
this.latitudeWgs84 = latitudeWgs84;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
@Override
public Long getId() {
return null;
}
@Override
public void setId(Long id) {
this.id = id;
}
}
@@ -1,452 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* @author lin
*/
@TableName("wvp_platform")
@Schema(description = "平台信息")
public class ParentPlatform {
/**
* id
*/
@Schema(description = "ID(数据库中)")
private Integer id;
/**
* 是否启用
*/
@Schema(description = "是否启用")
private Boolean enable;
/**
* 名称
*/
@Schema(description = "名称")
private String name;
/**
* SIP服务国标编码
*/
@Schema(description = "SIP服务国标编码")
@TableField("server_gb_id")
private String serverGBId;
/**
* SIP服务国标域
*/
@Schema(description = "SIP服务国标域")
@TableField("server_gb_domain")
private String serverGBDomain;
/**
* SIP服务IP
*/
@Schema(description = "SIP服务IP")
private String serverIp;
/**
* SIP服务端口
*/
@Schema(description = "SIP服务端口")
private Integer serverPort;
/**
* 设备国标编号
*/
@Schema(description = "设备国标编号")
@TableField("device_gb_id")
private String deviceGBId;
/**
* 设备ip
*/
@Schema(description = "设备ip")
private String deviceIp;
/**
* 设备端口
*/
@Schema(description = "设备端口")
private String devicePort;
/**
* SIP认证用户名(默认使用设备国标编号)
*/
@Schema(description = "SIP认证用户名(默认使用设备国标编号)")
private String username;
/**
* SIP认证密码
*/
@Schema(description = "SIP认证密码")
private String password;
/**
* 注册周期 (秒)
*/
@Schema(description = "注册周期 (秒)")
private Integer expires;
/**
* 心跳周期(秒)
*/
@Schema(description = "心跳周期(秒)")
private Integer keepTimeout;
/**
* 传输协议
* UDP/TCP
*/
@Schema(description = "传输协议")
private String transport;
/**
* 字符集
*/
@Schema(description = "字符集")
private String characterSet;
/**
* 允许云台控制
*/
@Schema(description = "允许云台控制")
private Boolean ptz;
/**
* RTCP流保活
*/
@Schema(description = "RTCP流保活")
private Boolean rtcp;
/**
* 在线状态
*/
@Schema(description = "在线状态")
private Boolean status;
/**
* 在线状态
*/
@TableField(exist = false)
@Schema(description = "通道数量")
private Integer channelCount;
/**
* 默认目录Id,自动添加的通道多放在这个目录下
*/
@Schema(description = "默认目录Id,自动添加的通道多放在这个目录下")
private String catalogId;
/**
* 已被订阅目录信息
*/
@TableField(exist = false)
@Schema(description = "已被订阅目录信息")
private Boolean catalogSubscribe;
/**
* 已被订阅报警信息
*/
@TableField(exist = false)
@Schema(description = "已被订阅报警信息")
private Boolean alarmSubscribe;
/**
* 已被订阅移动位置信息
*/
@TableField(exist = false)
@Schema(description = "已被订阅移动位置信息")
private Boolean mobilePositionSubscribe;
/**
* 点播未推流的设备时是否使用redis通知拉起
*/
@Schema(description = "点播未推流的设备时是否使用redis通知拉起")
private Boolean startOfflinePush;
/**
* 目录分组-每次向上级发送通道信息时单个包携带的通道数量,取值1,2,4,8
*/
@Schema(description = "目录分组-每次向上级发送通道信息时单个包携带的通道数量,取值1,2,4,8")
private Integer catalogGroup;
/**
* 行政区划
*/
@Schema(description = "行政区划")
private String administrativeDivision;
/**
* 更新时间
*/
@Schema(description = "更新时间")
private String updateTime;
/**
* 创建时间
*/
@Schema(description = "创建时间")
private String createTime;
@Schema(description = "是否作为消息通道")
private Boolean asMessageChannel;
@Schema(description = "是否作为消息通道")
private Boolean autoPushChannel;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Boolean isEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getServerGBId() {
return serverGBId;
}
public void setServerGBId(String serverGBId) {
this.serverGBId = serverGBId;
}
public String getServerGBDomain() {
return serverGBDomain;
}
public void setServerGBDomain(String serverGBDomain) {
this.serverGBDomain = serverGBDomain;
}
public int getServerPort() {
return serverPort;
}
public void setServerPort(int serverPort) {
this.serverPort = serverPort;
}
public String getDeviceGBId() {
return deviceGBId;
}
public void setDeviceGBId(String deviceGBId) {
this.deviceGBId = deviceGBId;
}
public String getDeviceIp() {
return deviceIp;
}
public void setDeviceIp(String deviceIp) {
this.deviceIp = deviceIp;
}
public String getDevicePort() {
return devicePort;
}
public void setDevicePort(String devicePort) {
this.devicePort = devicePort;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getExpires() {
return expires;
}
public void setExpires(int expires) {
this.expires = expires;
}
public int getKeepTimeout() {
return keepTimeout;
}
public void setKeepTimeout(int keepTimeout) {
this.keepTimeout = keepTimeout;
}
public String getTransport() {
return transport;
}
public void setTransport(String transport) {
this.transport = transport;
}
public String getCharacterSet() {
return characterSet;
}
public void setCharacterSet(String characterSet) {
this.characterSet = characterSet;
}
public Boolean isPtz() {
return ptz;
}
public void setPtz(Boolean ptz) {
this.ptz = ptz;
}
public Boolean isRtcp() {
return rtcp;
}
public void setRtcp(Boolean rtcp) {
this.rtcp = rtcp;
}
public Boolean isStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public int getChannelCount() {
return channelCount;
}
public void setChannelCount(int channelCount) {
this.channelCount = channelCount;
}
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
public Boolean isCatalogSubscribe() {
return catalogSubscribe;
}
public void setCatalogSubscribe(Boolean catalogSubscribe) {
this.catalogSubscribe = catalogSubscribe;
}
public Boolean isAlarmSubscribe() {
return alarmSubscribe;
}
public void setAlarmSubscribe(Boolean alarmSubscribe) {
this.alarmSubscribe = alarmSubscribe;
}
public Boolean isMobilePositionSubscribe() {
return mobilePositionSubscribe;
}
public void setMobilePositionSubscribe(Boolean mobilePositionSubscribe) {
this.mobilePositionSubscribe = mobilePositionSubscribe;
}
public Boolean isStartOfflinePush() {
return startOfflinePush;
}
public void setStartOfflinePush(Boolean startOfflinePush) {
this.startOfflinePush = startOfflinePush;
}
public int getCatalogGroup() {
return catalogGroup;
}
public void setCatalogGroup(int catalogGroup) {
this.catalogGroup = catalogGroup;
}
public String getAdministrativeDivision() {
return administrativeDivision;
}
public void setAdministrativeDivision(String administrativeDivision) {
this.administrativeDivision = administrativeDivision;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public Boolean isAsMessageChannel() {
return asMessageChannel;
}
public void setAsMessageChannel(Boolean asMessageChannel) {
this.asMessageChannel = asMessageChannel;
}
public Boolean isAutoPushChannel() {
return autoPushChannel;
}
public void setAutoPushChannel(Boolean autoPushChannel) {
this.autoPushChannel = autoPushChannel;
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
}
@@ -1,68 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class ParentPlatformCatch {
private String id;
/**
* 心跳未回复次数
*/
private int keepAliveReply;
// 注册未回复次数
private int registerAliveReply;
private String callId;
private ParentPlatform parentPlatform;
private SipTransactionInfo sipTransactionInfo;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getKeepAliveReply() {
return keepAliveReply;
}
public void setKeepAliveReply(int keepAliveReply) {
this.keepAliveReply = keepAliveReply;
}
public int getRegisterAliveReply() {
return registerAliveReply;
}
public void setRegisterAliveReply(int registerAliveReply) {
this.registerAliveReply = registerAliveReply;
}
public ParentPlatform getParentPlatform() {
return parentPlatform;
}
public void setParentPlatform(ParentPlatform parentPlatform) {
this.parentPlatform = parentPlatform;
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
public SipTransactionInfo getSipTransactionInfo() {
return sipTransactionInfo;
}
public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
this.sipTransactionInfo = sipTransactionInfo;
}
}
@@ -1,122 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 国标级联-目录
* @author lin
*/
@TableName("wvp_platform_catalog")
@Schema(description = "目录信息")
public class PlatformCatalog {
@Schema(description = "ID")
private String id;
@Schema(description = "名称")
private String name;
@Schema(description = "平台ID")
private String platformId;
@Schema(description = "父级目录ID")
private String parentId;
@Schema(description = "行政区划")
private String civilCode;
@Schema(description = "目录分组")
private String businessGroupId;
/**
* 子节点数
*/
@TableField(exist = false)
@Schema(description = "子节点数")
private int childrenCount;
/**
* 0 目录, 1 国标通道, 2 直播流
*/
@TableField(exist = false)
@Schema(description = "类型:0 目录, 1 国标通道, 2 直播流")
private int type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPlatformId() {
return platformId;
}
public void setPlatformId(String platformId) {
this.platformId = platformId;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public int getChildrenCount() {
return childrenCount;
}
public void setChildrenCount(int childrenCount) {
this.childrenCount = childrenCount;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setTypeForCatalog() {
this.type = 0;
}
public void setTypeForGb() {
this.type = 1;
}
public void setTypeForStream() {
this.type = 2;
}
public String getCivilCode() {
return civilCode;
}
public void setCivilCode(String civilCode) {
this.civilCode = civilCode;
}
public String getBusinessGroupId() {
return businessGroupId;
}
public void setBusinessGroupId(String businessGroupId) {
this.businessGroupId = businessGroupId;
}
}
@@ -1,44 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
@TableName("wvp_platform_gb_stream")
public class PlatformGbStream {
@TableId(type = IdType.AUTO)
@Schema(description = "ID")
private Integer gbStreamId;
@Schema(description = "平台ID")
private String platformId;
@Schema(description = "目录ID")
private String catalogId;
public Integer getGbStreamId() {
return gbStreamId;
}
public void setGbStreamId(Integer gbStreamId) {
this.gbStreamId = gbStreamId;
}
public String getPlatformId() {
return platformId;
}
public void setPlatformId(String platformId) {
this.platformId = platformId;
}
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
}
@@ -1,15 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class PlatformRegister {
// 未回复次数
private int reply;
public int getReply() {
return reply;
}
public void setReply(int reply) {
this.reply = reply;
}
}
@@ -1,28 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* @author chenjialing
*/
public class PresetQuerySipReq {
private String presetId;
private String presetName;
public String getPresetId() {
return presetId;
}
public void setPresetId(String presetId) {
this.presetId = presetId;
}
public String getPresetName() {
return presetName;
}
public void setPresetName(String presetName) {
this.presetName = presetName;
}
}
@@ -1,102 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Instant;
import java.util.List;
/**
* @description:设备录像信息bean
* @author: swwheihei
* @date: 2020年5月8日 下午2:05:56
*/
@Schema(description = "设备录像查询结果信息")
public class RecordInfo {
@Schema(description = "设备编号")
private String deviceId;
@Schema(description = "通道编号")
private String channelId;
@Schema(description = "命令序列号")
private String sn;
@Schema(description = "设备名称")
private String name;
@Schema(description = "列表总数")
private int sumNum;
private int count;
private Instant lastTime;
@Schema(description = "")
private List<RecordItem> recordList;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSumNum() {
return sumNum;
}
public void setSumNum(int sumNum) {
this.sumNum = sumNum;
}
public List<RecordItem> getRecordList() {
return recordList;
}
public void setRecordList(List<RecordItem> recordList) {
this.recordList = recordList;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public Instant getLastTime() {
return lastTime;
}
public void setLastTime(Instant lastTime) {
this.lastTime = lastTime;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
@@ -1,144 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.utils.DateUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.time.temporal.TemporalAccessor;
/**
* @description:设备录像bean
* @author: swwheihei
* @date: 2020年5月8日 下午2:06:54
*/
@Schema(description = "设备录像详情")
public class RecordItem implements Comparable<RecordItem>{
@Schema(description = "设备编号")
private String deviceId;
@Schema(description = "名称")
private String name;
@Schema(description = "文件路径名 (可选)")
private String filePath;
@Schema(description = "录像文件大小,单位:Byte(可选)")
private String fileSize;
@Schema(description = "录像地址(可选)")
private String address;
@Schema(description = "录像开始时间(可选)")
private String startTime;
@Schema(description = "录像结束时间(可选)")
private String endTime;
@Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
private int secrecy;
@Schema(description = "录像产生类型(可选)time或alarm 或 manua")
private String type;
@Schema(description = "录像触发者ID(可选)")
private String recorderId;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public int getSecrecy() {
return secrecy;
}
public void setSecrecy(int secrecy) {
this.secrecy = secrecy;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRecorderId() {
return recorderId;
}
public void setRecorderId(String recorderId) {
this.recorderId = recorderId;
}
public String getFileSize() {
return fileSize;
}
public void setFileSize(String fileSize) {
this.fileSize = fileSize;
}
@Override
public int compareTo(@NotNull RecordItem recordItem) {
TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime);
TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime());
Instant startTimeParamInstant = Instant.from(startTimeParam);
Instant startTimeNowInstant = Instant.from(startTimeNow);
if (startTimeNowInstant.equals(startTimeParamInstant)) {
return 0;
}else if (Instant.from(startTimeParam).isAfter(Instant.from(startTimeNow)) ) {
return -1;
}else {
return 1;
}
}
}
@@ -1,27 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class RemoteAddressInfo {
private String ip;
private int port;
public RemoteAddressInfo(String ip, int port) {
this.ip = ip;
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
@@ -1,14 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import javax.sdp.SessionDescription;
public class SDPInfo {
private byte[] source;
private SessionDescription sdpSource;
private String sessionName;
private Long startTime;
private Long stopTime;
private String username;
private String address;
private String ssrc;
}
@@ -1,295 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class SendRtpItem {
/**
* 推流ip
*/
private String ip;
/**
* 推流端口
*/
private int port;
/**
* 推流标识
*/
private String ssrc;
/**
* 平台id
*/
private String platformId;
/**
* 对应设备id
*/
private String deviceId;
/**
* 直播流的应用名
*/
private String app;
/**
* 通道id
*/
private String channelId;
/**
* 推流状态
* 0 等待设备推流上来
* 1 等待上级平台回复ack
* 2 推流中
*/
private int status = 0;
/**
* 设备推流的streamId
*/
private String streamId;
/**
* 是否为tcp
*/
private boolean tcp;
/**
* 是否为tcp主动模式
*/
private boolean tcpActive;
/**
* 自己推流使用的端口
*/
private int localPort;
/**
* 使用的流媒体
*/
private String mediaServerId;
/**
* 使用的服务的ID
*/
private String serverId;
/**
* invite 的 callId
*/
private String CallId;
/**
* invite 的 fromTag
*/
private String fromTag;
/**
* invite 的 toTag
*/
private String toTag;
/**
* 发送时,rtp的ptuint8_t,不传时默认为96
*/
private int pt = 96;
/**
* 发送时,rtp的负载类型。为true时,负载为ps;为false时,为es;
*/
private boolean usePs = true;
/**
* 当usePs 为false时,有效。为1时,发送音频;为0时,发送视频;不传时默认为0
*/
private boolean onlyAudio = false;
/**
* 是否开启rtcp保活
*/
private boolean rtcp = false;
/**
* 播放类型
*/
private InviteStreamType playType;
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;
}
public String getSsrc() {
return ssrc;
}
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
public String getPlatformId() {
return platformId;
}
public void setPlatformId(String platformId) {
this.platformId = platformId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getApp() {
return app;
}
public void setApp(String app) {
this.app = app;
}
public String getStreamId() {
return streamId;
}
public void setStreamId(String streamId) {
this.streamId = streamId;
}
public boolean isTcp() {
return tcp;
}
public void setTcp(boolean tcp) {
this.tcp = tcp;
}
public int getLocalPort() {
return localPort;
}
public void setLocalPort(int localPort) {
this.localPort = localPort;
}
public boolean isTcpActive() {
return tcpActive;
}
public void setTcpActive(boolean tcpActive) {
this.tcpActive = tcpActive;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public String getCallId() {
return CallId;
}
public void setCallId(String callId) {
CallId = callId;
}
public InviteStreamType getPlayType() {
return playType;
}
public void setPlayType(InviteStreamType playType) {
this.playType = playType;
}
public int getPt() {
return pt;
}
public void setPt(int pt) {
this.pt = pt;
}
public boolean isUsePs() {
return usePs;
}
public void setUsePs(boolean usePs) {
this.usePs = usePs;
}
public boolean isOnlyAudio() {
return onlyAudio;
}
public void setOnlyAudio(boolean onlyAudio) {
this.onlyAudio = onlyAudio;
}
public String getServerId() {
return serverId;
}
public void setServerId(String serverId) {
this.serverId = serverId;
}
public String getFromTag() {
return fromTag;
}
public void setFromTag(String fromTag) {
this.fromTag = fromTag;
}
public String getToTag() {
return toTag;
}
public void setToTag(String toTag) {
this.toTag = toTag;
}
public boolean isRtcp() {
return rtcp;
}
public void setRtcp(boolean rtcp) {
this.rtcp = rtcp;
}
}
@@ -1,56 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import org.dom4j.Element;
import javax.sip.RequestEvent;
public class SipMsgInfo {
private RequestEvent evt;
private Device device;
private ParentPlatform platform;
private Element rootElement;
public SipMsgInfo(RequestEvent evt, Device device, Element rootElement) {
this.evt = evt;
this.device = device;
this.rootElement = rootElement;
}
public SipMsgInfo(RequestEvent evt, ParentPlatform platform, Element rootElement) {
this.evt = evt;
this.platform = platform;
this.rootElement = rootElement;
}
public RequestEvent getEvt() {
return evt;
}
public void setEvt(RequestEvent evt) {
this.evt = evt;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public ParentPlatform getPlatform() {
return platform;
}
public void setPlatform(ParentPlatform platform) {
this.platform = platform;
}
public Element getRootElement() {
return rootElement;
}
public void setRootElement(Element rootElement) {
this.rootElement = rootElement;
}
}
@@ -1,54 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
public class SipTransactionInfo {
private String callId;
private String fromTag;
private String toTag;
private String viaBranch;
public SipTransactionInfo(SIPResponse response) {
this.callId = response.getCallIdHeader().getCallId();
this.fromTag = response.getFromTag();
this.toTag = response.getToTag();
this.viaBranch = response.getTopmostViaHeader().getBranch();
}
public SipTransactionInfo() {
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
public String getFromTag() {
return fromTag;
}
public void setFromTag(String fromTag) {
this.fromTag = fromTag;
}
public String getToTag() {
return toTag;
}
public void setToTag(String toTag) {
this.toTag = toTag;
}
public String getViaBranch() {
return viaBranch;
}
public void setViaBranch(String viaBranch) {
this.viaBranch = viaBranch;
}
}
@@ -1,81 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.common.InviteSessionType;
public class SsrcTransaction {
private String deviceId;
private String channelId;
private String callId;
private String stream;
private String mediaServerId;
private String ssrc;
private SipTransactionInfo sipTransactionInfo;
private InviteSessionType type;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getCallId() {
return callId;
}
public void setCallId(String callId) {
this.callId = callId;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public String getSsrc() {
return ssrc;
}
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
public InviteSessionType getType() {
return type;
}
public void setType(InviteSessionType type) {
this.type = type;
}
public SipTransactionInfo getSipTransactionInfo() {
return sipTransactionInfo;
}
public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
this.sipTransactionInfo = sipTransactionInfo;
}
}
@@ -1,110 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author lin
*/
@Component
public class SubscribeHolder {
@Autowired
private DynamicTask dynamicTask;
@Autowired
private UserSetting userSetting;
private final String taskOverduePrefix = "subscribe_overdue_";
private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>();
public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
catalogMap.put(platformId, subscribeInfo);
if (subscribeInfo.getExpires() > 0) {
// 添加订阅到期
String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
// 添加任务处理订阅过期
dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
subscribeInfo.getExpires() * 1000);
}
}
public SubscribeInfo getCatalogSubscribe(String platformId) {
return catalogMap.get(platformId);
}
public void removeCatalogSubscribe(String platformId) {
catalogMap.remove(platformId);
String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
Runnable runnable = dynamicTask.get(taskOverdueKey);
if (runnable instanceof ISubscribeTask) {
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
subscribeTask.stop();
}
// 添加任务处理订阅过期
dynamicTask.stop(taskOverdueKey);
}
public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
mobilePositionMap.put(platformId, subscribeInfo);
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId;
// 添加任务处理GPS定时推送
dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId),
subscribeInfo.getGpsInterval() * 1000);
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
if (subscribeInfo.getExpires() > 0) {
// 添加任务处理订阅过期
dynamicTask.startDelay(taskOverdueKey, () -> {
removeMobilePositionSubscribe(subscribeInfo.getId());
},
subscribeInfo.getExpires() * 1000);
}
}
public SubscribeInfo getMobilePositionSubscribe(String platformId) {
return mobilePositionMap.get(platformId);
}
public void removeMobilePositionSubscribe(String platformId) {
mobilePositionMap.remove(platformId);
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId;
// 结束任务处理GPS定时推送
dynamicTask.stop(key);
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
Runnable runnable = dynamicTask.get(taskOverdueKey);
if (runnable instanceof ISubscribeTask) {
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
subscribeTask.stop();
}
// 添加任务处理订阅过期
dynamicTask.stop(taskOverdueKey);
}
public List<String> getAllCatalogSubscribePlatform() {
List<String> platforms = new ArrayList<>();
if(catalogMap.size() > 0) {
for (String key : catalogMap.keySet()) {
platforms.add(catalogMap.get(key).getId());
}
}
return platforms;
}
public void removeAllSubscribe(String platformId) {
removeMobilePositionSubscribe(platformId);
removeCatalogSubscribe(platformId);
}
}
@@ -1,141 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import javax.sip.header.*;
public class SubscribeInfo {
public SubscribeInfo(SIPRequest request, String id) {
this.id = id;
this.request = request;
this.expires = request.getExpires().getExpires();
EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
this.eventId = eventHeader.getEventId();
this.eventType = eventHeader.getEventType();
}
public SubscribeInfo() {
}
private String id;
private SIPRequest request;
private int expires;
private String eventId;
private String eventType;
private SIPResponse response;
/**
* 以下为可选字段
* @return
*/
private String sn;
private int gpsInterval;
/**
* 模拟的FromTag
*/
private String simulatedFromTag;
/**
* 模拟的ToTag
*/
private String simulatedToTag;
/**
* 模拟的CallID
*/
private String simulatedCallId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public SIPRequest getRequest() {
return request;
}
public void setRequest(SIPRequest request) {
this.request = request;
}
public int getExpires() {
return expires;
}
public void setExpires(int expires) {
this.expires = expires;
}
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public SIPResponse getResponse() {
return response;
}
public void setResponse(SIPResponse response) {
this.response = response;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public int getGpsInterval() {
return gpsInterval;
}
public void setGpsInterval(int gpsInterval) {
this.gpsInterval = gpsInterval;
}
public String getSimulatedFromTag() {
return simulatedFromTag;
}
public void setSimulatedFromTag(String simulatedFromTag) {
this.simulatedFromTag = simulatedFromTag;
}
public String getSimulatedCallId() {
return simulatedCallId;
}
public void setSimulatedCallId(String simulatedCallId) {
this.simulatedCallId = simulatedCallId;
}
public String getSimulatedToTag() {
return simulatedToTag;
}
public void setSimulatedToTag(String simulatedToTag) {
this.simulatedToTag = simulatedToTag;
}
}
@@ -1,51 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 摄像机同步状态
* @author lin
*/
@Schema(description = "摄像机同步状态")
public class SyncStatus {
@Schema(description = "总数")
private int total;
@Schema(description = "当前更新多少")
private int current;
@Schema(description = "错误描述")
private String errorMsg;
@Schema(description = "是否同步中")
private boolean syncIng;
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCurrent() {
return current;
}
public void setCurrent(int current) {
this.current = current;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public boolean isSyncIng() {
return syncIng;
}
public void setSyncIng(boolean syncIng) {
this.syncIng = syncIng;
}
}
@@ -1,63 +0,0 @@
package com.genersoft.iot.vmp.gb28181.conf;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.AlarmNotifyMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties;
/**
* 获取sip默认配置
* @author lin
*/
public class DefaultProperties {
public static Properties getProperties(String name, boolean sipLog) {
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", name);
// properties.setProperty("javax.sip.IP_ADDRESS", ip);
// 关闭自动会话
properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
/**
* 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
* gov/nist/javax/sip/SipStackImpl.class
* sip消息的解析在 gov.nist.javax.sip.stack.UDPMessageChannel的processIncomingDataPacket方法
*/
// * gov/nist/javax/sip/SipStackImpl.class
// 接收所有notify请求,即使没有订阅
properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false");
properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "true");
// 为_NULL _对话框传递_终止的_事件
properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true");
// 是否自动计算content length的实际长度,默认不计算
properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
// 会话清理策略
properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal");
// 处理由该服务器处理的基于底层TCP的保持生存超时
properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
// 获取实际内容长度,不使用header中的长度信息
properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true");
// 线程可重入
properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "true");
// 定义应用程序打算多久审计一次 SIP 堆栈,了解其内部线程的健康状况(该属性指定连续审计之间的时间(以毫秒为单位))
properties.setProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS", "30000");
// properties.setProperty("gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY", "gov.nist.javax.sip.stack.NioMessageProcessorFactory");
/**
* sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
*/
Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class);
if (sipLog) {
properties.setProperty("gov.nist.javax.sip.STACK_LOGGER", "com.genersoft.iot.vmp.gb28181.conf.StackLoggerImpl");
properties.setProperty("gov.nist.javax.sip.SERVER_LOGGER", "com.genersoft.iot.vmp.gb28181.conf.ServerLoggerImpl");
properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
logger.info("[SIP日志]已开启");
}else {
logger.info("[SIP日志]已关闭");
}
return properties;
}
}
@@ -1,91 +0,0 @@
package com.genersoft.iot.vmp.gb28181.conf;
import gov.nist.core.CommonLogger;
import gov.nist.core.ServerLogger;
import gov.nist.core.StackLogger;
import gov.nist.javax.sip.message.SIPMessage;
import gov.nist.javax.sip.stack.SIPTransactionStack;
import javax.sip.SipStack;
import java.util.Properties;
public class ServerLoggerImpl implements ServerLogger {
private boolean showLog = true;
private SIPTransactionStack sipStack;
protected StackLogger stackLogger;
@Override
public void closeLogFile() {
}
@Override
public void logMessage(SIPMessage message, String from, String to, boolean sender, long time) {
if (!showLog) {
return;
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(sender? "发送:目标--->" + from:"接收:来自--->" + to)
.append("\r\n")
.append(message);
this.stackLogger.logInfo(stringBuilder.toString());
}
@Override
public void logMessage(SIPMessage message, String from, String to, String status, boolean sender, long time) {
if (!showLog) {
return;
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(sender? "发送: 目标->" + from :"接收:来自->" + to)
.append("\r\n")
.append(message);
this.stackLogger.logInfo(stringBuilder.toString());
}
@Override
public void logMessage(SIPMessage message, String from, String to, String status, boolean sender) {
if (!showLog) {
return;
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(sender? "发送: 目标->" + from :"接收:来自->" + to)
.append("\r\n")
.append(message);
this.stackLogger.logInfo(stringBuilder.toString());
}
@Override
public void logException(Exception ex) {
if (!showLog) {
return;
}
this.stackLogger.logException(ex);
}
@Override
public void setStackProperties(Properties stackProperties) {
if (!showLog) {
return;
}
String TRACE_LEVEL = stackProperties.getProperty("gov.nist.javax.sip.TRACE_LEVEL");
if (TRACE_LEVEL != null) {
showLog = true;
}
}
@Override
public void setSipStack(SipStack sipStack) {
if (!showLog) {
return;
}
if(sipStack instanceof SIPTransactionStack) {
this.sipStack = (SIPTransactionStack)sipStack;
this.stackLogger = CommonLogger.getLogger(SIPTransactionStack.class);
}
}
}
@@ -1,109 +0,0 @@
package com.genersoft.iot.vmp.gb28181.conf;
import gov.nist.core.StackLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
public class StackLoggerImpl implements StackLogger {
private final static Logger logger = LoggerFactory.getLogger(StackLoggerImpl.class);
@Override
public void logStackTrace() {
}
@Override
public void logStackTrace(int traceLevel) {
System.out.println("traceLevel: " + traceLevel);
}
@Override
public int getLineCount() {
return 0;
}
@Override
public void logException(Throwable ex) {
}
@Override
public void logDebug(String message) {
// logger.debug(message);
}
@Override
public void logDebug(String message, Exception ex) {
// logger.debug(message);
}
@Override
public void logTrace(String message) {
logger.trace(message);
}
@Override
public void logFatalError(String message) {
// logger.error(message);
}
@Override
public void logError(String message) {
// logger.error(message);
}
@Override
public boolean isLoggingEnabled() {
return true;
}
@Override
public boolean isLoggingEnabled(int logLevel) {
return true;
}
@Override
public void logError(String message, Exception ex) {
// logger.error(message);
}
@Override
public void logWarning(String message) {
logger.warn(message);
}
@Override
public void logInfo(String message) {
logger.info(message);
}
@Override
public void disableLogging() {
}
@Override
public void enableLogging() {
}
@Override
public void setBuildTimeStamp(String buildTimeStamp) {
}
@Override
public void setStackProperties(Properties stackProperties) {
}
@Override
public String getLoggerName() {
return null;
}
}
@@ -1,118 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent;
import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent;
import javax.sip.TimeoutEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @description:Event事件通知推送器,支持推送在线事件、离线事件
* @author: swwheihei
* @date: 2020年5月6日 上午11:30:50
*/
@Component
public class EventPublisher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
/**
* 设备报警事件
* @param deviceAlarm
*/
public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) {
AlarmEvent alarmEvent = new AlarmEvent(this);
alarmEvent.setAlarmInfo(deviceAlarm);
applicationEventPublisher.publishEvent(alarmEvent);
}
public void zlmOfflineEventPublish(String mediaServerId){
ZLMOfflineEvent outEvent = new ZLMOfflineEvent(this);
outEvent.setMediaServerId(mediaServerId);
applicationEventPublisher.publishEvent(outEvent);
}
public void zlmOnlineEventPublish(String mediaServerId) {
ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this);
outEvent.setMediaServerId(mediaServerId);
applicationEventPublisher.publishEvent(outEvent);
}
public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) {
List<DeviceChannel> deviceChannelList = new ArrayList<>();
deviceChannelList.add(deviceChannel);
catalogEventPublish(platformId, deviceChannelList, type);
}
public void requestTimeOut(TimeoutEvent timeoutEvent) {
RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this);
requestTimeoutEvent.setTimeoutEvent(timeoutEvent);
applicationEventPublisher.publishEvent(requestTimeoutEvent);
}
/**
*
* @param platformId
* @param deviceChannels
* @param type
*/
public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) {
CatalogEvent outEvent = new CatalogEvent(this);
List<DeviceChannel> channels = new ArrayList<>();
if (deviceChannels.size() > 1) {
// 数据去重
Set<String> gbIdSet = new HashSet<>();
for (DeviceChannel deviceChannel : deviceChannels) {
if (!gbIdSet.contains(deviceChannel.getChannelId())) {
gbIdSet.add(deviceChannel.getChannelId());
channels.add(deviceChannel);
}
}
}else {
channels = deviceChannels;
}
outEvent.setDeviceChannels(channels);
outEvent.setType(type);
outEvent.setPlatformId(platformId);
applicationEventPublisher.publishEvent(outEvent);
}
public void catalogEventPublishForStream(String platformId, List<GbStream> gbStreams, String type) {
CatalogEvent outEvent = new CatalogEvent(this);
outEvent.setGbStreams(gbStreams);
outEvent.setType(type);
outEvent.setPlatformId(platformId);
applicationEventPublisher.publishEvent(outEvent);
}
public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) {
List<GbStream> gbStreamList = new ArrayList<>();
gbStreamList.add(gbStream);
catalogEventPublishForStream(platformId, gbStreamList, type);
}
public void recordEndEventPush(RecordInfo recordInfo) {
RecordEndEvent outEvent = new RecordEndEvent(this);
outEvent.setRecordInfo(recordInfo);
applicationEventPublisher.publishEvent(outEvent);
}
}
@@ -1,180 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.sip.DialogTerminatedEvent;
import javax.sip.ResponseEvent;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Response;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* @author lin
*/
@Component
public class SipSubscribe {
private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class);
private Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>();
private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
private Map<String, Instant> okTimeSubscribes = new ConcurrentHashMap<>();
private Map<String, Instant> errorTimeSubscribes = new ConcurrentHashMap<>();
// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
// @Scheduled(fixedRate= 100 * 60 * 60 )
@Scheduled(cron="0 0/1 * * * ?") //每5分钟执行一次
public void execute(){
logger.info("[定时任务] 清理过期的SIP订阅信息");
Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
for (String key : okTimeSubscribes.keySet()) {
if (okTimeSubscribes.get(key).isBefore(instant)){
okSubscribes.remove(key);
okTimeSubscribes.remove(key);
}
}
for (String key : errorTimeSubscribes.keySet()) {
if (errorTimeSubscribes.get(key).isBefore(instant)){
errorSubscribes.remove(key);
errorTimeSubscribes.remove(key);
}
}
logger.debug("okTimeSubscribes.size:{}",okTimeSubscribes.size());
logger.debug("okSubscribes.size:{}",okSubscribes.size());
logger.debug("errorTimeSubscribes.size:{}",errorTimeSubscribes.size());
logger.debug("errorSubscribes.size:{}",errorSubscribes.size());
}
public interface Event { void response(EventResult eventResult) ;
}
/**
*
*/
public enum EventResultType{
// 超时
timeout,
// 回复
response,
// 事务已结束
transactionTerminated,
// 会话已结束
dialogTerminated,
// 设备未找到
deviceNotFoundEvent,
// 设备未找到
cmdSendFailEvent
}
public static class EventResult<EventObject>{
public int statusCode;
public EventResultType type;
public String msg;
public String callId;
public EventObject event;
public EventResult() {
}
public EventResult(EventObject event) {
this.event = event;
if (event instanceof ResponseEvent) {
ResponseEvent responseEvent = (ResponseEvent)event;
Response response = responseEvent.getResponse();
this.type = EventResultType.response;
if (response != null) {
this.msg = response.getReasonPhrase();
this.statusCode = response.getStatusCode();
}
this.callId = ((CallIdHeader)response.getHeader(CallIdHeader.NAME)).getCallId();
}else if (event instanceof TimeoutEvent) {
TimeoutEvent timeoutEvent = (TimeoutEvent)event;
this.type = EventResultType.timeout;
this.msg = "消息超时未回复";
this.statusCode = -1024;
if (timeoutEvent.isServerTransaction()) {
this.callId = ((SIPRequest)timeoutEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
}else {
this.callId = ((SIPRequest)timeoutEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
}
}else if (event instanceof TransactionTerminatedEvent) {
TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event;
this.type = EventResultType.transactionTerminated;
this.msg = "事务已结束";
this.statusCode = -1024;
if (transactionTerminatedEvent.isServerTransaction()) {
this.callId = ((SIPRequest)transactionTerminatedEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId();
}else {
this.callId = ((SIPRequest)transactionTerminatedEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId();
}
}else if (event instanceof DialogTerminatedEvent) {
DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event;
this.type = EventResultType.dialogTerminated;
this.msg = "会话已结束";
this.statusCode = -1024;
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
}else if (event instanceof DeviceNotFoundEvent) {
this.type = EventResultType.deviceNotFoundEvent;
this.msg = "设备未找到";
this.statusCode = -1024;
this.callId = ((DeviceNotFoundEvent) event).getCallId();
}
}
}
public void addErrorSubscribe(String key, SipSubscribe.Event event) {
errorSubscribes.put(key, event);
errorTimeSubscribes.put(key, Instant.now());
}
public void addOkSubscribe(String key, SipSubscribe.Event event) {
okSubscribes.put(key, event);
okTimeSubscribes.put(key, Instant.now());
}
public SipSubscribe.Event getErrorSubscribe(String key) {
return errorSubscribes.get(key);
}
public void removeErrorSubscribe(String key) {
if(key == null){
return;
}
errorSubscribes.remove(key);
errorTimeSubscribes.remove(key);
}
public SipSubscribe.Event getOkSubscribe(String key) {
return okSubscribes.get(key);
}
public void removeOkSubscribe(String key) {
if(key == null){
return;
}
okSubscribes.remove(key);
okTimeSubscribes.remove(key);
}
public int getErrorSubscribesSize(){
return errorSubscribes.size();
}
public int getOkSubscribesSize(){
return okSubscribes.size();
}
}
@@ -1,31 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.alarm;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import org.springframework.context.ApplicationEvent;
/**
* @description: 报警事件
* @author: lawrencehj
* @data: 2021-01-20
*/
public class AlarmEvent extends ApplicationEvent {
/**
*
*/
private static final long serialVersionUID = 1L;
public AlarmEvent(Object source) {
super(source);
}
private DeviceAlarm deviceAlarm;
public DeviceAlarm getAlarmInfo() {
return deviceAlarm;
}
public void setAlarmInfo(DeviceAlarm deviceAlarm) {
this.deviceAlarm = deviceAlarm;
}
}
@@ -1,70 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.alarm;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 报警事件监听器.
*
* @author lawrencehj
* @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
* @since 2021/01/20
*/
@Component
public class AlarmEventListener implements ApplicationListener<AlarmEvent> {
private static final Logger logger = LoggerFactory.getLogger(AlarmEventListener.class);
private static final Map<String, PrintWriter> SSE_CACHE = new ConcurrentHashMap<>();
public void addSseEmitter(String browserId, PrintWriter writer) {
SSE_CACHE.put(browserId, writer);
logger.info("SSE 在线数量: {}", SSE_CACHE.size());
}
public void removeSseEmitter(String browserId, PrintWriter writer) {
SSE_CACHE.remove(browserId, writer);
logger.info("SSE 在线数量: {}", SSE_CACHE.size());
}
@Override
public void onApplicationEvent(@NotNull AlarmEvent event) {
if (logger.isDebugEnabled()) {
logger.debug("设备报警事件触发, deviceId: {}, {}", event.getAlarmInfo().getDeviceId(), event.getAlarmInfo().getAlarmDescription());
}
String msg = "<strong>设备编号:</strong> <i>" + event.getAlarmInfo().getDeviceId() + "</i>"
+ "<br><strong>通道编号:</strong> <i>" + event.getAlarmInfo().getChannelId() + "</i>"
+ "<br><strong>报警描述:</strong> <i>" + event.getAlarmInfo().getAlarmDescription() + "</i>"
+ "<br><strong>报警时间:</strong> <i>" + event.getAlarmInfo().getAlarmTime() + "</i>";
for (Iterator<Map.Entry<String, PrintWriter>> it = SSE_CACHE.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, PrintWriter> response = it.next();
logger.info("推送到 SSE 连接, 浏览器 ID: {}", response.getKey());
try {
PrintWriter writer = response.getValue();
if (writer.checkError()) {
it.remove();
continue;
}
String sseMsg = "event:message\n" +
"data:" + msg + "\n" +
"\n";
writer.write(sseMsg);
writer.flush();
} catch (Exception e) {
it.remove();
}
}
}
}
@@ -1,25 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.device;
import org.springframework.context.ApplicationEvent;
import javax.sip.TimeoutEvent;
/**
* @author lin
*/
public class RequestTimeoutEvent extends ApplicationEvent {
public RequestTimeoutEvent(Object source) {
super(source);
}
private TimeoutEvent timeoutEvent;
public TimeoutEvent getTimeoutEvent() {
return timeoutEvent;
}
public void setTimeoutEvent(TimeoutEvent timeoutEvent) {
this.timeoutEvent = timeoutEvent;
}
}
@@ -1,39 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.device;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.service.IDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.sip.ClientTransaction;
import javax.sip.address.SipURI;
import javax.sip.message.Request;
/**
* @author lin
*/
@Component
public class RequestTimeoutEventImpl implements ApplicationListener<RequestTimeoutEvent> {
@Autowired
private IDeviceService deviceService;
@Override
public void onApplicationEvent(RequestTimeoutEvent event) {
ClientTransaction clientTransaction = event.getTimeoutEvent().getClientTransaction();
if (clientTransaction != null) {
Request request = clientTransaction.getRequest();
if (request != null) {
String host = ((SipURI) request.getRequestURI()).getHost();
int port = ((SipURI) request.getRequestURI()).getPort();
Device device = deviceService.getDeviceByHostAndPort(host, port);
if (device == null) {
return;
}
deviceService.offline(device.getDeviceId(), "等待消息超时");
}
}
}
}
@@ -1,32 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.record;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import org.springframework.context.ApplicationEvent;
/**
* @description: 录像查询结束时间
* @author: pan
* @data: 2022-02-23
*/
public class RecordEndEvent extends ApplicationEvent {
/**
*
*/
private static final long serialVersionUID = 1L;
public RecordEndEvent(Object source) {
super(source);
}
private RecordInfo recordInfo;
public RecordInfo getRecordInfo() {
return recordInfo;
}
public void setRecordInfo(RecordInfo recordInfo) {
this.recordInfo = recordInfo;
}
}
@@ -1,67 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.record;
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: 录像查询结束事件
* @author: pan
* @data: 2022-02-23
*/
@Component
public class RecordEndEventListener implements ApplicationListener<RecordEndEvent> {
private final static Logger logger = LoggerFactory.getLogger(RecordEndEventListener.class);
private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
public interface RecordEndEventHandler{
void handler(RecordInfo recordInfo);
}
@Override
public void onApplicationEvent(RecordEndEvent event) {
String deviceId = event.getRecordInfo().getDeviceId();
String channelId = event.getRecordInfo().getChannelId();
int count = event.getRecordInfo().getCount();
int sumNum = event.getRecordInfo().getSumNum();
logger.info("录像查询完成事件触发,deviceId{}, channelId: {}, 录像数量{}/{}条", event.getRecordInfo().getDeviceId(),
event.getRecordInfo().getChannelId(), count,sumNum);
if (handlerMap.size() > 0) {
RecordEndEventHandler handler = handlerMap.get(deviceId + channelId);
if (handler !=null){
handler.handler(event.getRecordInfo());
if (count ==sumNum){
handlerMap.remove(deviceId + channelId);
}
}
}
}
/**
* 添加
* @param device
* @param channelId
* @param recordEndEventHandler
*/
public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) {
handlerMap.put(device + channelId, recordEndEventHandler);
}
/**
* 添加
* @param device
* @param channelId
*/
public void delEndEventHandler(String device, String channelId) {
handlerMap.remove(device + channelId);
}
}
@@ -1,85 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import org.springframework.context.ApplicationEvent;
import java.util.List;
public class CatalogEvent extends ApplicationEvent {
public CatalogEvent(Object source) {
super(source);
}
/**
* 上线
*/
public static final String ON = "ON";
/**
* 离线
*/
public static final String OFF = "OFF";
/**
* 视频丢失
*/
public static final String VLOST = "VLOST";
/**
* 故障
*/
public static final String DEFECT = "DEFECT";
/**
* 增加
*/
public static final String ADD = "ADD";
/**
* 删除
*/
public static final String DEL = "DEL";
/**
* 更新
*/
public static final String UPDATE = "UPDATE";
private List<DeviceChannel> deviceChannels;
private List<GbStream> gbStreams;
private String type;
private String platformId;
public List<DeviceChannel> getDeviceChannels() {
return deviceChannels;
}
public void setDeviceChannels(List<DeviceChannel> deviceChannels) {
this.deviceChannels = deviceChannels;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPlatformId() {
return platformId;
}
public void setPlatformId(String platformId) {
this.platformId = platformId;
}
public List<GbStream> getGbStreams() {
return gbStreams;
}
public void setGbStreams(List<GbStream> gbStreams) {
this.gbStreams = gbStreams;
}
}
@@ -1,200 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.service.IGbStreamService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* catalog事件
*/
@Component
public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
private final static Logger logger = LoggerFactory.getLogger(CatalogEventLister.class);
@Autowired
private IVideoManagerStorage storager;
@Autowired
private SIPCommanderFroPlatform sipCommanderFroPlatform;
@Autowired
private IGbStreamService gbStreamService;
@Autowired
private SubscribeHolder subscribeHolder;
@Autowired
private UserSetting userSetting;
@Override
public void onApplicationEvent(CatalogEvent event) {
SubscribeInfo subscribe = null;
ParentPlatform parentPlatform = null;
Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
if (!ObjectUtils.isEmpty(event.getPlatformId())) {
subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
if (subscribe == null) {
return;
}
parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
if (parentPlatform != null && !parentPlatform.isStatus()) {
return;
}
}else {
// 获取所用订阅
List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform();
if (event.getDeviceChannels() != null) {
if (platforms.size() > 0) {
for (DeviceChannel deviceChannel : event.getDeviceChannels()) {
List<ParentPlatform> parentPlatformsForGB = storager.queryPlatFormListForGBWithGBId(deviceChannel.getChannelId(), platforms);
parentPlatformMap.put(deviceChannel.getChannelId(), parentPlatformsForGB);
}
}
}else if (event.getGbStreams() != null) {
if (platforms.size() > 0) {
for (GbStream gbStream : event.getGbStreams()) {
if (gbStream == null || ObjectUtils.isEmpty(gbStream.getGbId())) {
continue;
}
List<ParentPlatform> parentPlatformsForGB = storager.queryPlatFormListForStreamWithGBId(gbStream.getApp(),gbStream.getStream(), platforms);
parentPlatformMap.put(gbStream.getGbId(), parentPlatformsForGB);
}
}
}
}
switch (event.getType()) {
case CatalogEvent.ON:
case CatalogEvent.OFF:
case CatalogEvent.DEL:
if (parentPlatform != null || subscribe != null) {
List<DeviceChannel> deviceChannelList = new ArrayList<>();
if (event.getDeviceChannels() != null) {
deviceChannelList.addAll(event.getDeviceChannels());
}
if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
for (GbStream gbStream : event.getGbStreams()) {
if (gbStream != null
&& gbStream.getStreamType() != null
&& gbStream.getStreamType().equals("push")
&& !userSetting.isUsePushingAsStatus()) {
continue;
}
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
deviceChannelList.add(deviceChannelByStream);
}
}
if (deviceChannelList.size() > 0) {
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
try {
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
}
}
}else if (parentPlatformMap.keySet().size() > 0) {
for (String gbId : parentPlatformMap.keySet()) {
List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
if (parentPlatforms != null && parentPlatforms.size() > 0) {
for (ParentPlatform platform : parentPlatforms) {
SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
if (subscribeInfo == null) {
continue;
}
logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId);
List<DeviceChannel> deviceChannelList = new ArrayList<>();
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(gbId);
deviceChannelList.add(deviceChannel);
try {
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
}
}
}
}
}
break;
case CatalogEvent.VLOST:
break;
case CatalogEvent.DEFECT:
break;
case CatalogEvent.ADD:
case CatalogEvent.UPDATE:
if (parentPlatform != null || subscribe != null) {
List<DeviceChannel> deviceChannelList = new ArrayList<>();
if (event.getDeviceChannels() != null) {
deviceChannelList.addAll(event.getDeviceChannels());
}
if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
for (GbStream gbStream : event.getGbStreams()) {
deviceChannelList.add(
gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), parentPlatform));
}
}
if (deviceChannelList.size() > 0) {
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
try {
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
}
}
}else if (parentPlatformMap.keySet().size() > 0) {
for (String gbId : parentPlatformMap.keySet()) {
List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
if (parentPlatforms != null && parentPlatforms.size() > 0) {
for (ParentPlatform platform : parentPlatforms) {
SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
if (subscribeInfo == null) {
continue;
}
logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId);
List<DeviceChannel> deviceChannelList = new ArrayList<>();
DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(platform.getServerGBId(), gbId);
deviceChannelList.add(deviceChannel);
GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId);
if(gbStream != null){
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform);
deviceChannelList.add(deviceChannelByStream);
}
try {
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null);
} catch (InvalidArgumentException | ParseException | NoSuchFieldException |
SipException | IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
}
}
}
}
}
break;
default:
break;
}
}
}
@@ -1,146 +0,0 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.gb28181.bean.CatalogData;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@Component
public class CatalogDataCatch {
public static Map<String, CatalogData> data = new ConcurrentHashMap<>();
@Autowired
private IVideoManagerStorage storager;
public void addReady(Device device, int sn ) {
CatalogData catalogData = data.get(device.getDeviceId());
if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
catalogData = new CatalogData();
catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>()));
catalogData.setDevice(device);
catalogData.setSn(sn);
catalogData.setStatus(CatalogData.CatalogDataStatus.ready);
catalogData.setLastTime(Instant.now());
data.put(device.getDeviceId(), catalogData);
}
}
public void put(String deviceId, int sn, int total, Device device, List<DeviceChannel> deviceChannelList) {
CatalogData catalogData = data.get(deviceId);
if (catalogData == null) {
catalogData = new CatalogData();
catalogData.setSn(sn);
catalogData.setTotal(total);
catalogData.setDevice(device);
catalogData.setChannelList(deviceChannelList);
catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
catalogData.setLastTime(Instant.now());
data.put(deviceId, catalogData);
}else {
// 同一个设备的通道同步请求只考虑一个,其他的直接忽略
if (catalogData.getSn() != sn) {
return;
}
catalogData.setTotal(total);
catalogData.setDevice(device);
catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
catalogData.getChannelList().addAll(deviceChannelList);
catalogData.setLastTime(Instant.now());
}
}
public List<DeviceChannel> get(String deviceId) {
CatalogData catalogData = data.get(deviceId);
if (catalogData == null) {
return null;
}
return catalogData.getChannelList();
}
public int getTotal(String deviceId) {
CatalogData catalogData = data.get(deviceId);
if (catalogData == null) {
return 0;
}
return catalogData.getTotal();
}
public SyncStatus getSyncStatus(String deviceId) {
CatalogData catalogData = data.get(deviceId);
if (catalogData == null) {
return null;
}
SyncStatus syncStatus = new SyncStatus();
syncStatus.setCurrent(catalogData.getChannelList().size());
syncStatus.setTotal(catalogData.getTotal());
syncStatus.setErrorMsg(catalogData.getErrorMsg());
if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
syncStatus.setSyncIng(false);
}else {
syncStatus.setSyncIng(true);
}
return syncStatus;
}
public boolean isSyncRunning(String deviceId) {
CatalogData catalogData = data.get(deviceId);
if (catalogData == null) {
return false;
}
return !catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end);
}
@Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
private void timerTask(){
Set<String> keys = data.keySet();
Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5));
Instant instantBefore30S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(30));
for (String deviceId : keys) {
CatalogData catalogData = data.get(deviceId);
if ( catalogData.getLastTime().isBefore(instantBefore5S)) {
// 超过五秒收不到消息任务超时, 只更新这一部分数据, 收到数据与声明的总数一致,则重置通道数据,数据不全则只对收到的数据做更新操作
if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) {
if (catalogData.getTotal() == catalogData.getChannelList().size()) {
storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
}else {
storager.updateChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
}
String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "";
catalogData.setErrorMsg(errorMsg);
if (catalogData.getTotal() != catalogData.getChannelList().size()) {
}
}else if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.ready)) {
String errorMsg = "同步失败,等待回复超时";
catalogData.setErrorMsg(errorMsg);
}
catalogData.setStatus(CatalogData.CatalogDataStatus.end);
}
if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().isBefore(instantBefore30S)) { // 超过三十秒,如果标记为end则删除
data.remove(deviceId);
}
}
}
public void setChannelSyncEnd(String deviceId, String errorMsg) {
CatalogData catalogData = data.get(deviceId);
if (catalogData == null) {
return;
}
catalogData.setStatus(CatalogData.CatalogDataStatus.end);
catalogData.setErrorMsg(errorMsg);
}
}
@@ -1,92 +0,0 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEventListener;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* @author lin
*/
@Component
public class RecordDataCatch {
public static Map<String, RecordInfo> data = new ConcurrentHashMap<>();
@Autowired
private DeferredResultHolder deferredResultHolder;
@Autowired
private RecordEndEventListener recordEndEventListener;
public int put(String deviceId,String channelId, String sn, int sumNum, List<RecordItem> recordItems) {
String key = deviceId + sn;
RecordInfo recordInfo = data.get(key);
if (recordInfo == null) {
recordInfo = new RecordInfo();
recordInfo.setDeviceId(deviceId);
recordInfo.setChannelId(channelId);
recordInfo.setSn(sn.trim());
recordInfo.setSumNum(sumNum);
recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>()));
recordInfo.setLastTime(Instant.now());
recordInfo.getRecordList().addAll(recordItems);
data.put(key, recordInfo);
}else {
// 同一个设备的通道同步请求只考虑一个,其他的直接忽略
if (!Objects.equals(sn.trim(), recordInfo.getSn())) {
return 0;
}
recordInfo.getRecordList().addAll(recordItems);
recordInfo.setLastTime(Instant.now());
}
return recordInfo.getRecordList().size();
}
@Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
private void timerTask(){
Set<String> keys = data.keySet();
// 获取五秒前的时刻
Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5));
for (String key : keys) {
RecordInfo recordInfo = data.get(key);
// 超过五秒收不到消息任务超时, 只更新这一部分数据
if ( recordInfo.getLastTime().isBefore(instantBefore5S)) {
// 处理录像数据, 返回给前端
String msgKey = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn();
// 对数据进行排序
Collections.sort(recordInfo.getRecordList());
RequestMessage msg = new RequestMessage();
msg.setKey(msgKey);
msg.setData(recordInfo);
deferredResultHolder.invokeAllResult(msg);
recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId());
data.remove(key);
}
}
}
public boolean isComplete(String deviceId, String sn) {
RecordInfo recordInfo = data.get(deviceId + sn);
return recordInfo != null && recordInfo.getRecordList().size() == recordInfo.getSumNum();
}
public RecordInfo getRecordInfo(String deviceId, String sn) {
return data.get(deviceId + sn);
}
public void remove(String deviceId, String sn) {
data.remove(deviceId + sn);
}
}
@@ -1,125 +0,0 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* ssrc使用
*/
@Component
public class SSRCFactory {
/**
* 播流最大并发个数
*/
private static final Integer MAX_STREAM_COUNT = 10000;
/**
* 播流最大并发个数
*/
private static final String SSRC_INFO_KEY = "VMP_SSRC_INFO_";
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private SipConfig sipConfig;
@Autowired
private UserSetting userSetting;
public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
String ssrcPrefix = sipConfig.getDomain().substring(3, 8);
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
List<String> ssrcList = new ArrayList<>();
for (int i = 1; i < MAX_STREAM_COUNT; i++) {
String ssrc = String.format("%s%04d", ssrcPrefix, i);
if (null == usedSet || !usedSet.contains(ssrc)) {
ssrcList.add(ssrc);
}
}
if (redisTemplate.opsForSet().size(redisKey) != null) {
redisTemplate.delete(redisKey);
}
redisTemplate.opsForSet().add(redisKey, ssrcList.toArray(new String[0]));
}
/**
* 获取视频预览的SSRC值,第一位固定为0
*
* @return ssrc
*/
public String getPlaySsrc(String mediaServerId) {
return "0" + getSN(mediaServerId);
}
/**
* 获取录像回放的SSRC值,第一位固定为1
*/
public String getPlayBackSsrc(String mediaServerId) {
return "1" + getSN(mediaServerId);
}
/**
* 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
*
* @param ssrc 需要重置的ssrc
*/
public void releaseSsrc(String mediaServerId, String ssrc) {
if (ssrc == null) {
return;
}
String sn = ssrc.substring(1);
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
redisTemplate.opsForSet().add(redisKey, sn);
}
/**
* 获取后四位数SN,随机数
*/
private String getSN(String mediaServerId) {
String sn = null;
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
Long size = redisTemplate.opsForSet().size(redisKey);
if (size == null || size == 0) {
throw new RuntimeException("ssrc已经用完");
} else {
// 在集合中移除并返回一个随机成员。
sn = (String) redisTemplate.opsForSet().pop(redisKey);
redisTemplate.opsForSet().remove(redisKey, sn);
}
return sn;
}
/**
* 重置一个流媒体服务的所有ssrc
*
* @param mediaServerId 流媒体服务ID
*/
public void reset(String mediaServerId) {
this.initMediaServerSSRC(mediaServerId, null);
}
/**
* 是否已经存在了某个MediaServer的SSRC信息
*
* @param mediaServerId 流媒体服务ID
*/
public boolean hasMediaServerSSRC(String mediaServerId) {
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
return Boolean.TRUE.equals(redisTemplate.hasKey(redisKey));
}
}
@@ -1,150 +0,0 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.utils.JsonUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import gov.nist.javax.sip.message.SIPResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 视频流session管理器,管理视频预览、预览回放的通信句柄
*/
@Component
public class VideoStreamSessionManager {
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
/**
* 添加一个点播/回放的事务信息
* 后续可以通过流Id/callID
* @param deviceId 设备ID
* @param channelId 通道ID
* @param callId 一次请求的CallID
* @param stream 流名称
* @param mediaServerId 所使用的流媒体ID
* @param response 回复
*/
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){
SsrcTransaction ssrcTransaction = new SsrcTransaction();
ssrcTransaction.setDeviceId(deviceId);
ssrcTransaction.setChannelId(channelId);
ssrcTransaction.setStream(stream);
ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
ssrcTransaction.setCallId(callId);
ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId);
ssrcTransaction.setType(type);
redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
}
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
if (ObjectUtils.isEmpty(deviceId)) {
deviceId ="*";
}
if (ObjectUtils.isEmpty(channelId)) {
channelId ="*";
}
if (ObjectUtils.isEmpty(callId)) {
callId ="*";
}
if (ObjectUtils.isEmpty(stream)) {
stream ="*";
}
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
if (scanResult.size() == 0) {
return null;
}
return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
}
public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
if (ObjectUtils.isEmpty(deviceId)) {
deviceId ="*";
}
if (ObjectUtils.isEmpty(channelId)) {
channelId ="*";
}
if (ObjectUtils.isEmpty(callId)) {
callId ="*";
}
if (ObjectUtils.isEmpty(stream)) {
stream ="*";
}
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
if (scanResult.size() == 0) {
return null;
}
List<SsrcTransaction> result = new ArrayList<>();
for (Object keyObj : scanResult) {
result.add((SsrcTransaction)redisTemplate.opsForValue().get(keyObj));
}
return result;
}
public String getMediaServerId(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) {
return null;
}
return ssrcTransaction.getMediaServerId();
}
public String getSSRC(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) {
return null;
}
return ssrcTransaction.getSsrc();
}
public void remove(String deviceId, String channelId, String stream) {
List<SsrcTransaction> ssrcTransactionList = getSsrcTransactionForAll(deviceId, channelId, null, stream);
if (ssrcTransactionList == null || ssrcTransactionList.isEmpty()) {
return;
}
for (SsrcTransaction ssrcTransaction : ssrcTransactionList) {
redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
+ deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
}
}
public void removeByCallId(String deviceId, String channelId, String callId) {
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
if (ssrcTransaction == null ) {
return;
}
redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
+ deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
}
public List<SsrcTransaction> getAllSsrc() {
List<Object> ssrcTransactionKeys = RedisUtil.scan(redisTemplate, String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId()));
List<SsrcTransaction> result= new ArrayList<>();
for (Object ssrcTransactionKey : ssrcTransactionKeys) {
String key = (String) ssrcTransactionKey;
SsrcTransaction ssrcTransaction = JsonUtil.redisJsonToObject(redisTemplate, key, SsrcTransaction.class);
result.add(ssrcTransaction);
}
return result;
}
}
@@ -1,10 +0,0 @@
package com.genersoft.iot.vmp.gb28181.task;
import javax.sip.DialogState;
/**
* @author lin
*/
public interface ISubscribeTask extends Runnable{
void stop();
}
@@ -1,132 +0,0 @@
package com.genersoft.iot.vmp.gb28181.task;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 系统启动时控制设备
* @author lin
*/
@Component
@Order(value=14)
public class SipRunner implements CommandLineRunner {
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private SSRCFactory ssrcFactory;
@Autowired
private UserSetting userSetting;
@Autowired
private IDeviceService deviceService;
@Autowired
private ZLMRESTfulUtils zlmresTfulUtils;
@Autowired
private IMediaServerService mediaServerService;
@Autowired
private IPlatformService platformService;
@Autowired
private ISIPCommanderForPlatform commanderForPlatform;
private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
@Override
public void run(String... args) throws Exception {
List<Device> deviceList = deviceService.getAllOnlineDevice();
for (Device device : deviceList) {
if (deviceService.expire(device)){
deviceService.offline(device.getDeviceId(), "注册已过期");
}else {
deviceService.online(device, null);
}
}
// 重置cseq计数
redisCatchStorage.resetAllCSEQ();
// 清理redis
// 清理数据库不存在但是redis中存在的数据
List<Device> devicesInDb = deviceService.getAll();
if (devicesInDb.size() == 0) {
redisCatchStorage.removeAllDevice();
}else {
List<Device> devicesInRedis = redisCatchStorage.getAllDevices();
if (devicesInRedis.size() > 0) {
Map<String, Device> deviceMapInDb = new HashMap<>();
devicesInDb.parallelStream().forEach(device -> {
deviceMapInDb.put(device.getDeviceId(), device);
});
devicesInRedis.parallelStream().forEach(device -> {
if (deviceMapInDb.get(device.getDeviceId()) == null) {
redisCatchStorage.removeDevice(device.getDeviceId());
}
});
}
}
// 查找国标推流
List<SendRtpItem> sendRtpItems = redisCatchStorage.queryAllSendRTPServer();
if (sendRtpItems.size() > 0) {
for (SendRtpItem sendRtpItem : sendRtpItems) {
MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId());
redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStreamId());
if (mediaServerItem != null) {
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
Map<String, Object> param = new HashMap<>();
param.put("vhost","__defaultVhost__");
param.put("app",sendRtpItem.getApp());
param.put("stream",sendRtpItem.getStreamId());
param.put("ssrc",sendRtpItem.getSsrc());
JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
if (jsonObject != null && jsonObject.getInteger("code") == 0) {
ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
if (platform != null) {
try {
commanderForPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
}
}
}
}
}
}
}
@@ -1,105 +0,0 @@
package com.genersoft.iot.vmp.gb28181.task.impl;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sip.*;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.Timer;
import java.util.TimerTask;
/**
* 目录订阅任务
* @author lin
*/
public class CatalogSubscribeTask implements ISubscribeTask {
private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
private Device device;
private final ISIPCommander sipCommander;
private SIPRequest request;
private DynamicTask dynamicTask;
private String taskKey = "catalog-subscribe-timeout";
public CatalogSubscribeTask(Device device, ISIPCommander sipCommander, DynamicTask dynamicTask) {
this.device = device;
this.sipCommander = sipCommander;
this.dynamicTask = dynamicTask;
}
@Override
public void run() {
if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey);
}
SIPRequest sipRequest = null;
try {
sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
ResponseEvent event = (ResponseEvent) eventResult.event;
// 成功
logger.info("[目录订阅]成功: {}", device.getDeviceId());
ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
try {
this.request.getToHeader().setTag(toHeader.getTag());
} catch (ParseException e) {
logger.info("[目录订阅]成功: 但为request设置ToTag失败");
this.request = null;
}
},eventResult -> {
this.request = null;
// 失败
logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 目录订阅: {}", e.getMessage());
}
if (sipRequest != null) {
this.request = sipRequest;
}
}
@Override
public void stop() {
/**
* dialog 的各个状态
* EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
* CONFIRMED-> Confirmed Dialog状态-已确认
* COMPLETED-> Completed Dialog状态-已完成
* TERMINATED-> Terminated Dialog状态-终止
*/
logger.info("取消目录订阅时dialog状态为{}", DialogState.CONFIRMED);
if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey);
}
device.setSubscribeCycleForCatalog(0);
try {
sipCommander.catalogSubscribe(device, request, eventResult -> {
ResponseEvent event = (ResponseEvent) eventResult.event;
if (event.getResponse().getRawContent() != null) {
// 成功
logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
}else {
// 成功
logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
}
},eventResult -> {
// 失败
logger.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 取消目录订阅: {}", e.getMessage());
}
}
}
@@ -1,44 +0,0 @@
package com.genersoft.iot.vmp.gb28181.task.impl;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import javax.sip.DialogState;
import java.util.List;
/**
* 向已经订阅(移动位置)的上级发送MobilePosition消息
* @author lin
*/
public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
private IPlatformService platformService;
private String platformId;
public MobilePositionSubscribeHandlerTask(String platformId) {
this.platformService = SpringBeanFactory.getBean("platformServiceImpl");
this.platformId = platformId;
}
@Override
public void run() {
platformService.sendNotifyMobilePosition(this.platformId);
}
@Override
public void stop() {
}
}
@@ -1,103 +0,0 @@
package com.genersoft.iot.vmp.gb28181.task.impl;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import javax.sip.*;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.Timer;
import java.util.TimerTask;
/**
* 移动位置订阅的定时更新
* @author lin
*/
public class MobilePositionSubscribeTask implements ISubscribeTask {
private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
private Device device;
private ISIPCommander sipCommander;
private SIPRequest request;
private DynamicTask dynamicTask;
private String taskKey = "mobile-position-subscribe-timeout";
public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander, DynamicTask dynamicTask) {
this.device = device;
this.sipCommander = sipCommander;
this.dynamicTask = dynamicTask;
}
@Override
public void run() {
if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey);
}
SIPRequest sipRequest = null;
try {
sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
// 成功
logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
ResponseEvent event = (ResponseEvent) eventResult.event;
ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
try {
this.request.getToHeader().setTag(toHeader.getTag());
} catch (ParseException e) {
logger.info("[移动位置订阅]成功: 为request设置ToTag失败");
this.request = null;
}
},eventResult -> {
this.request = null;
// 失败
logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 移动位置订阅: {}", e.getMessage());
}
if (sipRequest != null) {
this.request = sipRequest;
}
}
@Override
public void stop() {
/**
* dialog 的各个状态
* EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
* CONFIRMED-> Confirmed Dialog状态-已确认
* COMPLETED-> Completed Dialog状态-已完成
* TERMINATED-> Terminated Dialog状态-终止
*/
if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey);
}
device.setSubscribeCycleForMobilePosition(0);
try {
sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
ResponseEvent event = (ResponseEvent) eventResult.event;
if (event.getResponse().getRawContent() != null) {
// 成功
logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
}else {
// 成功
logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
}
},eventResult -> {
// 失败
logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 取消移动位置订阅: {}", e.getMessage());
}
}
}
@@ -1,7 +0,0 @@
package com.genersoft.iot.vmp.gb28181.transmit;
import javax.sip.SipListener;
public interface ISIPProcessorObserver extends SipListener {
}
@@ -1,205 +0,0 @@
package com.genersoft.iot.vmp.gb28181.transmit;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.sip.*;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.net.InetAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: SIP信令处理类观察者
* @author: panlinlin
* @date: 2021年11月5日 下午1532
*/
@Component
public class SIPProcessorObserver implements ISIPProcessorObserver {
private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class);
private static Map<String, ISIPRequestProcessor> requestProcessorMap = new ConcurrentHashMap<>();
private static Map<String, ISIPResponseProcessor> responseProcessorMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
private SipSubscribe sipSubscribe;
@Autowired
private EventPublisher eventPublisher;
/**
* 添加 request订阅
* @param method 方法名
* @param processor 处理程序
*/
public void addRequestProcessor(String method, ISIPRequestProcessor processor) {
requestProcessorMap.put(method, processor);
}
/**
* 添加 response订阅
* @param method 方法名
* @param processor 处理程序
*/
public void addResponseProcessor(String method, ISIPResponseProcessor processor) {
responseProcessorMap.put(method, processor);
}
/**
* 添加 超时事件订阅
* @param processor 处理程序
*/
public void addTimeoutProcessor(ITimeoutProcessor processor) {
timeoutProcessor = processor;
}
/**
* 分发RequestEvent事件
* @param requestEvent RequestEvent事件
*/
@Override
@Async("taskExecutor")
public void processRequest(RequestEvent requestEvent) {
String method = requestEvent.getRequest().getMethod();
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
if (sipRequestProcessor == null) {
logger.warn("不支持方法{}的request", method);
// TODO 回复错误玛
return;
}
requestProcessorMap.get(method).process(requestEvent);
}
/**
* 分发ResponseEvent事件
* @param responseEvent responseEvent事件
*/
@Override
@Async("taskExecutor")
public void processResponse(ResponseEvent responseEvent) {
Response response = responseEvent.getResponse();
int status = response.getStatusCode();
// Success
if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
String method = cseqHeader.getMethod();
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method);
if (sipRequestProcessor != null) {
sipRequestProcessor.process(responseEvent);
}
if (status != Response.UNAUTHORIZED && responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
if (callIdHeader != null) {
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
if (subscribe != null) {
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
subscribe.response(eventResult);
}
}
}
} else if ((status >= Response.TRYING) && (status < Response.OK)) {
// 增加其它无需回复的响应,如101、180等
} else {
logger.warn("接收到失败的response响应!status" + status + ",message:" + response.getReasonPhrase());
if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
if (callIdHeader != null) {
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
if (subscribe != null) {
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
subscribe.response(eventResult);
sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
}
}
}
if (responseEvent.getDialog() != null) {
responseEvent.getDialog().delete();
}
}
}
/**
* 向超时订阅发送消息
* @param timeoutEvent timeoutEvent事件
*/
@Override
public void processTimeout(TimeoutEvent timeoutEvent) {
logger.info("[消息发送超时]");
ClientTransaction clientTransaction = timeoutEvent.getClientTransaction();
if (clientTransaction != null) {
logger.info("[发送错误订阅] clientTransaction != null");
Request request = clientTransaction.getRequest();
if (request != null) {
logger.info("[发送错误订阅] request != null");
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
if (callIdHeader != null) {
logger.info("[发送错误订阅]");
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent);
if (subscribe != null){
subscribe.response(eventResult);
}
sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
}
}
}
eventPublisher.requestTimeOut(timeoutEvent);
}
@Override
public void processIOException(IOExceptionEvent exceptionEvent) {
System.out.println("processIOException");
}
@Override
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
// if (transactionTerminatedEvent.isServerTransaction()) {
// ServerTransaction serverTransaction = transactionTerminatedEvent.getServerTransaction();
// serverTransaction.get
// }
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
// transaction = transactionTerminatedEvent.getServerTransaction();
// }else {
// transaction = transactionTerminatedEvent.getClientTransaction();
// }
//
// System.out.println(transaction.getBranchId());
// System.out.println(transaction.getState());
// System.out.println(transaction.getRequest().getMethod());
// CallIdHeader header = (CallIdHeader)transaction.getRequest().getHeader(CallIdHeader.NAME);
// SipSubscribe.EventResult<TransactionTerminatedEvent> terminatedEventEventResult = new SipSubscribe.EventResult<>(transactionTerminatedEvent);
// sipSubscribe.getErrorSubscribe(header.getCallId()).response(terminatedEventEventResult);
}
@Override
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
}
@@ -1,132 +0,0 @@
package com.genersoft.iot.vmp.gb28181.transmit;
import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.SipProviderImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.sip.SipException;
import javax.sip.header.CallIdHeader;
import javax.sip.header.UserAgentHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Message;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
/**
* 发送SIP消息
* @author lin
*/
@Component
public class SIPSender {
private final Logger logger = LoggerFactory.getLogger(SIPSender.class);
@Autowired
private SipLayer sipLayer;
@Autowired
private GitUtil gitUtil;
@Autowired
private SipSubscribe sipSubscribe;
public void transmitRequest(String ip, Message message) throws SipException, ParseException {
transmitRequest(ip, message, null, null);
}
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent) throws SipException, ParseException {
transmitRequest(ip, message, errorEvent, null);
}
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException {
ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);
String transport = "UDP";
if (viaHeader == null) {
logger.warn("[消息头缺失] ViaHeader, 使用默认的UDP方式处理数据");
}else {
transport = viaHeader.getTransport();
}
if (message.getHeader(UserAgentHeader.NAME) == null) {
try {
message.addHeader(SipUtils.createUserAgentHeader(gitUtil));
} catch (ParseException e) {
logger.error("添加UserAgentHeader失败", e);
}
}
CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
// 添加错误订阅
if (errorEvent != null) {
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
errorEvent.response(eventResult);
sipSubscribe.removeErrorSubscribe(eventResult.callId);
sipSubscribe.removeOkSubscribe(eventResult.callId);
}));
}
// 添加订阅
if (okEvent != null) {
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
okEvent.response(eventResult);
sipSubscribe.removeOkSubscribe(eventResult.callId);
sipSubscribe.removeErrorSubscribe(eventResult.callId);
});
}
if ("TCP".equals(transport)) {
SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip);
if (tcpSipProvider == null) {
logger.error("[发送信息失败] 未找到tcp://{}的监听信息", ip);
return;
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
} else if ("UDP".equals(transport)) {
SipProviderImpl sipProvider = sipLayer.getUdpSipProvider(ip);
if (sipProvider == null) {
logger.error("[发送信息失败] 未找到udp://{}的监听信息", ip);
return;
}
if (message instanceof Request) {
sipProvider.sendRequest((Request)message);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
}
}
public CallIdHeader getNewCallIdHeader(String ip, String transport){
if (ObjectUtils.isEmpty(transport)) {
return sipLayer.getUdpSipProvider().getNewCallId();
}
SipProviderImpl sipProvider;
if (ObjectUtils.isEmpty(ip)) {
sipProvider = transport.equalsIgnoreCase("TCP") ? sipLayer.getTcpSipProvider()
: sipLayer.getUdpSipProvider();
}else {
sipProvider = transport.equalsIgnoreCase("TCP") ? sipLayer.getTcpSipProvider(ip)
: sipLayer.getUdpSipProvider(ip);
}
if (sipProvider == null) {
sipProvider = sipLayer.getUdpSipProvider();
}
if (sipProvider != null) {
return sipProvider.getNewCallId();
}else {
logger.warn("[新建CallIdHeader失败] ip={}, transport={}", ip, transport);
return null;
}
}
}
@@ -1,160 +0,0 @@
package com.genersoft.iot.vmp.gb28181.transmit.callback;
import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: 异步请求处理
* @author: swwheihei
* @date: 2020年5月8日 下午7:59:05
*/
@SuppressWarnings(value = {"rawtypes", "unchecked"})
@Component
public class DeferredResultHolder {
public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS";
public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL";
public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG";
public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD";
public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK";
public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY";
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL";
public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION";
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP";
private Map<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>();
public void put(String key, String id, DeferredResultEx result) {
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
if (deferredResultMap == null) {
deferredResultMap = new ConcurrentHashMap<>();
map.put(key, deferredResultMap);
}
deferredResultMap.put(id, result);
}
public void put(String key, String id, DeferredResult result) {
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
if (deferredResultMap == null) {
deferredResultMap = new ConcurrentHashMap<>();
map.put(key, deferredResultMap);
}
deferredResultMap.put(id, new DeferredResultEx(result));
}
public DeferredResultEx get(String key, String id) {
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
if (deferredResultMap == null || ObjectUtils.isEmpty(id)) {
return null;
}
return deferredResultMap.get(id);
}
public Collection<DeferredResultEx> getAllByKey(String key) {
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
if (deferredResultMap == null) {
return null;
}
return deferredResultMap.values();
}
public boolean exist(String key, String id){
if (key == null) {
return false;
}
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
if (id == null) {
return deferredResultMap != null;
}else {
return deferredResultMap != null && deferredResultMap.get(id) != null;
}
}
/**
* 释放单个请求
* @param msg
*/
public void invokeResult(RequestMessage msg) {
Map<String, DeferredResultEx> deferredResultMap = map.get(msg.getKey());
if (deferredResultMap == null) {
return;
}
DeferredResultEx result = deferredResultMap.get(msg.getId());
if (result == null) {
return;
}
result.getDeferredResult().setResult(msg.getData());
deferredResultMap.remove(msg.getId());
if (deferredResultMap.size() == 0) {
map.remove(msg.getKey());
}
}
/**
* 释放所有的请求
* @param msg
*/
public void invokeAllResult(RequestMessage msg) {
Map<String, DeferredResultEx> deferredResultMap = map.get(msg.getKey());
if (deferredResultMap == null) {
return;
}
synchronized (this) {
deferredResultMap = map.get(msg.getKey());
if (deferredResultMap == null) {
return;
}
Set<String> ids = deferredResultMap.keySet();
for (String id : ids) {
DeferredResultEx result = deferredResultMap.get(id);
if (result == null) {
return;
}
if (result.getFilter() != null) {
Object handler = result.getFilter().handler(msg.getData());
result.getDeferredResult().setResult(handler);
}else {
result.getDeferredResult().setResult(msg.getData());
}
}
map.remove(msg.getKey());
}
}
}

Some files were not shown because too many files have changed in this diff Show More