Merge branch 'main' into main2

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
结构优化
648540858 2023-02-10 16:25:33 +08:00
commit 197f80581b
95 changed files with 2184 additions and 1050 deletions
doc/_content/introduction

View File

@ -98,6 +98,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 支持推流鉴权
- [X] 支持接口鉴权
- [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载
- [X] 支持打包可执行jar和war
# 遇到问题如何解决

View File

@ -77,13 +77,18 @@ npm run build
**编译完成一般是这个样子,中间没有报红的错误信息**
![编译成功](_media/img.png)
### 5.3 打包项目, 生成可执行jar
### 5.3 生成可执行jar
```bash
cd wvp-GB28181-pro
mvn package
```
### 5.4 生成war
```bash
cd wvp-GB28181-pro
mvn package -P war
```
编译如果报错, 一般都是网络问题, 导致的依赖包下载失败
编译完成后在target目录下出现wvp-pro-***.jar。
编译完成后在target目录下出现wvp-pro-***.jar/wvp-pro-***.war
接下来[配置服务](./_content/introduction/config.md)

View File

@ -31,6 +31,7 @@ java -jar wvp-pro-*.jar
## 2 配置WVP-PRO
### 2.1 Mysql数据库配置
首先你需要创建一个名为wvp也可使用其他名字的数据库并使用sql/mysql.sql导入数据库初始化数据库结构。
(这里注意取决于版本新版的sql文件夹下有update.sql补丁包一定要注意运行导入)
在application-dev.yml中配置使用1.2方式的是在jar包的同级目录的application.yml配置数据库连接包括数据库连接信息密码。
### 2.2 Redis数据库配置
配置wvp中的redis连接信息建议wvp自己单独使用一个db。
@ -116,4 +117,4 @@ user-settings:
如果配置信息无误你可以启动zlm再启动wvp来测试了启动成功的话你可以在wvp的日志下看到zlm已连接的提示。
接下来[部署到服务器](./_content/introduction/deployment.md) 如何你只是本地运行直接再本地运行即可。
接下来[部署到服务器](./_content/introduction/deployment.md) 如何你只是本地运行直接再本地运行即可。

View File

@ -27,7 +27,9 @@
```shell
nohup java -jar wvp-pro-*.jar &
```
war包
下载Tomcat后将war包放入webapps中启动Tomcat以解压war包停止Tomcat后删除ROOT目录以及war包将解压后的war包目录重命名为ROOT
然后启动Tomcat。
**启动ZLM**
```shell
nohup ./MediaServer -d -m 3 &

39
pom.xml
View File

@ -14,6 +14,7 @@
<version>2.6.7</version>
<name>web video platform</name>
<description>国标28181视频平台</description>
<packaging>${project.packaging}</packaging>
<repositories>
<repository>
@ -56,6 +57,42 @@
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
</properties>
<profiles>
<profile>
<id>jar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<project.packaging>jar</project.packaging>
</properties>
</profile>
<profile>
<id>war</id>
<properties>
<project.packaging>war</project.packaging>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -242,8 +279,8 @@
<artifactId>spring-boot-starter-test</artifactId>
<!-- <scope>test</scope>-->
</dependency>
</dependencies>
</dependencies>
<build>

View File

@ -1,3 +0,0 @@
-- 2.6.6->2.6.7
alter table device
add keepaliveIntervalTime int default null;

View File

@ -1,20 +1,24 @@
package com.genersoft.iot.vmp;
import java.util.logging.LogManager;
import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport;
import com.genersoft.iot.vmp.storager.impl.RedisCatchStorageImpl;
import com.genersoft.iot.vmp.utils.GitUtil;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import java.util.Collections;
/**
*
*/
@ -22,7 +26,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@EnableDruidSupport
public class VManageBootstrap extends LogManager {
public class VManageBootstrap extends SpringBootServletInitializer {
private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class);
@ -41,6 +45,21 @@ public class VManageBootstrap extends LogManager {
context.close();
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(VManageBootstrap.class);
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.setSessionTrackingModes(
Collections.singleton(SessionTrackingMode.COOKIE)
);
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(true);
}
}

View File

@ -0,0 +1,77 @@
package com.genersoft.iot.vmp.common.enums;
import org.dom4j.Element;
import org.springframework.util.ObjectUtils;
/**
* @author gaofuwang
* @date 2023/01/18/ 10:09:00
* @since 1.0
*/
public enum DeviceControlType {
/**
*
*
*/
PTZ("PTZCmd","云台控制"),
/**
*
*/
TELE_BOOT("TeleBoot","远程启动"),
/**
*
*/
RECORD("RecordCmd","录像控制"),
/**
*
*/
GUARD("GuardCmd","布防撤防"),
/**
*
*/
ALARM("AlarmCmd","告警控制"),
/**
*
*/
I_FRAME("IFameCmd","强制关键帧"),
/**
*
*/
DRAG_ZOOM_IN("DragZoomIn","拉框放大"),
/**
*
*/
DRAG_ZOOM_OUT("DragZoomOut","拉框缩小"),
/**
*
*/
HOME_POSITION("HomePosition","看守位");
private final String val;
private final String desc;
DeviceControlType(String val, String desc) {
this.val = val;
this.desc = desc;
}
public String getVal() {
return val;
}
public String getDesc() {
return desc;
}
public static DeviceControlType typeOf(Element rootElement) {
for (DeviceControlType item : DeviceControlType.values()) {
if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) {
return item;
}
}
return null;
}
}

View File

@ -10,6 +10,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter;
@ -23,6 +24,7 @@ import java.io.IOException;
* @author lin
*/
@WebFilter(filterName = "ApiAccessFilter", urlPatterns = "/api/*", asyncSupported=true)
@Component
public class ApiAccessFilter extends OncePerRequestFilter {
private final static Logger logger = LoggerFactory.getLogger(ApiAccessFilter.class);
@ -48,7 +50,7 @@ public class ApiAccessFilter extends OncePerRequestFilter {
filterChain.doFilter(servletRequest, servletResponse);
if (uriName != null && userSetting.getLogInDatebase()) {
if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) {
LogDto logDto = new LogDto();
logDto.setName(uriName);

View File

@ -2,7 +2,6 @@ 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.catalina.connector.ClientAbortException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
@ -15,11 +14,9 @@ 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 org.springframework.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.ConnectException;
@ -77,9 +74,7 @@ public class ProxyServletConfig {
} catch (IOException ioException) {
if (ioException instanceof ConnectException) {
logger.error("zlm 连接失败");
} else if (ioException instanceof ClientAbortException) {
logger.error("zlm: 用户已中断连接,代理终止");
} else {
} else {
logger.error("zlm 代理失败: ", e);
}
} catch (RuntimeException exception){
@ -195,9 +190,7 @@ public class ProxyServletConfig {
} catch (IOException ioException) {
if (ioException instanceof ConnectException) {
logger.error("录像服务 连接失败");
} else if (ioException instanceof ClientAbortException) {
logger.error("录像服务:用户已中断连接,代理终止");
} else {
}else {
logger.error("录像服务 代理失败: ", e);
}
} catch (RuntimeException exception){

View File

@ -0,0 +1,30 @@
package com.genersoft.iot.vmp.conf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ServiceInfo implements ApplicationListener<WebServerInitializedEvent> {
private final Logger logger = LoggerFactory.getLogger(ServiceInfo.class);
private static int serverPort;
public static int getServerPort() {
return serverPort;
}
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
// 项目启动获取启动的端口号
ServiceInfo.serverPort = event.getWebServer().getPort();
logger.info("项目启动获取启动的端口号: " + ServiceInfo.serverPort);
}
public void setServerPort(int serverPort) {
ServiceInfo.serverPort = serverPort;
}
}

View File

@ -1,24 +0,0 @@
package com.genersoft.iot.vmp.conf.security;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import java.util.Collections;
public class UrlTokenHandler extends SpringBootServletInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.setSessionTrackingModes(
Collections.singleton(SessionTrackingMode.COOKIE)
);
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(true);
}
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* redis
*/
@ -8,12 +9,14 @@ public class AlarmChannelMessage {
*
*/
private String gbId;
/**
*
*/
private int alarmSn;
/**
*
*/
private int alarmType;
/**
*
@ -36,6 +39,14 @@ public class AlarmChannelMessage {
this.alarmSn = alarmSn;
}
public int getAlarmType() {
return alarmType;
}
public void setAlarmType(int alarmType) {
this.alarmType = alarmType;
}
public String getAlarmDescription() {
return alarmDescription;
}

View File

@ -37,4 +37,18 @@ public enum DeviceAlarmMethod {
public int getVal() {
return val;
}
/**
*
* @param code
* @return
*/
public static DeviceAlarmMethod typeOf(int code) {
for (DeviceAlarmMethod item : DeviceAlarmMethod.values()) {
if (code==item.getVal()) {
return item;
}
}
return null;
}
}

View File

@ -0,0 +1,143 @@
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;
}
}

View File

@ -0,0 +1,94 @@
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;
}
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.bean;
import java.time.Instant;
import java.util.List;
@ -20,6 +21,8 @@ public class RecordInfo {
private int sumNum;
private int count;
private Instant lastTime;
private List<RecordItem> recordList;
@ -79,4 +82,12 @@ public class RecordInfo {
public void setLastTime(Instant lastTime) {
this.lastTime = lastTime;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}

View File

@ -1,8 +1,10 @@
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;
@ -20,25 +22,46 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
private final static Logger logger = LoggerFactory.getLogger(RecordEndEventListener.class);
private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
public interface RecordEndEventHandler{
void handler(RecordInfo recordInfo);
}
private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
@Override
public void onApplicationEvent(RecordEndEvent event) {
logger.info("录像查询完成事件触发deviceId{}, channelId: {}, 录像数量{}条", event.getRecordInfo().getDeviceId(),
event.getRecordInfo().getChannelId(), event.getRecordInfo().getSumNum() );
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) {
for (RecordEndEventHandler recordEndEventHandler : handlerMap.values()) {
recordEndEventHandler.handler(event.getRecordInfo());
RecordEndEventHandler handler = handlerMap.get(deviceId + channelId);
if (handler !=null){
handler.handler(event.getRecordInfo());
if (count ==sumNum){
handlerMap.remove(deviceId + channelId);
}
}
}
handlerMap.clear();
}
/**
*
* @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);
}
}

View File

@ -109,12 +109,18 @@ public class CatalogDataCatch {
for (String deviceId : keys) {
CatalogData catalogData = data.get(deviceId);
if ( catalogData.getLastTime().isBefore(instantBefore5S)) { // 超过五秒收不到消息任务超时, 只更新这一部分数据
if ( catalogData.getLastTime().isBefore(instantBefore5S)) {
// 超过五秒收不到消息任务超时, 只更新这一部分数据, 收到数据与声明的总数一致,则重置通道数据,数据不全则只对收到的数据做更新操作
if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) {
storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
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()) {
String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条";
catalogData.setErrorMsg(errorMsg);
}
}else if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.ready)) {
String errorMsg = "同步失败,等待回复超时";

View File

@ -1,6 +1,7 @@
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;
@ -23,14 +24,17 @@ public class RecordDataCatch {
@Autowired
private DeferredResultHolder deferredResultHolder;
@Autowired
private RecordEndEventListener recordEndEventListener;
public int put(String deviceId, String sn, int sumNum, List<RecordItem> recordItems) {
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<>()));
@ -67,6 +71,7 @@ public class RecordDataCatch {
msg.setKey(msgKey);
msg.setData(recordInfo);
deferredResultHolder.invokeAllResult(msg);
recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId());
data.remove(key);
}
}

View File

@ -4,6 +4,7 @@ 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;
@ -134,7 +135,7 @@ public class VideoStreamSessionManager {
List<SsrcTransaction> result= new ArrayList<>();
for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
String key = (String)ssrcTransactionKeys.get(i);
SsrcTransaction ssrcTransaction = (SsrcTransaction)RedisUtil.get(key);
SsrcTransaction ssrcTransaction = JsonUtil.redisJsonToObject(key, SsrcTransaction.class);
result.add(ssrcTransaction);
}
return result;

View File

@ -47,61 +47,65 @@ public class SIPSender {
}
public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
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(sipLayer.getSipFactory(), gitUtil));
} catch (ParseException e) {
logger.error("添加UserAgentHeader失败", e);
try {
ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);
String transport = "UDP";
if (viaHeader == null) {
logger.warn("[消息头缺失] ViaHeader 使用默认的UDP方式处理数据");
}else {
transport = viaHeader.getTransport();
}
}
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);
if (message.getHeader(UserAgentHeader.NAME) == null) {
try {
message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
} catch (ParseException e) {
logger.error("添加UserAgentHeader失败", e);
}
}
} else if ("UDP".equals(transport)) {
SipProviderImpl sipProvider = sipLayer.getUdpSipProvider(ip);
if (sipProvider == null) {
logger.error("[发送信息失败] 未找到udp://{}的监听信息", ip);
return;
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 (message instanceof Request) {
sipProvider.sendRequest((Request)message);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
// 添加订阅
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);
}
}
} finally {
logger.info("[SEND]:SUCCESS:{}", message);
}
}

View File

@ -182,7 +182,7 @@ public interface ISIPCommander {
* @param channelId
* @param recordCmdStr Record / StopRecord
*/
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
/**
*
@ -196,7 +196,7 @@ public interface ISIPCommander {
*
* @param device
*/
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
/**
*
@ -205,7 +205,7 @@ public interface ISIPCommander {
* @param alarmMethod
* @param alarmType
*/
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* ,IDR
@ -214,17 +214,19 @@ public interface ISIPCommander {
* @param channelId
*/
void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
/**
*
*
* @param device
* @param enabled 使1 = 0 =
* @param resetTime 使:(s)
* @param presetIndex 使0~255
*
* @param device
* @param channelId id
* @param frontCmd
* @param enabled 使1 = 0 =
* @param resetTime 使:(s)
* @param presetIndex 使0~255
*/
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
/**
*
*

View File

@ -69,12 +69,11 @@ public interface ISIPCommanderForPlatform {
* DeviceInfo
*
* @param parentPlatform
* @param sn
* @param fromTag
* @param sn SN
* @param fromTag FROMtag
* @return
*/
void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag)
throws SipException, InvalidArgumentException, ParseException;
void deviceInfoResponse(ParentPlatform parentPlatform,Device device, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
/**
* DeviceStatus

View File

@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
@ -711,7 +712,7 @@ public class SIPCommander implements ISIPCommander {
* @param recordCmdStr Record / StopRecord
*/
@Override
public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset();
cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
@ -729,7 +730,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
}
/**
@ -763,7 +764,7 @@ public class SIPCommander implements ISIPCommander {
* @param guardCmdStr "SetGuard"/"ResetGuard"
*/
@Override
public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset();
@ -778,7 +779,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
}
/**
@ -787,7 +788,7 @@ public class SIPCommander implements ISIPCommander {
* @param device
*/
@Override
public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset();
@ -814,7 +815,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
}
/**
@ -850,12 +851,14 @@ public class SIPCommander implements ISIPCommander {
*
*
* @param device
* @param channelId id
* @param frontCmd
* @param enabled 使1 = 0 =
* @param resetTime 使:(s)
* @param presetIndex 使0~255
*/
@Override
public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
StringBuffer cmdXml = new StringBuffer(200);
String charset = device.getCharset();
@ -890,7 +893,7 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
}
/**

View File

@ -81,6 +81,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
@Autowired
private VideoStreamSessionManager streamSession;
@Autowired
private DynamicTask dynamicTask;
@Override
public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
register(parentPlatform, null, null, errorEvent, okEvent, false, true);
@ -129,13 +132,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer keepaliveXml = new StringBuffer(200);
keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
keepaliveXml.append("<Notify>\r\n");
keepaliveXml.append("<CmdType>Keepalive</CmdType>\r\n");
keepaliveXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
keepaliveXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
keepaliveXml.append("<Status>OK</Status>\r\n");
keepaliveXml.append("</Notify>\r\n");
keepaliveXml.append("<?xml version=\"1.0\" encoding=\"")
.append(characterSet).append("\"?>\r\n")
.append("<Notify>\r\n")
.append("<CmdType>Keepalive</CmdType>\r\n")
.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n")
.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
.append("<Status>OK</Status>\r\n")
.append("</Notify>\r\n");
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
@ -153,7 +157,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
*
* @param channel
* @param parentPlatform
* @return
*/
@Override
public void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException {
@ -180,18 +183,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
if ( parentPlatform ==null) {
return ;
}
sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0, true);
}
private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer catalogXml = new StringBuffer(600);
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet +"\"?>\r\n");
catalogXml.append("<Response>\r\n");
catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
catalogXml.append("<SN>" +sn + "</SN>\r\n");
catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");
catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet +"\"?>\r\n")
.append("<Response>\r\n")
.append("<CmdType>Catalog</CmdType>\r\n")
.append("<SN>" +sn + "</SN>\r\n")
.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
.append("<SumNum>" + size + "</SumNum>\r\n")
.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
if (channels.size() > 0) {
for (DeviceChannel channel : channels) {
if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
@ -242,7 +245,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return catalogXml.toString();
}
private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) throws SipException, InvalidArgumentException, ParseException {
private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index, boolean sendAfterResponse) throws SipException, InvalidArgumentException, ParseException {
if (index >= channels.size()) {
return;
}
@ -256,15 +259,49 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
// callid
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, eventResult -> {
int indexNext = index + parentPlatform.getCatalogGroup();
try {
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
}
});
SIPRequest request = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
String timeoutTaskKey = "catalog_task_" + parentPlatform.getServerGBId() + sn;
String callId = request.getCallIdHeader().getCallId();
if (sendAfterResponse) {
// 默认按照收到200回复后发送下一条 如果超时收不到回复就以30毫秒的间隔直接发送。
dynamicTask.startDelay(timeoutTaskKey, ()->{
sipSubscribe.removeOkSubscribe(callId);
int indexNext = index + parentPlatform.getCatalogGroup();
try {
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, false);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
}
}, 3000);
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, eventResult -> {
logger.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
dynamicTask.stop(timeoutTaskKey);
}, eventResult -> {
dynamicTask.stop(timeoutTaskKey);
int indexNext = index + parentPlatform.getCatalogGroup();
try {
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, true);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
}
});
}else {
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, eventResult -> {
logger.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
dynamicTask.stop(timeoutTaskKey);
}, null);
dynamicTask.startDelay(timeoutTaskKey, ()->{
int indexNext = index + parentPlatform.getCatalogGroup();
try {
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, false);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
}
}, 30);
}
}
/**
@ -275,7 +312,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return
*/
@Override
public void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
public void deviceInfoResponse(ParentPlatform parentPlatform,Device device, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) {
return;
}
@ -285,11 +322,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
deviceInfoXml.append("<Response>\r\n");
deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n");
deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n");
deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n");
deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n");
deviceInfoXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
deviceInfoXml.append("<DeviceName>" + device.getName() + "</DeviceName>\r\n");
deviceInfoXml.append("<Manufacturer>" + device.getManufacturer() + "</Manufacturer>\r\n");
deviceInfoXml.append("<Model>" + device.getModel() + "</Model>\r\n");
deviceInfoXml.append("<Firmware>" + device.getFirmware() + "</Firmware>\r\n");
deviceInfoXml.append("<Result>OK</Result>\r\n");
deviceInfoXml.append("</Response>\r\n");
@ -314,15 +351,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
String statusStr = (status==1)?"ONLINE":"OFFLINE";
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<Response>\r\n");
deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
deviceStatusXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
deviceStatusXml.append("<Result>OK</Result>\r\n");
deviceStatusXml.append("<Online>"+statusStr+"</Online>\r\n");
deviceStatusXml.append("<Status>OK</Status>\r\n");
deviceStatusXml.append("</Response>\r\n");
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Response>\r\n")
.append("<CmdType>DeviceStatus</CmdType>\r\n")
.append("<SN>" +sn + "</SN>\r\n")
.append("<DeviceID>" + channelId + "</DeviceID>\r\n")
.append("<Result>OK</Result>\r\n")
.append("<Online>"+statusStr+"</Online>\r\n")
.append("<Status>OK</Status>\r\n")
.append("</Response>\r\n");
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
@ -341,18 +378,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<Notify>\r\n");
deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");
deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");
deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");
deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");
deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");
deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");
deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
deviceStatusXml.append("</Notify>\r\n");
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Notify>\r\n")
.append("<CmdType>MobilePosition</CmdType>\r\n")
.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n")
.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n")
.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n")
.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n")
.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n")
.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n")
.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n")
.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n")
.append("</Notify>\r\n");
sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
@ -369,21 +406,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm));
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<Notify>\r\n");
deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
deviceStatusXml.append("<info>\r\n");
deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
deviceStatusXml.append("</info>\r\n");
deviceStatusXml.append("</Notify>\r\n");
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Notify>\r\n")
.append("<CmdType>Alarm</CmdType>\r\n")
.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n")
.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n")
.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n")
.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n")
.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n")
.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n")
.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n")
.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n")
.append("<info>\r\n")
.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n")
.append("</info>\r\n")
.append("</Notify>\r\n");
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
@ -442,13 +479,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
StringBuffer catalogXml = new StringBuffer(600);
String characterSet = parentPlatform.getCharacterSet();
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
catalogXml.append("<Notify>\r\n");
catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
catalogXml.append("<SumNum>1</SumNum>\r\n");
catalogXml.append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Notify>\r\n")
.append("<CmdType>Catalog</CmdType>\r\n")
.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n")
.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
.append("<SumNum>1</SumNum>\r\n")
.append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
if (channels.size() > 0) {
for (DeviceChannel channel : channels) {
if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
@ -469,16 +506,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParental() == 0) {
// 通道项
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n")
.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n")
.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n")
.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n")
.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n")
.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n")
.append("<Address>" + channel.getAddress() + "</Address>\r\n");
}
if (!"presence".equals(subscribeInfo.getEventType())) {
catalogXml.append("<Event>" + type + "</Event>\r\n");
@ -488,8 +525,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("</Item>\r\n");
}
}
catalogXml.append("</DeviceList>\r\n");
catalogXml.append("</Notify>\r\n");
catalogXml.append("</DeviceList>\r\n")
.append("</Notify>\r\n");
return catalogXml.toString();
}
@ -535,26 +572,26 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer catalogXml = new StringBuffer(600);
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
catalogXml.append("<Notify>\r\n");
catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
catalogXml.append("<SumNum>1</SumNum>\r\n");
catalogXml.append("<DeviceList Num=\" " + channels.size() + " \">\r\n");
catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Notify>\r\n")
.append("<CmdType>Catalog</CmdType>\r\n")
.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n")
.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
.append("<SumNum>1</SumNum>\r\n")
.append("<DeviceList Num=\" " + channels.size() + " \">\r\n");
if (channels.size() > 0) {
for (DeviceChannel channel : channels) {
if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
channel.setParentId(parentPlatform.getDeviceGBId());
}
catalogXml.append("<Item>\r\n");
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
catalogXml.append("<Event>" + type + "</Event>\r\n");
catalogXml.append("</Item>\r\n");
catalogXml.append("<Item>\r\n")
.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n")
.append("<Event>" + type + "</Event>\r\n")
.append("</Item>\r\n");
}
}
catalogXml.append("</DeviceList>\r\n");
catalogXml.append("</Notify>\r\n");
catalogXml.append("</DeviceList>\r\n")
.append("</Notify>\r\n");
return catalogXml.toString();
}
@Override
@ -564,12 +601,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}
String characterSet = parentPlatform.getCharacterSet();
StringBuffer recordXml = new StringBuffer(600);
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
recordXml.append("<Response>\r\n");
recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");
recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");
recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n");
recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Response>\r\n")
.append("<CmdType>RecordInfo</CmdType>\r\n")
.append("<SN>" +recordInfo.getSn() + "</SN>\r\n")
.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n")
.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
if (recordInfo.getRecordList() == null ) {
recordXml.append("<RecordList Num=\"0\">\r\n");
}else {
@ -578,12 +615,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
for (RecordItem recordItem : recordInfo.getRecordList()) {
recordXml.append("<Item>\r\n");
if (deviceChannel != null) {
recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n");
recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n");
recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n");
recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");
recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");
recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");
recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n")
.append("<Name>" + recordItem.getName() + "</Name>\r\n")
.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n")
.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n")
.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n")
.append("<Type>" + recordItem.getType() + "</Type>\r\n");
if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {
recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");
}
@ -596,8 +633,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}
}
recordXml.append("</RecordList>\r\n");
recordXml.append("</Response>\r\n");
recordXml.append("</RecordList>\r\n")
.append("</Response>\r\n");
// callid
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
@ -616,13 +653,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer mediaStatusXml = new StringBuffer(200);
mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
mediaStatusXml.append("<Notify>\r\n");
mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");
mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
mediaStatusXml.append("</Notify>\r\n");
mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
.append("<Notify>\r\n")
.append("<CmdType>MediaStatus</CmdType>\r\n")
.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n")
.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n")
.append("<NotifyType>121</NotifyType>\r\n")
.append("</Notify>\r\n");
SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(parentPlatform, mediaStatusXml.toString(),
sendRtpItem);

View File

@ -16,7 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.ExpiresHeader;
@ -42,15 +41,6 @@ public abstract class SIPRequestProcessorParent {
@Autowired
private SIPSender sipSender;
public AddressFactory getAddressFactory() {
try {
return SipFactory.getInstance().createAddressFactory();
} catch (PeerUnavailableException e) {
e.printStackTrace();
}
return null;
}
public HeaderFactory getHeaderFactory() {
try {
return SipFactory.getInstance().createHeaderFactory();

View File

@ -275,7 +275,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}
return;
} else {
logger.info("通道不存在返回404");
logger.info("通道不存在返回404: {}", channelId);
try {
// 通道不存在发404资源不存在
responseAck(request, Response.NOT_FOUND);

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
import com.genersoft.iot.vmp.conf.ServiceInfo;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
@ -82,6 +83,19 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
RequestEventExt evtExt = (RequestEventExt) evt;
String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
logger.info("[注册请求] 开始处理: {}", requestAddress);
// MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
// QueryExp protocol = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"));
//// ObjectName name = new ObjectName("*:type=Connector,*");
// ObjectName name = new ObjectName("*:*");
// Set<ObjectName> objectNames = beanServer.queryNames(name, protocol);
// for (ObjectName objectName : objectNames) {
// String catalina = objectName.getDomain();
// if ("Catalina".equals(catalina)) {
// System.out.println(objectName.getKeyProperty("port"));
// }
// }
System.out.println(ServiceInfo.getServerPort());
SIPRequest request = (SIPRequest)evt.getRequest();
Response response = null;
boolean passwordCorrect = false;

View File

@ -1,8 +1,11 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.cmd;
import com.genersoft.iot.vmp.VManageBootstrap;
import com.genersoft.iot.vmp.common.enums.DeviceControlType;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DragZoomRequest;
import com.genersoft.iot.vmp.gb28181.bean.HomePositionRequest;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@ -19,17 +22,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.*;
import javax.sip.address.SipURI;
import javax.sip.header.HeaderAddress;
import javax.sip.header.ToHeader;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
@Component
public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@ -81,7 +81,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
}
taskExecutor.execute(()->{
taskExecutor.execute(() -> {
// 远程启动
// try {
// Thread.sleep(3000);
@ -101,13 +101,12 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
// logger.error("[任务执行失败] 服务重启: {}", e.getMessage());
// }
});
} else {
// 远程启动指定设备
}
}
// 云台/前端控制命令
if (!ObjectUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) {
String cmdString = getText(rootElement,"PTZCmd");
DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement);
logger.info("[接受deviceControl命令] 命令: {}", deviceControlType);
if (!ObjectUtils.isEmpty(deviceControlType) && !parentPlatform.getServerGBId().equals(targetGBId)) {
//判断是否存在该通道
Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
if (deviceForPlatform == null) {
try {
@ -117,25 +116,240 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
}
return;
}
try {
cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
// 失败的回复
try {
responseAck(request, eventResult.statusCode, eventResult.msg);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
}
}, eventResult -> {
// 成功的回复
try {
responseAck(request, eventResult.statusCode);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
}
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
switch (deviceControlType) {
case PTZ:
handlePtzCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.PTZ);
break;
case ALARM:
handleAlarmCmd(deviceForPlatform, rootElement, request);
break;
case GUARD:
handleGuardCmd(deviceForPlatform, rootElement, request, DeviceControlType.GUARD);
break;
case RECORD:
handleRecordCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.RECORD);
break;
case I_FRAME:
handleIFameCmd(deviceForPlatform, request, channelId);
break;
case TELE_BOOT:
handleTeleBootCmd(deviceForPlatform, request);
break;
case DRAG_ZOOM_IN:
handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_IN);
break;
case DRAG_ZOOM_OUT:
handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_OUT);
break;
case HOME_POSITION:
handleHomePositionCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.HOME_POSITION);
break;
default:
break;
}
}
}
/**
*
*
* @param device
* @param channelId id
* @param rootElement
* @param request
*/
private void handlePtzCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
String cmdString = getText(rootElement, type.getVal());
try {
cmder.fronEndCmd(device, channelId, cmdString,
errorResult -> onError(request, errorResult),
okResult -> onOk(request, okResult));
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
}
}
/**
*
*
* @param device
* @param channelId id
*/
private void handleIFameCmd(Device device, SIPRequest request, String channelId) {
try {
cmder.iFrameCmd(device, channelId);
responseAck(request, Response.OK);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
}
}
/**
*
*
* @param device
*/
private void handleTeleBootCmd(Device device, SIPRequest request) {
try {
cmder.teleBootCmd(device);
responseAck(request, Response.OK);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 重启: {}", e.getMessage());
}
}
/**
* ***
*
* @param device
* @param channelId id
* @param rootElement
* @param type
*/
private void handleDragZoom(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
try {
DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class);
DragZoomRequest.DragZoom dragZoom = dragZoomRequest.getDragZoomIn();
if (dragZoom == null) {
dragZoom = dragZoomRequest.getDragZoomOut();
}
StringBuffer cmdXml = new StringBuffer(200);
cmdXml.append("<" + type.getVal() + ">\r\n");
cmdXml.append("<Length>" + dragZoom.getLength() + "</Length>\r\n");
cmdXml.append("<Width>" + dragZoom.getWidth() + "</Width>\r\n");
cmdXml.append("<MidPointX>" + dragZoom.getMidPointX() + "</MidPointX>\r\n");
cmdXml.append("<MidPointY>" + dragZoom.getMidPointY() + "</MidPointY>\r\n");
cmdXml.append("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n");
cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n");
cmdXml.append("</" + type.getVal() + ">\r\n");
cmder.dragZoomCmd(device, channelId, cmdXml.toString());
responseAck(request, Response.OK);
} catch (Exception e) {
logger.error("[命令发送失败] 拉框控制: {}", e.getMessage());
}
}
/**
* ***
*
* @param device
* @param channelId id
* @param rootElement
* @param request
* @param type
*/
private void handleHomePositionCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
try {
HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class);
//获取整个消息主体,我们只需要修改请求头即可
HomePositionRequest.HomePosition info = homePosition.getHomePosition();
cmder.homePositionCmd(device, channelId, info.getEnabled(), info.getResetTime(), info.getPresetIndex(),
errorResult -> onError(request, errorResult),
okResult -> onOk(request, okResult));
} catch (Exception e) {
logger.error("[命令发送失败] 看守位设置: {}", e.getMessage());
}
}
/**
* ***
*
* @param device
* @param rootElement
* @param request
*/
private void handleAlarmCmd(Device device, Element rootElement, SIPRequest request) {
//告警方法
String alarmMethod = "";
//告警类型
String alarmType = "";
List<Element> info = rootElement.elements("Info");
if (info != null) {
for (Element element : info) {
alarmMethod = getText(element, "AlarmMethod");
alarmType = getText(element, "AlarmType");
}
}
try {
cmder.alarmCmd(device, alarmMethod, alarmType,
errorResult -> onError(request, errorResult),
okResult -> onOk(request, okResult));
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 告警消息: {}", e.getMessage());
}
}
/**
*
*
* @param device
* @param channelId id
* @param rootElement
* @param request
* @param type
*/
private void handleRecordCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
//获取整个消息主体,我们只需要修改请求头即可
String cmdString = getText(rootElement, type.getVal());
try {
cmder.recordCmd(device, channelId, cmdString,
errorResult -> onError(request, errorResult),
okResult -> onOk(request, okResult));
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 录像控制: {}", e.getMessage());
}
}
/**
* /
*
* @param device
* @param rootElement
* @param request
* @param type
*/
private void handleGuardCmd(Device device, Element rootElement, SIPRequest request, DeviceControlType type) {
//获取整个消息主体,我们只需要修改请求头即可
String cmdString = getText(rootElement, type.getVal());
try {
cmder.guardCmd(device, cmdString,
errorResult -> onError(request, errorResult),
okResult -> onOk(request, okResult));
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 布防/撤防命令: {}", e.getMessage());
}
}
/**
*
*
* @param request
* @param eventResult
*/
private void onError(SIPRequest request, SipSubscribe.EventResult eventResult) {
// 失败的回复
try {
responseAck(request, eventResult.statusCode, eventResult.msg);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 回复: {}", e.getMessage());
}
}
/**
*
*
* @param request
* @param eventResult
*/
private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult) {
// 成功的回复
try {
responseAck(request, eventResult.statusCode);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 回复: {}", e.getMessage());
}
}
}

View File

@ -181,11 +181,14 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
}
}
logger.info("[收到报警通知]内容:{}", JSON.toJSONString(deviceAlarm));
if ("7".equals(deviceAlarm.getAlarmMethod()) ) {
// 作者自用判断其他小伙伴需要此消息可以自行修改但是不要提在pr里
if (DeviceAlarmMethod.Other.getVal() == Integer.parseInt(deviceAlarm.getAlarmMethod())) {
// 发送给平台的报警信息。 发送redis通知
logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm));
AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType()));
alarmChannelMessage.setGbId(channelId);
redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
continue;
@ -264,6 +267,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
alarmChannelMessage.setGbId(channelId);
alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType()));
redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
return;
}

View File

@ -1,9 +1,10 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
@ -63,7 +64,6 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
@Override
public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId();
FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
try {
// 回复200 OK

View File

@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element;
import org.slf4j.Logger;
@ -21,6 +22,8 @@ import javax.sip.header.FromHeader;
import javax.sip.message.Response;
import java.text.ParseException;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
@Component
public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@ -32,6 +35,8 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
@Autowired
private SIPCommanderFroPlatform cmderFroPlatform;
@Autowired
private IVideoManagerStorage storager;
@Override
public void afterPropertiesSet() throws Exception {
@ -52,10 +57,20 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
responseAck((SIPRequest) evt.getRequest(), Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] DeviceInfo查询回复: {}", e.getMessage());
return;
}
String sn = rootElement.element("SN").getText();
/*WVP
NVR/IPCNVR/IPC使
使*/
String channelId = getText(rootElement, "DeviceID");
Device device = storager.queryDeviceInfoByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
if (device ==null){
logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId);
return;
}
try {
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
cmderFroPlatform.deviceInfoResponse(parentPlatform,device, sn, fromHeader.getTag());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage());
}

View File

@ -102,8 +102,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
Element recordListElement = rootElementForCharset.element("RecordList");
if (recordListElement == null || sumNum == 0) {
logger.info("无录像数据");
int count = recordDataCatch.put(take.getDevice().getDeviceId(),channelId, sn, sumNum, new ArrayList<>());
recordInfo.setCount(count);
eventPublisher.recordEndEventPush(recordInfo);
recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, new ArrayList<>());
releaseRequest(take.getDevice().getDeviceId(), sn);
} else {
Iterator<Element> recordListIterator = recordListElement.elementIterator();
@ -137,12 +138,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
recordList.add(record);
}
recordInfo.setRecordList(recordList);
int count = recordDataCatch.put(take.getDevice().getDeviceId(),channelId, sn, sumNum, recordList);recordInfo.setCount(count);
logger.info("[国标录像] {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum);
// 发送消息,如果是上级查询此录像,则会通过这里通知给上级
eventPublisher.recordEndEventPush(recordInfo);
int count = recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, recordList);
logger.info("[国标录像] {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum);
}
if (recordDataCatch.isComplete(take.getDevice().getDeviceId(), sn)){
releaseRequest(take.getDevice().getDeviceId(), sn);
}

View File

@ -0,0 +1,17 @@
package com.genersoft.iot.vmp.gb28181.utils;
import java.lang.annotation.*;
/**
* @author gaofuwang
* @version 1.0
* @date 2022/6/28 14:58
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MessageElement {
String value();
String subVal() default "";
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.utils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -15,12 +16,16 @@ import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.ReflectionUtils;
import javax.sip.RequestEvent;
import javax.sip.message.Request;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/**
@ -411,4 +416,76 @@ public class XmlUtil {
}
return deviceChannel;
}
/**
*
*
* @param element xmlElement
* @param clazz
* @param <T>
* @return
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static <T> T loadElement(Element element, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Field[] fields = clazz.getDeclaredFields();
T t = clazz.getDeclaredConstructor().newInstance();
for (Field field : fields) {
ReflectionUtils.makeAccessible(field);
MessageElement annotation = field.getAnnotation(MessageElement.class);
if (annotation == null) {
continue;
}
String value = annotation.value();
String subVal = annotation.subVal();
Element element1 = element.element(value);
if (element1 == null) {
continue;
}
if ("".equals(subVal)) {
// 无下级数据
Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType());
Object o = simpleTypeDeal(field.getType(), fieldVal);
ReflectionUtils.setField(field, t, o);
} else {
// 存在下级数据
ArrayList<Object> list = new ArrayList<>();
Type genericType = field.getGenericType();
if (!(genericType instanceof ParameterizedType)) {
continue;
}
Class<?> aClass = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
for (Element element2 : element1.elements(subVal)) {
list.add(loadElement(element2, aClass));
}
ReflectionUtils.setField(field, t, list);
}
}
return t;
}
/**
*
*
* @param tClass
* @param val
* @return
*/
private static Object simpleTypeDeal(Class<?> tClass, Object val) {
if (tClass.equals(String.class)) {
return val.toString();
}
if (tClass.equals(Integer.class)) {
return Integer.valueOf(val.toString());
}
if (tClass.equals(Double.class)) {
return Double.valueOf(val.toString());
}
if (tClass.equals(Long.class)) {
return Long.valueOf(val.toString());
}
return val;
}
}

View File

@ -36,7 +36,7 @@ public class ZLMRESTfulUtils {
// 设置连接超时时间
httpClientBuilder.connectTimeout(5,TimeUnit.SECONDS);
// 设置读取超时时间
httpClientBuilder.readTimeout(15,TimeUnit.SECONDS);
httpClientBuilder.readTimeout(10,TimeUnit.SECONDS);
// 设置连接池
httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES));
if (logger.isDebugEnabled()) {
@ -189,6 +189,7 @@ public class ZLMRESTfulUtils {
FileOutputStream outStream = new FileOutputStream(snapFile);
outStream.write(Objects.requireNonNull(response.body()).bytes());
outStream.flush();
outStream.close();
} else {
logger.error(String.format("[ %s ]请求失败: %s %s", url, response.code(), response.message()));

View File

@ -0,0 +1,36 @@
package com.genersoft.iot.vmp.media.zlm.dto.hook;
public class HookResult {
private int code;
private String msg;
public HookResult() {
}
public HookResult(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static HookResult SUCCESS(){
return new HookResult(0, "success");
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

View File

@ -0,0 +1,44 @@
package com.genersoft.iot.vmp.media.zlm.dto.hook;
public class HookResultForOnPublish extends HookResult{
private boolean enable_audio;
private boolean enable_mp4;
private int mp4_max_second;
public HookResultForOnPublish() {
}
public static HookResultForOnPublish SUCCESS(){
return new HookResultForOnPublish(0, "success");
}
public HookResultForOnPublish(int code, String msg) {
setCode(code);
setMsg(msg);
}
public boolean isEnable_audio() {
return enable_audio;
}
public void setEnable_audio(boolean enable_audio) {
this.enable_audio = enable_audio;
}
public boolean isEnable_mp4() {
return enable_mp4;
}
public void setEnable_mp4(boolean enable_mp4) {
this.enable_mp4 = enable_mp4;
}
public int getMp4_max_second() {
return mp4_max_second;
}
public void setMp4_max_second(int mp4_max_second) {
this.mp4_max_second = mp4_max_second;
}
}

View File

@ -152,6 +152,10 @@ public class GbStreamServiceImpl implements IGbStreamService {
@Override
public void sendCatalogMsg(GbStream gbStream, String type) {
if (gbStream == null || type == null) {
logger.warn("[发送目录订阅]类型流信息或类型为NULL");
return;
}
List<GbStream> gbStreams = new ArrayList<>();
if (gbStream.getGbId() != null) {
gbStreams.add(gbStream);

View File

@ -33,6 +33,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.JsonUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import okhttp3.OkHttpClient;
@ -241,7 +242,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
for (Object mediaServerKey : mediaServerKeys) {
String key = (String) mediaServerKey;
MediaServerItem mediaServerItem = (MediaServerItem) RedisUtil.get(key);
MediaServerItem mediaServerItem = JsonUtil.redisJsonToObject(key, MediaServerItem.class);
if (Objects.isNull(mediaServerItem)) {
continue;
}
// 检查状态
Double aDouble = RedisUtil.zScore(onlineKey, mediaServerItem.getId());
if (aDouble != null) {
@ -293,7 +297,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
return null;
}
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
return (MediaServerItem)RedisUtil.get(key);
return JsonUtil.redisJsonToObject(key, MediaServerItem.class);
}
@ -410,8 +414,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain());
serverItem.setSsrcConfig(ssrcConfig);
}else {
MediaServerItem mediaServerItemInRedis = (MediaServerItem)RedisUtil.get(key);
serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
MediaServerItem mediaServerItemInRedis = JsonUtil.redisJsonToObject(key, MediaServerItem.class);
if (Objects.nonNull(mediaServerItemInRedis)) {
serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
}
}
RedisUtil.set(key, serverItem);
resetOnlineServerItem(serverItem);

View File

@ -184,7 +184,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
@Override
public boolean stop(String app, String streamId) {
StreamPushItem streamPushItem = streamPushMapper.selectOne(app, streamId);
gbStreamService.sendCatalogMsg(streamPushItem, CatalogEvent.DEL);
if (streamPushItem != null) {
gbStreamService.sendCatalogMsg(streamPushItem, CatalogEvent.DEL);
}
platformGbStreamMapper.delByAppAndStream(app, streamId);
gbStreamMapper.del(app, streamId);

View File

@ -62,16 +62,16 @@ public class RedisAlarmMsgListener implements MessageListener {
}
String gbId = alarmChannelMessage.getGbId();
DeviceAlarm deviceAlarm = new DeviceAlarm();
deviceAlarm.setCreateTime(DateUtil.getNow());
deviceAlarm.setChannelId(gbId);
deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
deviceAlarm.setAlarmPriority("1");
deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601());
deviceAlarm.setAlarmType("1");
deviceAlarm.setLongitude(0D);
deviceAlarm.setLatitude(0D);
DeviceAlarm deviceAlarm = new DeviceAlarm();
deviceAlarm.setCreateTime(DateUtil.getNow());
deviceAlarm.setChannelId(gbId);
deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType());
deviceAlarm.setAlarmPriority("1");
deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601());
deviceAlarm.setLongitude(0);
deviceAlarm.setLatitude(0);
if (ObjectUtils.isEmpty(gbId)) {
// 发送给所有的上级

View File

@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.storager;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
@ -186,7 +185,13 @@ public interface IVideoManagerStorage {
Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
/**
* deviceinfo
* @param platformId id
* @param channelId id
* @return
*/
Device queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId);
/**
* Mobile Position
* @param mobilePosition
@ -324,6 +329,8 @@ public interface IVideoManagerStorage {
*/
boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList);
boolean updateChannels(String deviceId, List<DeviceChannel> deviceChannelList);
/**
*
* @param platformId

View File

@ -1,9 +1,10 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@ -20,7 +21,7 @@ public interface DeviceAlarmMapper {
int add(DeviceAlarm alarm);
@Select(value = {" <script>" +
@Select( value = {" <script>" +
" SELECT * FROM device_alarm " +
" WHERE 1=1 " +
" <if test=\"deviceId != null\" > AND deviceId = #{deviceId}</if>" +

View File

@ -107,4 +107,14 @@ public interface PlatformChannelMapper {
"DELETE FROM platform_gb_channel WHERE platformId=#{platformId} and catalogId=#{catalogId}" +
"</script>")
int delChannelForGBByCatalogId(String platformId, String catalogId);
@Select("select dc.channelId deviceId,dc.name,d.manufacturer,d.model,d.firmware\n" +
"from platform_gb_channel pgc\n" +
" left join device_channel dc on dc.id = pgc.deviceChannelId\n" +
" left join device d on dc.deviceId = d.deviceId\n" +
"where dc.channelId = #{channelId} and pgc.platformId=#{platformId}")
List<Device> queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId);
@Select("SELECT pgc.platformId FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}'")
List<String> queryParentPlatformByChannelId(String channelId);
}

View File

@ -17,6 +17,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.JsonUtil;
import com.genersoft.iot.vmp.utils.SystemInfoUtils;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.slf4j.Logger;
@ -157,7 +158,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
}
for (Object player : players) {
String key = (String) player;
StreamInfo streamInfo = (StreamInfo) RedisUtil.get(key);
StreamInfo streamInfo = JsonUtil.redisJsonToObject(key, StreamInfo.class);
if (Objects.isNull(streamInfo)) {
continue;
}
streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getChannelId(), streamInfo);
}
return streamInfos;
@ -624,8 +628,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public ThirdPartyGB queryMemberNoGBId(String queryKey) {
String key = VideoManagerConstants.WVP_STREAM_GB_ID_PREFIX + queryKey;
JSONObject jsonObject = (JSONObject)RedisUtil.get(key);
return jsonObject.to(ThirdPartyGB.class);
return JsonUtil.redisJsonToObject(key, ThirdPartyGB.class);
}
@Override
@ -664,7 +667,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public Device getDevice(String deviceId) {
String key = VideoManagerConstants.DEVICE_PREFIX + userSetting.getServerId() + "_" + deviceId;
return (Device)RedisUtil.get(key);
return JsonUtil.redisJsonToObject(key, Device.class);
}
@Override
@ -676,7 +679,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public GPSMsgInfo getGpsMsgInfo(String gbId) {
String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_" + gbId;
return (GPSMsgInfo)RedisUtil.get(key);
return JsonUtil.redisJsonToObject(key, GPSMsgInfo.class);
}
@Override
@ -686,9 +689,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
List<Object> keys = RedisUtil.scan(scanKey);
for (Object o : keys) {
String key = (String) o;
GPSMsgInfo gpsMsgInfo = (GPSMsgInfo) RedisUtil.get(key);
if (!gpsMsgInfo.isStored()) { // 只取没有存过得
result.add((GPSMsgInfo) RedisUtil.get(key));
GPSMsgInfo gpsMsgInfo = JsonUtil.redisJsonToObject(key, GPSMsgInfo.class);
if (Objects.nonNull(gpsMsgInfo) && !gpsMsgInfo.isStored()) { // 只取没有存过得
result.add(JsonUtil.redisJsonToObject(key, GPSMsgInfo.class));
}
}
@ -710,7 +713,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream) {
String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
return (StreamAuthorityInfo) RedisUtil.get(key);
return JsonUtil.redisJsonToObject(key, StreamAuthorityInfo.class);
}
@ -721,7 +724,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
List<Object> keys = RedisUtil.scan(scanKey);
for (Object o : keys) {
String key = (String) o;
result.add((StreamAuthorityInfo) RedisUtil.get(key));
result.add(JsonUtil.redisJsonToObject(key, StreamAuthorityInfo.class));
}
return result;
}
@ -735,7 +738,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
List<Object> keys = RedisUtil.scan(scanKey);
if (keys.size() > 0) {
String key = (String) keys.get(0);
result = (OnStreamChangedHookParam)RedisUtil.get(key);
result = JsonUtil.redisJsonToObject(key, OnStreamChangedHookParam.class);
}
return result;
@ -827,7 +830,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public void sendAlarmMsg(AlarmChannelMessage msg) {
String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM;
String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE;
logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg));
RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
}

View File

@ -126,6 +126,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
if (allChannelMap.get(deviceChannel.getChannelId()).getStatus() !=deviceChannel.getStatus()){
List<String> strings = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getChannelId());
if (!CollectionUtils.isEmpty(strings)){
strings.forEach(platformId->{
eventPublisher.catalogEventPublish(platformId, deviceChannel, deviceChannel.getStatus()==1?CatalogEvent.ON:CatalogEvent.OFF);
});
}
}
}
channels.add(deviceChannel);
if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
@ -187,6 +196,119 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
}
@Override
public boolean updateChannels(String deviceId, List<DeviceChannel> deviceChannelList) {
if (CollectionUtils.isEmpty(deviceChannelList)) {
return false;
}
List<DeviceChannel> allChannels = deviceChannelMapper.queryAllChannels(deviceId);
Map<String,DeviceChannel> allChannelMap = new ConcurrentHashMap<>();
if (allChannels.size() > 0) {
for (DeviceChannel deviceChannel : allChannels) {
allChannelMap.put(deviceChannel.getChannelId(), deviceChannel);
}
}
List<DeviceChannel> addChannels = new ArrayList<>();
List<DeviceChannel> updateChannels = new ArrayList<>();
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
// 数据去重
StringBuilder stringBuilder = new StringBuilder();
Map<String, Integer> subContMap = new HashMap<>();
if (deviceChannelList.size() > 0) {
// 数据去重
Set<String> gbIdSet = new HashSet<>();
for (DeviceChannel deviceChannel : deviceChannelList) {
if (!gbIdSet.contains(deviceChannel.getChannelId())) {
gbIdSet.add(deviceChannel.getChannelId());
if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
updateChannels.add(deviceChannel);
}else {
addChannels.add(deviceChannel);
}
if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
if (subContMap.get(deviceChannel.getParentId()) == null) {
subContMap.put(deviceChannel.getParentId(), 1);
}else {
Integer count = subContMap.get(deviceChannel.getParentId());
subContMap.put(deviceChannel.getParentId(), count++);
}
}
}else {
stringBuilder.append(deviceChannel.getChannelId()).append(",");
}
}
if (addChannels.size() > 0) {
for (DeviceChannel channel : addChannels) {
if (subContMap.get(channel.getChannelId()) != null){
channel.setSubCount(subContMap.get(channel.getChannelId()));
}
}
}
if (updateChannels.size() > 0) {
for (DeviceChannel channel : updateChannels) {
if (subContMap.get(channel.getChannelId()) != null){
channel.setSubCount(subContMap.get(channel.getChannelId()));
}
}
}
}
if (stringBuilder.length() > 0) {
logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder);
}
if(CollectionUtils.isEmpty(updateChannels) && CollectionUtils.isEmpty(addChannels) ){
logger.info("通道更新,数据为空={}" , deviceChannelList);
return false;
}
try {
int limitCount = 300;
boolean result = false;
if (addChannels.size() > 0) {
if (addChannels.size() > limitCount) {
for (int i = 0; i < addChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > addChannels.size()) {
toIndex = addChannels.size();
}
result = result || deviceChannelMapper.batchAdd(addChannels.subList(i, toIndex)) < 0;
}
}else {
result = result || deviceChannelMapper.batchAdd(addChannels) < 0;
}
}
if (updateChannels.size() > 0) {
if (updateChannels.size() > limitCount) {
for (int i = 0; i < updateChannels.size(); i += limitCount) {
int toIndex = i + limitCount;
if (i + limitCount > updateChannels.size()) {
toIndex = updateChannels.size();
}
result = result || deviceChannelMapper.batchUpdate(updateChannels.subList(i, toIndex)) < 0;
}
}else {
result = result || deviceChannelMapper.batchUpdate(updateChannels) < 0;
}
}
if (result) {
//事务回滚
dataSourceTransactionManager.rollback(transactionStatus);
}else {
//手动提交
dataSourceTransactionManager.commit(transactionStatus);
}
return true;
}catch (Exception e) {
e.printStackTrace();
dataSourceTransactionManager.rollback(transactionStatus);
return false;
}
}
@Override
public void deviceChannelOnline(String deviceId, String channelId) {
deviceChannelMapper.online(deviceId, channelId);
@ -464,6 +586,20 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
}
@Override
public Device queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId) {
List<Device> devices = platformChannelMapper.queryDeviceInfoByPlatformIdAndChannelId(platformId, channelId);
if (devices.size() > 1) {
// 出现长度大于0的时候肯定是国标通道的ID重复了
logger.warn("国标ID存在重复{}", channelId);
}
if (devices.size() == 0) {
return null;
}else {
return devices.get(0);
}
}
/**
*
* @param deviceId

View File

@ -0,0 +1,36 @@
package com.genersoft.iot.vmp.utils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import java.util.Objects;
/**
* JsonUtil
*
* @author KunLong-Luo
* @version 1.0.0
* @since 2023/2/2 15:24
*/
public final class JsonUtil {
private JsonUtil() {
}
/**
* safe json type conversion
*
* @param key redis key
* @param clazz cast type
* @param <T>
* @return result type
*/
public static <T> T redisJsonToObject(String key, Class<T> clazz) {
Object jsonObject = RedisUtil.get(key);
if (Objects.isNull(jsonObject)) {
return null;
}
return clazz.cast(jsonObject);
}
}

View File

@ -110,7 +110,7 @@ public class DeviceControl {
msg.setKey(key);
msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeAllResult(msg);
});
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
@ -143,7 +143,7 @@ public class DeviceControl {
msg.setKey(key);
msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
@ -192,7 +192,7 @@ public class DeviceControl {
msg.setKey(key);
msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 报警复位: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
@ -274,7 +274,7 @@ public class DeviceControl {
msg.setKey(key);
msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
},null);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 看守位控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.vmanager.gb28181.playback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.ServiceException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
@ -64,13 +65,16 @@ public class PlaybackController {
@Autowired
private DeferredResultHolder resultHolder;
@Autowired
private UserSetting userSetting;
@Operation(summary = "开始视频回放")
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "startTime", description = "开始时间", required = true)
@Parameter(name = "endTime", description = "结束时间", required = true)
@GetMapping("/start/{deviceId}/{channelId}")
public DeferredResult<WVPResult<StreamContent>> play(@PathVariable String deviceId, @PathVariable String channelId,
public DeferredResult<WVPResult<StreamContent>> start(@PathVariable String deviceId, @PathVariable String channelId,
String startTime, String endTime) {
if (logger.isDebugEnabled()) {
@ -79,7 +83,7 @@ public class PlaybackController {
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L);
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
resultHolder.put(key, uuid, result);
WVPResult<StreamContent> wvpResult = new WVPResult<>();

View File

@ -11,17 +11,13 @@ import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.security.sasl.AuthenticationException;
@ -90,7 +86,7 @@ public class UserController {
@PostMapping("/add")
@Operation(summary = "停止视频回放")
@Operation(summary = "添加用户")
@Parameter(name = "username", description = "用户名", required = true)
@Parameter(name = "password", description = "密码未md5加密的密码", required = true)
@Parameter(name = "roleId", description = "角色ID", required = true)

View File

@ -167,7 +167,7 @@ user-settings:
senior-sdp: false
# 保存移动位置历史轨迹true:保留历史数据false:仅保留最后的位置(默认)
save-position-history: false
# 点播等待超时时间,单位:毫秒
# 点播/录像回放 等待超时时间,单位:毫秒
play-timeout: 18000
# 上级点播等待超时时间,单位:毫秒
platform-play-timeout: 60000

View File

@ -1,86 +1,86 @@
spring:
# [可选]上传文件大小限制
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
# REDIS数据库配置
redis:
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
host: 127.0.0.1
# [必须修改] 端口号
port: 6379
# [可选] 数据库 DB
database: 6
# [可选] 访问密码,若你的redis服务器没有设置密码就不需要用密码去连接
password: face2020
# [可选] 超时时间
timeout: 10000
# mysql数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
username: root
password: 123456
druid:
initialSize: 10 # 连接池初始化连接数
maxActive: 200 # 连接池最大连接数
minIdle: 5 # 连接池最小空闲连接数
maxWait: 60000 # 获取连接时最大等待时间单位毫秒。配置了maxWait之后缺省启用公平锁并发效率会有所下降如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
keepAlive: true # 连接池中的minIdle数量以内的连接空闲时间超过minEvictableIdleTimeMillis则会执行keepAlive操作。
validationQuery: select 1 # 检测连接是否有效sql要求是查询语句常用select 'x'。如果validationQuery为nulltestOnBorrow、testOnReturn、testWhileIdle都不会起作用。
testWhileIdle: true # 建议配置为true不影响性能并且保证安全性。申请连接的时候检测如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效。
testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效做了这个配置会降低性能。
testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效做了这个配置会降低性能。
poolPreparedStatements: false # 是否開啟PSCache並且指定每個連線上PSCache的大小
timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒
filters: stat,slf4j # 配置监控统计拦截的filters监控统计用的filter:sta, 日志用的filter:log4j
useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000
#stat-view-servlet.url-pattern: /admin/druid/*
# [可选]上传文件大小限制
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
# REDIS数据库配置
redis:
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
host: 127.0.0.1
# [必须修改] 端口号
port: 6379
# [可选] 数据库 DB
database: 6
# [可选] 访问密码,若你的redis服务器没有设置密码就不需要用密码去连接
password: face2020
# [可选] 超时时间
timeout: 10000
# mysql数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
username: root
password: 123456
druid:
initialSize: 10 # 连接池初始化连接数
maxActive: 200 # 连接池最大连接数
minIdle: 5 # 连接池最小空闲连接数
maxWait: 60000 # 获取连接时最大等待时间单位毫秒。配置了maxWait之后缺省启用公平锁并发效率会有所下降如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
keepAlive: true # 连接池中的minIdle数量以内的连接空闲时间超过minEvictableIdleTimeMillis则会执行keepAlive操作。
validationQuery: select 1 # 检测连接是否有效sql要求是查询语句常用select 'x'。如果validationQuery为nulltestOnBorrow、testOnReturn、testWhileIdle都不会起作用。
testWhileIdle: true # 建议配置为true不影响性能并且保证安全性。申请连接的时候检测如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效。
testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效做了这个配置会降低性能。
testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效做了这个配置会降低性能。
poolPreparedStatements: false # 是否開啟PSCache並且指定每個連線上PSCache的大小
timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒
filters: stat,slf4j # 配置监控统计拦截的filters监控统计用的filter:sta, 日志用的filter:log4j
useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000
#stat-view-servlet.url-pattern: /admin/druid/*
#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
server:
port: 18080
port: 18080
# 作为28181服务器的配置
sip:
# [必须修改] 本机的IP
ip: 192.168.41.16
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码由省级、市级、区级、基层编号组成参照GB/T 2260-2007
# 后两位为行业编码定义参照附录D.3
# 3701020049标识山东济南历下区 信息行业接入
# [可选]
domain: 4401020049
# [可选]
id: 44010200492000000001
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
password: admin123
# [必须修改] 本机的IP
ip: 192.168.41.16
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码由省级、市级、区级、基层编号组成参照GB/T 2260-2007
# 后两位为行业编码定义参照附录D.3
# 3701020049标识山东济南历下区 信息行业接入
# [可选]
domain: 4401020049
# [可选]
id: 44010200492000000001
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
password: admin123
#zlm 默认服务器配置
media:
id: FQ3TF8yT83wh5Wvz
# [必须修改] zlm服务器的内网IP
ip: 192.168.41.16
# [必须修改] zlm服务器的http.port
http-port: 8091
# [可选] zlm服务器的hook.admin_params=secret
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
enable: true
# [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性不然自动配置此属性可能不成功
port-range: 30000,30500 # 端口范围
# [可选] 国标级联在此范围内选择端口发送媒体流,
send-port-range: 30000,30500 # 端口范围
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载 0 表示不使用
record-assist-port: 18081
id: FQ3TF8yT83wh5Wvz
# [必须修改] zlm服务器的内网IP
ip: 192.168.41.16
# [必须修改] zlm服务器的http.port
http-port: 8091
# [可选] zlm服务器的hook.admin_params=secret
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
enable: true
# [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性不然自动配置此属性可能不成功
port-range: 30000,30500 # 端口范围
# [可选] 国标级联在此范围内选择端口发送媒体流,
send-port-range: 30000,30500 # 端口范围
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载 0 表示不使用
record-assist-port: 18081
# [可选] 日志配置, 一般不需要改
logging:
config: classpath:logback-spring-local.xml
config: classpath:logback-spring-local.xml

View File

@ -1,3 +1,16 @@
spring:
application:
name: wvp
profiles:
active: local
# flayway相关配置
flyway:
enabled: true #是否启用flyway(默认true)
locations: classpath:db/migration #这个路径指的是fly版本控制的sql语句存放的路径,可以多个,可以给每个环境使用不同位置,比如classpath:db/migration,classpath:test/db/migration
baseline-on-migrate: true #开启自动创建flyway元数据表标识 默认: false
# 与 baseline-on-migrate: true 搭配使用,将当前数据库初始版本设置为0
baseline-version: 0
clean-disabled: true #禁止flyway执行清理
# 假如已经执行了版本1和版本3如果增加了一个版本2下面这个选项将会允许执行版本2的脚本
out-of-order: true
table: flyway_schema_history_${spring.application.name} #用于记录所有的版本变化记录

View File

@ -39,6 +39,7 @@ CREATE TABLE `device` (
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`port` int DEFAULT NULL,
`expires` int DEFAULT NULL,
`keepaliveIntervalTime` int DEFAULT NULL,
`subscribeCycleForCatalog` int DEFAULT NULL,
`hostAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`charset` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,

View File

@ -47,7 +47,8 @@ exports.cssLoaders = function (options) {
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
fallback: 'vue-style-loader',
publicPath: '../../'
})
} else {
return ['vue-style-loader'].concat(loaders)

View File

@ -8,8 +8,8 @@ module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
assetsSubDirectory: './static',
assetsPublicPath: './',
proxyTable: {
'/debug': {
target: 'https://default.wvp-pro.cn:18080',
@ -61,7 +61,7 @@ module.exports = {
// Paths
assetsRoot: path.resolve(__dirname, '../../src/main/resources/static/'),
assetsSubDirectory: './static',
assetsPublicPath: '/',
assetsPublicPath: './',
/**
* Source Maps

View File

@ -133,7 +133,7 @@
let that = this;
this.$axios({
method: 'get',
url:`/record_proxy/${that.mediaServerId}/api/record/list`,
url:`./record_proxy/${that.mediaServerId}/api/record/list`,
params: {
page: that.currentPage,
count: that.count
@ -185,7 +185,7 @@
let that = this;
this.$axios({
method: 'delete',
url:`/record_proxy/api/record/delete`,
url:`./record_proxy/api/record/delete`,
params: {
page: that.currentPage,
count: that.count

View File

@ -1,14 +1,15 @@
<template>
<div id="recordDetail">
<el-container>
<el-aside width="300px">
<el-aside width="260px">
<div class="record-list-box-box">
<el-date-picker size="mini" v-model="chooseDate" :picker-options="pickerOptions" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="dateChange()"></el-date-picker>
<div style="margin-top: 20px">
<el-date-picker size="mini" style="width: 160px" v-model="chooseDate" :picker-options="pickerOptions" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="dateChange()"></el-date-picker>
<el-button size="mini" type="primary" icon="fa fa-cloud-download" style="margin: auto; margin-left: 12px " title="裁剪合并" @click="drawerOpen"></el-button>
</div>
<div class="record-list-box" :style="recordListStyle">
<ul v-if="detailFiles.length >0" class="infinite-list record-list" v-infinite-scroll="infiniteScroll" >
<li v-for="item in detailFiles" class="infinite-list-item record-list-item" >
<li v-for="(item,index) in detailFiles" :key="index" class="infinite-list-item record-list-item" >
<el-tag v-if="choosedFile != item" @click="chooseFile(item)">
<i class="el-icon-video-camera" ></i>
{{ item.substring(0,17)}}
@ -24,9 +25,7 @@
<div v-if="detailFiles.length ==0" class="record-list-no-val" >暂无数据</div>
</div>
<div class="record-list-option">
<el-button size="mini" type="primary" icon="fa fa-cloud-download" style="margin: auto; " title="裁剪合并" @click="drawerOpen"></el-button>
</div>
</el-aside>
<el-main style="padding: 22px">
<div class="playBox" :style="playerStyle">
@ -45,7 +44,7 @@
:marks="playTimeSliderMarks">
</el-slider>
<div class="slider-val-box">
<div class="slider-val" v-for="item of detailFiles" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
<div class="slider-val" v-for="(item,index) of detailFiles" :key="index" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
</div>
</div>
@ -62,7 +61,7 @@
<el-tab-pane name="running">
<span slot="label"><i class="el-icon-scissors"></i>进行中</span>
<ul class="task-list">
<li class="task-list-item" v-for="item in taskListForRuning">
<li class="task-list-item" v-for="(item,index) in taskListForRuning" :key="index">
<div class="task-list-item-box">
<span>{{ item.startTime.substr(10) }}-{{item.endTime.substr(10)}}</span>
<el-progress :percentage="(parseFloat(item.percentage)*100).toFixed(1)"></el-progress>
@ -74,10 +73,10 @@
<el-tab-pane name="ended">
<span slot="label"><i class="el-icon-finished"></i>已完成</span>
<ul class="task-list">
<li class="task-list-item" v-for="item in taskListEnded">
<li class="task-list-item" v-for="(item, index) in taskListEnded" :key="index">
<div class="task-list-item-box" style="height: 2rem;line-height: 2rem;">
<span>{{ item.startTime.substr(10) }}-{{item.endTime.substr(10)}}</span>
<a class="el-icon-download download-btn" :href="basePath + '/download.html?url=../' + item.recordFile" target="_blank">
<a class="el-icon-download download-btn" :href="mediaServerPath + '/download.html?url=../' + item.recordFile" target="_blank">
</a>
</div>
</li>
@ -116,7 +115,7 @@
props: ['recordFile', 'mediaServerId', 'dateFiles', 'mediaServerPath'],
data() {
return {
basePath: `${this.mediaServerPath}`,
basePath: `${this.mediaServerPath}/record`,
dateFilesObj: [],
detailFiles: [],
chooseDate: null,
@ -147,6 +146,7 @@
"margin-bottom": "20px",
"height": this.winHeight + "px",
},
timeFormat:'00:00:00',
winHeight: window.innerHeight - 240,
playTime: 0,
playTimeSliderMarks: {
@ -213,7 +213,7 @@
this.currentPage = 1;
this.sliderMIn= 0;
this.sliderMax= 86400;
let chooseFullDate = new Date(this.chooseDate + " " + "00:00:00");
let chooseFullDate = new Date(this.chooseDate +" " + this.timeFormat);
if (chooseFullDate.getFullYear() !== this.queryDate.getFullYear()
|| chooseFullDate.getMonth() !== this.queryDate.getMonth()){
// this.getDateInYear()
@ -222,8 +222,8 @@
if (this.detailFiles.length > 0){
let timeForFile = this.getTimeForFile(this.detailFiles[0]);
let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
this.playTime = parseInt(timeNum/1000)
this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60))
@ -241,7 +241,7 @@
let that = this;
that.$axios({
method: 'get',
url:`/record_proxy/${that.mediaServerId}/api/record/file/list`,
url:`./record_proxy/${that.mediaServerId}/api/record/file/list`,
params: {
app: that.recordFile.app,
stream: that.recordFile.stream,
@ -281,14 +281,14 @@
},
getDataLeft(item){
let timeForFile = this.getTimeForFile(item);
let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " 00:00:00").getTime()
let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
return parseFloat((differenceTime - this.sliderMIn * 1000)/((this.sliderMax - this.sliderMIn)*1000))*100 ;
},
playTimeChange(val){
let minTime = this.getTimeForFile(this.detailFiles[0])[0]
let maxTime = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1])[1];
this.chooseFile(null);
let timeMilli = new Date(this.chooseDate + " 00:00:00").getTime() + val*1000
let timeMilli = new Date(this.chooseDate + " " + this.timeFormat).getTime() + val*1000
if (timeMilli >= minTime.getTime() && timeMilli <= maxTime.getTime()){
for (let i = 0; i < this.detailFiles.length; i++) {
let timeForFile = this.getTimeForFile(this.detailFiles[i]);
@ -302,10 +302,20 @@
},
getTimeForFile(file){
let timeStr = file.substring(0,17);
let starTime = new Date(this.chooseDate + " " + timeStr.split("-")[0]);
let endTime = new Date(this.chooseDate + " " + timeStr.split("-")[1]);
if(timeStr.indexOf("~") > 0){
timeStr = timeStr.replaceAll("-",":")
}
let timeArr = timeStr.split("~");
let starTime = new Date(this.chooseDate + " " + timeArr[0]);
let endTime = new Date(this.chooseDate + " " + timeArr[1]);
if(this.checkIsOver24h(starTime,endTime)){
endTime = new Date(this.chooseDate + " " + "23:59:59");
}
return [starTime, endTime, endTime.getTime() - starTime.getTime()];
},
checkIsOver24h(starTime,endTime){
return starTime > endTime;
},
playTimeFormat(val){
let h = parseInt(val/3600);
let m = parseInt((val - h*3600)/60);
@ -330,7 +340,7 @@
let that = this;
this.$axios({
method: 'delete',
url:`/record_proxy/${that.mediaServerId}/api/record/delete`,
url:`./record_proxy/${that.mediaServerId}/api/record/delete`,
params: {
page: that.currentPage,
count: that.count
@ -349,7 +359,7 @@
that.dateFilesObj = {};
this.$axios({
method: 'get',
url:`/record_proxy/${that.mediaServerId}/api/record/date/list`,
url:`./record_proxy/${that.mediaServerId}/api/record/date/list`,
params: {
app: that.recordFile.app,
stream: that.recordFile.stream
@ -398,7 +408,7 @@
let that = this;
this.$axios({
method: 'get',
url:`/record_proxy/${that.mediaServerId}/api/record/file/download/task/add`,
url:`./record_proxy/${that.mediaServerId}/api/record/file/download/task/add`,
params: {
app: that.recordFile.app,
stream: that.recordFile.stream,
@ -423,7 +433,7 @@
let that = this;
this.$axios({
method: 'get',
url:`/record_proxy/${that.mediaServerId}/api/record/file/download/task/list`,
url:`./record_proxy/${that.mediaServerId}/api/record/file/download/task/list`,
params: {
isEnd: isEnd,
}

View File

@ -152,7 +152,7 @@ export default {
this.getDeviceListLoading = true;
this.$axios({
method: 'get',
url: `/api/device/query/devices`,
url: `./api/device/query/devices`,
params: {
page: this.currentPage,
count: this.count
@ -182,7 +182,7 @@ export default {
}).then(() => {
this.$axios({
method: 'delete',
url: `/api/device/query/devices/${row.deviceId}/delete`
url: `./api/device/query/devices/${row.deviceId}/delete`
}).then((res) => {
this.getDeviceList();
}).catch((error) => {
@ -208,7 +208,7 @@ export default {
let that = this;
this.$axios({
method: 'get',
url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
url: './api/device/query/devices/' + itemData.deviceId + '/sync'
}).then((res) => {
console.log("刷新设备结果:" + JSON.stringify(res));
if (res.data.code !== 0) {
@ -242,7 +242,7 @@ export default {
await this.$axios({
method: 'get',
async: false,
url: `/api/device/query/${deviceId}/sync_status/`,
url: `./api/device/query/${deviceId}/sync_status/`,
}).then((res) => {
if (res.data.code == 0) {
if (res.data.data.errorMsg !== null) {
@ -261,7 +261,7 @@ export default {
let that = this;
this.$axios({
method: 'post',
url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode
url: './api/device/query/transport/' + row.deviceId + '/' + row.streamMode
}).then(function (res) {
}).catch(function (e) {

View File

@ -197,7 +197,7 @@
this.detailFiles = [];
this.$axios({
method: 'get',
url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + this.endTime
url: './api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + this.endTime
}).then((res)=>{
this.recordsLoading = false;
if(res.data.code === 0) {
@ -249,7 +249,7 @@
} else {
this.$axios({
method: 'get',
url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' +
url: './api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' +
this.endTime
}).then((res)=> {
if (res.data.code === 0) {
@ -273,7 +273,7 @@
console.log('前端控制:播放');
this.$axios({
method: 'get',
url: '/api/playback/resume/' + this.streamId
url: './api/playback/resume/' + this.streamId
}).then((res)=> {
this.$refs["recordVideoPlayer"].play(this.videoUrl)
});
@ -282,14 +282,14 @@
console.log('前端控制:暂停');
this.$axios({
method: 'get',
url: '/api/playback/pause/' + this.streamId
url: './api/playback/pause/' + this.streamId
}).then(function (res) {});
},
gbScale(command){
console.log('前端控制:倍速 ' + command);
this.$axios({
method: 'get',
url: `/api/playback/speed/${this.streamId }/${command}`
url: `./api/playback/speed/${this.streamId }/${command}`
}).then(function (res) {});
},
downloadRecord: function (row) {
@ -311,7 +311,7 @@
}else {
this.$axios({
method: 'get',
url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
url: './api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
row.endTime + '&downloadSpeed=4'
}).then( (res)=> {
if (res.data.code === 0) {
@ -332,7 +332,7 @@
this.videoUrl = '';
this.$axios({
method: 'get',
url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
url: './api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
}).then((res)=> {
if (callback) callback(res)
});
@ -342,7 +342,7 @@
this.videoUrl = '';
this.$axios({
method: 'get',
url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
url: './api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
}).then(function (res) {
if (callback) callback()
});

View File

@ -81,7 +81,7 @@ export default {
this.$axios({
method: 'get',
url:"/api/user/login",
url:"./api/user/login",
params: loginParam
}).then(function (res) {
window.clearTimeout(timeoutTask)

View File

@ -128,7 +128,7 @@ export default {
var that = this;
that.$axios({
method: 'delete',
url:`/api/platform/delete/${platform.serverGBId}`
url:`./api/platform/delete/${platform.serverGBId}`
}).then(function (res) {
if (res.data.code === 0) {
that.$message({
@ -162,7 +162,7 @@ export default {
this.$axios({
method: 'get',
url:`/api/platform/query/${that.count}/${that.currentPage}`
url:`./api/platform/query/${that.count}/${that.currentPage}`
}).then(function (res) {
if (res.data.code === 0) {
that.total = res.data.data.total;

View File

@ -171,7 +171,7 @@ export default {
this.getDeviceListLoading = true;
this.$axios({
method: 'get',
url: `/api/push/list`,
url: `./api/push/list`,
params: {
page: that.currentPage,
count: that.count,
@ -197,7 +197,7 @@ export default {
this.getListLoading = true;
this.$axios({
method: 'get',
url: '/api/push/getPlayUrl',
url: './api/push/getPlayUrl',
params: {
app: row.app,
stream: row.stream,
@ -223,7 +223,7 @@ export default {
let that = this;
that.$axios({
method: "post",
url: "/api/push/stop",
url: "./api/push/stop",
params: {
app: row.app,
streamId: row.stream
@ -247,7 +247,7 @@ export default {
let that = this;
that.$axios({
method: "delete",
url: "/api/push/remove_form_gb",
url: "./api/push/remove_form_gb",
data: row
}).then((res) => {
if (res.data.code === 0) {
@ -274,7 +274,7 @@ export default {
let that = this;
that.$axios({
method: "delete",
url: "/api/push/batchStop",
url: "./api/push/batchStop",
data: {
gbStreams: this.multipleSelection
}

View File

@ -167,7 +167,7 @@
let that = this;
this.$axios({
method: 'get',
url:`/api/proxy/list`,
url:`./api/proxy/list`,
params: {
page: that.currentPage,
count: that.count
@ -190,7 +190,7 @@
addOnvif: function(){
this.$axios({
method: 'get',
url:`/api/onvif/search?timeout=3000`,
url:`./api/onvif/search?timeout=3000`,
}).then((res) =>{
if (res.data.code === 0 ){
if (res.data.data.length > 0) {
@ -218,7 +218,7 @@
let that = this;
this.$axios({
method: 'get',
url:`/api/push/getPlayUrl`,
url:`./api/push/getPlayUrl`,
params: {
app: row.app,
stream: row.stream,
@ -247,7 +247,7 @@
let that = this;
that.$axios({
method:"delete",
url:"/api/proxy/del",
url:"./api/proxy/del",
params:{
app: row.app,
stream: row.stream
@ -263,7 +263,7 @@
this.$set(row, 'startBtnLoading', true)
this.$axios({
method: 'get',
url:`/api/proxy/start`,
url:`./api/proxy/start`,
params: {
app: row.app,
stream: row.stream
@ -295,7 +295,7 @@
let that = this;
this.$axios({
method: 'get',
url:`/api/proxy/stop`,
url:`./api/proxy/stop`,
params: {
app: row.app,
stream: row.stream

View File

@ -99,7 +99,7 @@ export default {
this.getUserListLoading = true;
this.$axios({
method: 'get',
url: `/api/user/users`,
url: `./api/user/users`,
params: {
page: that.currentPage,
count: that.count
@ -141,7 +141,7 @@ export default {
}).then(() => {
this.$axios({
method: 'delete',
url: `/api/user/delete?id=${row.id}`
url: `./api/user/delete?id=${row.id}`
}).then((res) => {
this.getUserList();
}).catch((error) => {

View File

@ -206,7 +206,7 @@ export default {
if (typeof (this.$route.params.deviceId) == "undefined") return;
this.$axios({
method: 'get',
url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,
url: `./api/device/query/devices/${this.$route.params.deviceId}/channels`,
params: {
page: that.currentPage,
count: that.count,
@ -238,7 +238,7 @@ export default {
let that = this;
this.$axios({
method: 'get',
url: '/api/play/start/' + deviceId + '/' + channelId
url: './api/play/start/' + deviceId + '/' + channelId
}).then(function (res) {
console.log(res)
that.isLoging = false;
@ -278,7 +278,7 @@ export default {
var that = this;
this.$axios({
method: 'get',
url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId
url: './api/play/stop/' + this.deviceId + "/" + itemData.channelId
}).then(function (res) {
that.initData();
}).catch(function (error) {
@ -334,7 +334,7 @@ export default {
if (!this.showTree) {
this.$axios({
method: 'get',
url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
url: `./api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
params: {
page: this.currentPage,
count: this.count,
@ -358,7 +358,7 @@ export default {
}else {
this.$axios({
method: 'get',
url: `/api/device/query/tree/channel/${this.deviceId}`,
url: `./api/device/query/tree/channel/${this.deviceId}`,
params: {
parentId: this.parentChannelId,
page: this.currentPage,
@ -387,7 +387,7 @@ export default {
updateChannel: function (row) {
this.$axios({
method: 'post',
url: `/api/device/query/channel/update/${this.deviceId}`,
url: `./api/device/query/channel/update/${this.deviceId}`,
params: row
}).then(function (res) {
console.log(JSON.stringify(res));

View File

@ -114,7 +114,7 @@ export default {
getSystemInfo: function (){
this.$axios({
method: 'get',
url: `/api/server/system/info`,
url: `./api/server/system/info`,
}).then( (res)=> {
if (res.data.code === 0) {
this.$refs.consoleCPU.setData(res.data.data.cpu)
@ -128,7 +128,7 @@ export default {
getLoad: function (){
this.$axios({
method: 'get',
url: `/api/server/media_server/load`,
url: `./api/server/media_server/load`,
}).then( (res)=> {
if (res.data.code === 0) {
this.$refs.consoleNodeLoad.setData(res.data.data)
@ -139,7 +139,7 @@ export default {
getResourceInfo: function (){
this.$axios({
method: 'get',
url: `/api/server/resource/info`,
url: `./api/server/resource/info`,
}).then( (res)=> {
if (res.data.code === 0) {
this.$refs.consoleResource.setData(res.data.data)
@ -151,7 +151,7 @@ export default {
this.$axios({
method: 'get',
url: `/api/server/system/configInfo`,
url: `./api/server/system/configInfo`,
}).then( (res)=> {
console.log(res)
if (res.data.code === 0) {

View File

@ -335,7 +335,7 @@ export default {
var that = this;
await that.$axios({
method: 'get',
url:`/api/platform/exit/${deviceGbId}`
url:`./api/platform/exit/${deviceGbId}`
}).then(function (res) {
result = res.data;
}).catch(function (error) {

View File

@ -195,7 +195,7 @@ export default {
let that = this;
this.$axios({
method: 'get',
url:`/api/platform/query/10000/1`
url:`./api/platform/query/10000/1`
}).then(function (res) {
that.platformList = res.data.data.list;
}).catch(function (error) {
@ -212,7 +212,7 @@ export default {
if (that.proxyParam.mediaServerId !== "auto"){
that.$axios({
method: 'get',
url:`/api/proxy/ffmpeg_cmd/list`,
url:`./api/proxy/ffmpeg_cmd/list`,
params: {
mediaServerId: that.proxyParam.mediaServerId
}
@ -230,7 +230,7 @@ export default {
this.noneReaderHandler();
this.$axios({
method: 'post',
url:`/api/proxy/save`,
url:`./api/proxy/save`,
data: this.proxyParam
}).then((res)=> {
this.dialogLoading = false;
@ -261,7 +261,7 @@ export default {
var that = this;
await that.$axios({
method: 'get',
url:`/api/platform/exit/${deviceGbId}`
url:`./api/platform/exit/${deviceGbId}`
}).then(function (res) {
result = res.data;
}).catch(function (error) {

View File

@ -55,7 +55,7 @@ export default {
getProgress(){
this.$axios({
method: 'get',
url:`/api/device/query/${this.deviceId}/sync_status/`,
url:`./api/device/query/${this.deviceId}/sync_status/`,
}).then((res) => {
if (res.data.code === 0) {
if (!this.syncFlag) {

View File

@ -100,7 +100,7 @@ export default {
onSubmit: function () {
this.$axios({
method: 'post',
url: "/api/user/add",
url: "./api/user/add",
params: {
username: this.username,
password: this.password,
@ -139,7 +139,7 @@ export default {
this.$axios({
method: 'get',
url: "/api/role/all"
url: "./api/role/all"
}).then((res) => {
this.loading = true;
if (res.data.code === 0) {

View File

@ -116,7 +116,7 @@ export default {
console.log(this.form);
this.$axios({
method:"post",
url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
url:`./api/platform/catalog/${!this.isEdit? "add":"edit"}`,
data: this.form
}).then((res)=> {
if (res.data.code === 0) {

View File

@ -90,7 +90,7 @@ export default {
onSubmit: function () {
this.$axios({
method: 'post',
url:"/api/user/changePassword",
url:"./api/user/changePassword",
params: {
oldPassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'),
password: this.newPassword

View File

@ -85,7 +85,7 @@ export default {
onSubmit: function () {
this.$axios({
method: 'post',
url:"/api/user/changePasswordForAdmin",
url:"./api/user/changePasswordForAdmin",
params: {
password: this.newPassword,
userId: this.form.id,

View File

@ -65,7 +65,7 @@ export default {
onSubmit: function () {
this.$axios({
method: 'post',
url:"/api/user/changePushKey",
url:"./api/user/changePushKey",
params: {
pushKey: this.newPushKey,
userId: this.form.id,

View File

@ -44,7 +44,7 @@ export default {
let that = this;
this.$axios({
method: 'get',
url: '/api/play/start/' + deviceId + '/' + channelId
url: './api/play/start/' + deviceId + '/' + channelId
}).then(function (res) {
that.isLoging = false;
if (res.data.code === 0) {

View File

@ -98,7 +98,7 @@ export default {
this.$axios({
method:"post",
url:"/api/platform/update_channel_for_gb",
url:"./api/platform/update_channel_for_gb",
data:{
platformId: that.platformId,
channelReduces: that.chooseData

View File

@ -82,7 +82,7 @@ export default {
let that = this;
this.$axios({
method:"get",
url:`/api/platform/catalog`,
url:`./api/platform/catalog`,
params: {
platformId: that.platformId,
parentId: parentId
@ -134,7 +134,7 @@ export default {
removeCatalog: function (id, node){
this.$axios({
method:"delete",
url:`/api/platform/catalog/del`,
url:`./api/platform/catalog/del`,
params: {
id: id,
platformId: this.platformId,
@ -156,7 +156,7 @@ export default {
setDefaultCatalog: function (id){
this.$axios({
method:"post",
url:`/api/platform/catalog/default/update`,
url:`./api/platform/catalog/default/update`,
params: {
platformId: this.platformId,
catalogId: id,
@ -201,7 +201,7 @@ export default {
onClick: () => {
this.$axios({
method:"delete",
url:"/api/platform/catalog/relation/del",
url:"./api/platform/catalog/relation/del",
data: data
}).then((res)=>{
console.log("移除成功")

View File

@ -121,7 +121,7 @@ export default {
this.getCatalogFromUser((catalogId)=> {
this.$axios({
method:"post",
url:"/api/platform/update_channel_for_gb",
url:"./api/platform/update_channel_for_gb",
data:{
platformId: this.platformId,
all: all,
@ -149,7 +149,7 @@ export default {
this.$axios({
method:"delete",
url:"/api/platform/del_channel_for_gb",
url:"./api/platform/del_channel_for_gb",
data:{
platformId: this.platformId,
all: all,
@ -248,7 +248,7 @@ export default {
this.$axios({
method:"get",
url:`/api/platform/channel_list`,
url:`./api/platform/channel_list`,
params: {
page: that.currentPage,
count: that.count,
@ -290,7 +290,7 @@ export default {
}).then(() => {
this.$axios({
method:"delete",
url:"/api/platform/del_channel_for_gb",
url:"./api/platform/del_channel_for_gb",
data:{
platformId: this.platformId,
channelReduces: this.multipleSelection
@ -310,7 +310,7 @@ export default {
this.$axios({
method: "post",
url: "/api/platform/update_channel_for_gb",
url: "./api/platform/update_channel_for_gb",
data: {
platformId: this.platformId,
channelReduces: this.multipleSelection,

View File

@ -134,7 +134,7 @@ export default {
this.getCatalogFromUser((catalogId)=>{
this.$axios({
method:"post",
url:"/api/gbStream/add",
url:"./api/gbStream/add",
data:{
platformId: this.platformId,
catalogId: catalogId,
@ -163,7 +163,7 @@ export default {
this.$axios({
method:"delete",
url:"/api/gbStream/del",
url:"./api/gbStream/del",
data:{
platformId: this.platformId,
all: all,
@ -186,7 +186,7 @@ export default {
this.$axios({
method: 'get',
url:`/api/gbStream/list`,
url:`./api/gbStream/list`,
params: {
page: that.currentPage,
count: that.count,
@ -222,7 +222,7 @@ export default {
}).then(() => {
this.$axios({
method:"delete",
url:"/api/gbStream/del",
url:"./api/gbStream/del",
data:{
platformId: this.platformId,
gbStreams: this.multipleSelection,
@ -242,7 +242,7 @@ export default {
this.getCatalogFromUser((catalogId)=>{
this.$axios({
method:"post",
url:"/api/gbStream/add",
url:"./api/gbStream/add",
data:{
platformId: this.platformId,
catalogId: catalogId,

View File

@ -134,7 +134,7 @@ export default {
this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0
this.$axios({
method: 'post',
url:`/api/device/query/device/${this.isEdit?'update':'add'}/`,
url:`./api/device/query/device/${this.isEdit?'update':'add'}/`,
params: this.form
}).then((res) => {
console.log(res.data)

View File

@ -89,7 +89,7 @@ export default {
let that = this;
this.$axios({
method:"get",
url:`/api/platform/catalog`,
url:`./api/platform/catalog`,
params: {
platformId: that.platformId,
parentId: parentId
@ -111,7 +111,7 @@ export default {
if (node.level === 0) {
this.$axios({
method:"get",
url:`/api/platform/info/` + this.platformId,
url:`./api/platform/info/` + this.platformId,
})
.then((res)=> {
if (res.data.code === 0) {

View File

@ -60,7 +60,7 @@ export default {
console.log(this.form);
this.$axios({
method:"post",
url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
url:`./api/platform/catalog/${!this.isEdit? "add":"edit"}`,
data: this.form
})
.then((res)=> {

View File

@ -81,7 +81,7 @@ export default {
console.log(this.form);
this.$axios({
method: 'get',
url:`api/onvif/rtsp`,
url:`./api/onvif/rtsp`,
params: {
hostname: this.form.hostName,
timeout: 3000,

View File

@ -138,7 +138,7 @@ export default {
showDialog: false,
isLoging: false,
onSubmit_text: "立即创建",
saveUrl: "/api/platform/save",
saveUrl: "./api/platform/save",
platform: {
id: null,
@ -192,7 +192,7 @@ export default {
this.saveUrl = "/api/platform/add";
this.$axios({
method: 'get',
url:`/api/platform/server_config`
url:`./api/platform/server_config`
}).then(function (res) {
console.log(res);
if (res.data.code === 0) {
@ -315,7 +315,7 @@ export default {
var that = this;
await that.$axios({
method: 'get',
url:`/api/platform/exit/${deviceGbId}`})
url:`./api/platform/exit/${deviceGbId}`})
.then(function (res) {
if (res.data.code === 0) {
result = res.data.data;

View File

@ -109,7 +109,7 @@ export default {
if (this.edit) {
this.$axios({
method:"post",
url:`/api/push/save_to_gb`,
url:`./api/push/save_to_gb`,
data: this.proxyParam
}).then( (res) => {
if (res.data.code === 0) {
@ -129,7 +129,7 @@ export default {
}else {
this.$axios({
method:"post",
url:`/api/push/add`,
url:`./api/push/add`,
data: this.proxyParam
}).then( (res) => {
if (res.data.code === 0) {
@ -159,7 +159,7 @@ export default {
var that = this;
await that.$axios({
method:"get",
url:`/api/platform/exit/${deviceGbId}`
url:`./api/platform/exit/${deviceGbId}`
}).then(function (res) {
result = res.data;
}).catch(function (error) {

View File

@ -72,7 +72,7 @@ export default {
onSubmit: function () {
console.log("onSubmit");
this.isLoging = true;
let url = `/api/position/history/${this.channel.deviceId}?start=${this.searchFrom}&end=${this.searchTo}`;
let url = `./api/position/history/${this.channel.deviceId}?start=${this.searchFrom}&end=${this.searchTo}`;
if (this.channel.channelId) {
url+="&channelId=${this.channel.channelId}"
}

View File

@ -71,7 +71,7 @@ export default {
getProgress: function (callback){
this.$axios({
method: 'get',
url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
url: `./api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
}).then((res)=> {
console.log(res)
if (res.data.code === 0) {
@ -124,7 +124,7 @@ export default {
stopDownloadRecord: function (callback) {
this.$axios({
method: 'get',
url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.stream
url: './api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.stream
}).then((res)=> {
if (callback) callback(res)
});
@ -132,7 +132,7 @@ export default {
getFileDownload: function (){
this.$axios({
method: 'get',
url:`/record_proxy/${this.mediaServerId}/api/record/file/download/task/add`,
url:`./record_proxy/${this.mediaServerId}/api/record/file/download/task/add`,
params: {
app: this.app,
stream: this.stream,
@ -164,7 +164,7 @@ export default {
getProgressForFile: function (callback){
this.$axios({
method: 'get',
url:`/record_proxy/${this.mediaServerId}/api/record/file/download/task/list`,
url:`./record_proxy/${this.mediaServerId}/api/record/file/download/task/list`,
params: {
app: this.app,
stream: this.stream,

View File

@ -135,7 +135,7 @@ export default {
this.loading = true
this.$axios({
method: 'get',
url: '/api/play/start/' + deviceId + '/' + channelId
url: './api/play/start/' + deviceId + '/' + channelId
}).then(function (res) {
if (res.data.code === 0 && res.data.data) {
let videoUrl;

View File

@ -298,7 +298,7 @@ export default {
let that = this;
this.$axios({
method: 'get',
url: '/api/play/start/' + deviceId + '/' + channelId
url: './api/play/start/' + deviceId + '/' + channelId
}).then(function (res) {
that.isLoging = false;
if (res.data.code === 0) {

View File

@ -9,7 +9,7 @@ class DeviceService{
getDeviceList(currentPage, count, callback, errorCallback){
this.$axios({
method: 'get',
url:`/api/device/query/devices`,
url:`./api/device/query/devices`,
params: {
page: currentPage,
count: count
@ -25,7 +25,7 @@ class DeviceService{
getDevice(deviceId, callback, errorCallback){
this.$axios({
method: 'get',
url:`/api/device/query/devices/${deviceId}`,
url:`./api/device/query/devices/${deviceId}`,
}).then((res) => {
if (typeof (callback) == "function") callback(res.data)
}).catch((error) => {
@ -82,7 +82,7 @@ class DeviceService{
getChanel(isCatalog, catalogUnderDevice, deviceId, currentPage, count, callback, errorCallback) {
this.$axios({
method: 'get',
url: `/api/device/query/devices/${deviceId}/channels`,
url: `./api/device/query/devices/${deviceId}/channels`,
params:{
page: currentPage,
count: count,
@ -121,7 +121,7 @@ class DeviceService{
getSubChannel(isCatalog, deviceId, channelId, currentPage, count, callback, errorCallback) {
this.$axios({
method: 'get',
url: `/api/device/query/sub_channels/${deviceId}/${channelId}/channels`,
url: `./api/device/query/sub_channels/${deviceId}/${channelId}/channels`,
params:{
page: currentPage,
count: count,
@ -161,7 +161,7 @@ class DeviceService{
}
this.$axios({
method: 'get',
url: `/api/device/query/tree/${deviceId}`,
url: `./api/device/query/tree/${deviceId}`,
params:{
page: currentPage,
count: count,

View File

@ -9,7 +9,7 @@ class MediaServer{
getOnlineMediaServerList(callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/online/list`,
url:`./api/server/media_server/online/list`,
}).then((res) => {
if (typeof (callback) == "function") callback(res.data)
}).catch((error) => {
@ -19,7 +19,7 @@ class MediaServer{
getMediaServerList(callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/list`,
url:`./api/server/media_server/list`,
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
}).catch(function (error) {
@ -30,7 +30,7 @@ class MediaServer{
getMediaServer(id, callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/one/` + id,
url:`./api/server/media_server/one/` + id,
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
}).catch(function (error) {
@ -41,7 +41,7 @@ class MediaServer{
checkServer(param, callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/check`,
url:`./api/server/media_server/check`,
params: {
ip: param.ip,
port: param.httpPort,
@ -57,7 +57,7 @@ class MediaServer{
checkRecordServer(param, callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/record/check`,
url:`./api/server/media_server/record/check`,
params: {
ip: param.ip,
port: param.recordAssistPort
@ -72,7 +72,7 @@ class MediaServer{
addServer(param, callback){
this.$axios({
method: 'post',
url:`/api/server/media_server/save`,
url:`./api/server/media_server/save`,
data: param
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
@ -84,7 +84,7 @@ class MediaServer{
delete(id, callback) {
this.$axios({
method: 'delete',
url:`/api/server/media_server/delete`,
url:`./api/server/media_server/delete`,
params: {
id: id
}