Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
This commit is contained in:
648540858 2022-09-01 14:50:28 +08:00
commit 03d6ad289b
76 changed files with 979 additions and 904 deletions

View File

@ -1,7 +0,0 @@
# 捐赠
项目目前仍在积极开发。大家的捐赠以及start可以让我看到大家的支持于关注。更加有动力把项目维护下去。
<div align="left">
<img src=_media/weixin.jpg style="height: 500px; border: 1px solid #e2e2e2"/>
<img src=_media/zhifubao.jpg style="height: 500px; border: 1px solid #e2e2e2; margin-left: 20px"/>
</div>

View File

@ -29,5 +29,4 @@
- [设备注册不上来的解决办法](_content/qa/regiser_error.md) - [设备注册不上来的解决办法](_content/qa/regiser_error.md)
- [点播超时/报错的解决办法](_content/qa/play_error.md) - [点播超时/报错的解决办法](_content/qa/play_error.md)
* [**免责声明**](_content/disclaimers.md) * [**免责声明**](_content/disclaimers.md)
* [**捐赠**](_content/donation.md)
* [**关于本文档**](_content/about_doc.md) * [**关于本文档**](_content/about_doc.md)

View File

@ -11,7 +11,7 @@
<groupId>com.genersoft</groupId> <groupId>com.genersoft</groupId>
<artifactId>wvp-pro</artifactId> <artifactId>wvp-pro</artifactId>
<version>2.3.1</version> <version>2.3.2</version>
<name>web video platform</name> <name>web video platform</name>
<description>国标28181视频平台</description> <description>国标28181视频平台</description>

View File

@ -31,6 +31,8 @@ public class StreamInfo {
private String rtsp; private String rtsp;
private String rtsps; private String rtsps;
private String rtc; private String rtc;
private String rtcs;
private String mediaServerId; private String mediaServerId;
private Object tracks; private Object tracks;
private String startTime; private String startTime;
@ -302,4 +304,12 @@ public class StreamInfo {
public void setIp(String ip) { public void setIp(String ip) {
this.ip = ip; this.ip = ip;
} }
public String getRtcs() {
return rtcs;
}
public void setRtcs(String rtcs) {
this.rtcs = rtcs;
}
} }

View File

@ -14,8 +14,6 @@ public class VideoManagerConstants {
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_"; public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
public static final String MEDIA_SERVER_KEEPALIVE_PREFIX = "VMP_MEDIA_SERVER_KEEPALIVE_";
public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_";
public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM"; public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";

View File

@ -1,40 +0,0 @@
package com.genersoft.iot.vmp.conf;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import java.util.Properties;
public class RedisKeyExpirationEventMessageListener extends KeyExpirationEventMessageListener {
private UserSetting userSetting;
private RedisMessageListenerContainer listenerContainer;
private String keyspaceNotificationsConfigParameter = "EA";
public RedisKeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {
super(listenerContainer);
this.listenerContainer = listenerContainer;
this.userSetting = userSetting;
}
@Override
public void init() {
if (!userSetting.getRedisConfig()) {
// 配置springboot默认Config为空即不让应用去修改redis的默认配置因为Redis服务出于安全会禁用CONFIG命令给远程用户使用
setKeyspaceNotificationsConfigParameter("");
}else {
RedisConnection connection = this.listenerContainer.getConnectionFactory().getConnection();
Properties config = connection.getConfig("notify-keyspace-events");
try {
if (!keyspaceNotificationsConfigParameter.equals(config.getProperty("notify-keyspace-events"))) {
connection.setConfig("notify-keyspace-events", keyspaceNotificationsConfigParameter);
}
} finally {
connection.close();
}
}
super.init();
}
}

View File

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -15,6 +16,7 @@ import java.util.List;
/** /**
* 系统启动时控制上级平台重新注册 * 系统启动时控制上级平台重新注册
* @author lin
*/ */
@Component @Component
@Order(value=3) @Order(value=3)
@ -27,7 +29,7 @@ public class SipPlatformRunner implements CommandLineRunner {
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Autowired @Autowired
private EventPublisher publisher; private IPlatformService platformService;
@Autowired @Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform; private ISIPCommanderForPlatform sipCommanderForPlatform;
@ -35,33 +37,26 @@ public class SipPlatformRunner implements CommandLineRunner {
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
// 设置所有平台离线 // 获取所有启用的平台
storager.outlineForAllParentPlatform();
// 清理所有平台注册缓存
redisCatchStorage.cleanPlatformRegisterInfos();
// 停止所有推流
// zlmrtpServerFactory.closeAllSendRtpStream();
List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true); List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true);
for (ParentPlatform parentPlatform : parentPlatforms) { for (ParentPlatform parentPlatform : parentPlatforms) {
redisCatchStorage.updatePlatformRegister(parentPlatform); // 更新缓存
redisCatchStorage.updatePlatformKeepalive(parentPlatform);
ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch();
parentPlatformCatch.setParentPlatform(parentPlatform); parentPlatformCatch.setParentPlatform(parentPlatform);
parentPlatformCatch.setId(parentPlatform.getServerGBId()); parentPlatformCatch.setId(parentPlatform.getServerGBId());
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
if (parentPlatform.isStatus()) {
// 设置所有平台离线
platformService.offline(parentPlatform);
// 取消订阅
sipCommanderForPlatform.unregister(parentPlatform, null, (eventResult)->{
platformService.login(parentPlatform);
});
}else {
platformService.login(parentPlatform);
}
// 取消订阅
sipCommanderForPlatform.unregister(parentPlatform, null, (eventResult)->{
// 发送平台未注册消息
publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId());
});
} }
} }
} }

View File

@ -31,8 +31,6 @@ public class UserSetting {
private Boolean logInDatebase = Boolean.TRUE; private Boolean logInDatebase = Boolean.TRUE;
private Boolean redisConfig = Boolean.TRUE;
private String serverId = "000000"; private String serverId = "000000";
private String thirdPartyGBIdReg = "[\\s\\S]*"; private String thirdPartyGBIdReg = "[\\s\\S]*";
@ -123,14 +121,6 @@ public class UserSetting {
this.thirdPartyGBIdReg = thirdPartyGBIdReg; this.thirdPartyGBIdReg = thirdPartyGBIdReg;
} }
public Boolean getRedisConfig() {
return redisConfig;
}
public void setRedisConfig(Boolean redisConfig) {
this.redisConfig = redisConfig;
}
public Boolean getRecordSip() { public Boolean getRecordSip() {
return recordSip; return recordSip;
} }

View File

@ -1,6 +1,8 @@
package com.genersoft.iot.vmp.conf.security; package com.genersoft.iot.vmp.conf.security;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.apache.poi.hssf.eventmodel.ERFListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
@ -28,8 +30,8 @@ public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoi
response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified"); response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
response.setHeader("Content-type", "application/json;charset=UTF-8"); response.setHeader("Content-type", "application/json;charset=UTF-8");
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "-1"); jsonObject.put("code", ErrorCode.ERROR401.getCode());
jsonObject.put("msg", "请登录后重新请求"); jsonObject.put("msg", ErrorCode.ERROR401.getMsg());
String logUri = "api/user/login"; String logUri = "api/user/login";
if (request.getRequestURI().contains(logUri)){ if (request.getRequestURI().contains(logUri)){
jsonObject.put("msg", e.getMessage()); jsonObject.put("msg", e.getMessage());

View File

@ -0,0 +1,24 @@
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

@ -10,14 +10,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import javax.sip.*; import javax.sip.*;
import java.util.Properties; import java.util.Properties;
import java.util.TooManyListenersException; import java.util.TooManyListenersException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration @Configuration
public class SipLayer{ public class SipLayer{
@ -52,7 +48,9 @@ public class SipLayer{
* 完整配置参考 gov.nist.javax.sip.SipStackImpl需要下载源码 * 完整配置参考 gov.nist.javax.sip.SipStackImpl需要下载源码
* gov/nist/javax/sip/SipStackImpl.class * gov/nist/javax/sip/SipStackImpl.class
*/ */
properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true"); if (logger.isDebugEnabled()) {
properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false");
}
// 接收所有notify请求即使没有订阅 // 接收所有notify请求即使没有订阅
properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true");
// 为_NULL _对话框传递_终止的_事件 // 为_NULL _对话框传递_终止的_事件
@ -63,13 +61,13 @@ public class SipLayer{
properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60"); properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
/** /**
* sip_server_log.log sip_debug_log.log public static final int TRACE_NONE = * sip_server_log.log sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
* 0; public static final int TRACE_MESSAGES = 16; public static final int
* TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
*/ */
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log"); // if (logger.isDebugEnabled()) {
properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log"); // properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
// }
sipStack = (SipStackImpl) sipFactory.createSipStack(properties); sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
return sipStack; return sipStack;

View File

@ -84,7 +84,7 @@ public class ParentPlatform {
* 注册周期 () * 注册周期 ()
*/ */
@Schema(description = "注册周期 (秒)") @Schema(description = "注册周期 (秒)")
private String expires; private int expires;
/** /**
* 心跳周期() * 心跳周期()
@ -286,11 +286,11 @@ public class ParentPlatform {
this.password = password; this.password = password;
} }
public String getExpires() { public int getExpires() {
return expires; return expires;
} }
public void setExpires(String expires) { public void setExpires(int expires) {
this.expires = expires; this.expires = expires;
} }

View File

@ -4,7 +4,9 @@ public class ParentPlatformCatch {
private String id; private String id;
// 心跳未回复次数 /**
* 心跳未回复次数
*/
private int keepAliveReply; private int keepAliveReply;
// 注册未回复次数 // 注册未回复次数

View File

@ -14,6 +14,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/**
* @author lin
*/
@Component @Component
public class SubscribeHolder { public class SubscribeHolder {

View File

@ -2,9 +2,6 @@ package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent;
import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformCycleRegisterEvent;
import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent;
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent;
@ -31,36 +28,6 @@ public class EventPublisher {
@Autowired @Autowired
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
/**
* 平台心跳到期事件
* @param platformGbId
*/
public void platformKeepaliveExpireEventPublish(String platformGbId){
PlatformKeepaliveExpireEvent platformKeepaliveExpireEvent = new PlatformKeepaliveExpireEvent(this);
platformKeepaliveExpireEvent.setPlatformGbID(platformGbId);
applicationEventPublisher.publishEvent(platformKeepaliveExpireEvent);
}
/**
* 平台未注册事件
* @param platformGbId
*/
public void platformNotRegisterEventPublish(String platformGbId){
PlatformNotRegisterEvent platformNotRegisterEvent = new PlatformNotRegisterEvent(this);
platformNotRegisterEvent.setPlatformGbID(platformGbId);
applicationEventPublisher.publishEvent(platformNotRegisterEvent);
}
/**
* 平台周期注册事件
* @param paltformGbId
*/
public void platformRegisterCycleEventPublish(String paltformGbId) {
PlatformCycleRegisterEvent platformCycleRegisterEvent = new PlatformCycleRegisterEvent(this);
platformCycleRegisterEvent.setPlatformGbID(paltformGbId);
applicationEventPublisher.publishEvent(platformCycleRegisterEvent);
}
/** /**
* 设备报警事件 * 设备报警事件

View File

@ -59,9 +59,25 @@ public class SipSubscribe {
void response(EventResult eventResult); void response(EventResult eventResult);
} }
/**
*
*/
public enum EventResultType{
// 超时
timeout,
// 回复
response,
// 事务已结束
transactionTerminated,
// 会话已结束
dialogTerminated,
// 设备未找到
deviceNotFoundEvent
}
public static class EventResult<EventObject>{ public static class EventResult<EventObject>{
public int statusCode; public int statusCode;
public String type; public EventResultType type;
public String msg; public String msg;
public String callId; public String callId;
public Dialog dialog; public Dialog dialog;
@ -76,7 +92,7 @@ public class SipSubscribe {
ResponseEvent responseEvent = (ResponseEvent)event; ResponseEvent responseEvent = (ResponseEvent)event;
Response response = responseEvent.getResponse(); Response response = responseEvent.getResponse();
this.dialog = responseEvent.getDialog(); this.dialog = responseEvent.getDialog();
this.type = "response"; this.type = EventResultType.response;
if (response != null) { if (response != null) {
this.msg = response.getReasonPhrase(); this.msg = response.getReasonPhrase();
this.statusCode = response.getStatusCode(); this.statusCode = response.getStatusCode();
@ -85,28 +101,28 @@ public class SipSubscribe {
}else if (event instanceof TimeoutEvent) { }else if (event instanceof TimeoutEvent) {
TimeoutEvent timeoutEvent = (TimeoutEvent)event; TimeoutEvent timeoutEvent = (TimeoutEvent)event;
this.type = "timeout"; this.type = EventResultType.timeout;
this.msg = "消息超时未回复"; this.msg = "消息超时未回复";
this.statusCode = -1024; this.statusCode = -1024;
this.dialog = timeoutEvent.getClientTransaction().getDialog(); this.dialog = timeoutEvent.getClientTransaction().getDialog();
this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null; this.callId = this.dialog != null?timeoutEvent.getClientTransaction().getDialog().getCallId().getCallId(): null;
}else if (event instanceof TransactionTerminatedEvent) { }else if (event instanceof TransactionTerminatedEvent) {
TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event; TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event;
this.type = "transactionTerminated"; this.type = EventResultType.transactionTerminated;
this.msg = "事务已结束"; this.msg = "事务已结束";
this.statusCode = -1024; this.statusCode = -1024;
this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId(); this.callId = transactionTerminatedEvent.getClientTransaction().getDialog().getCallId().getCallId();
this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog(); this.dialog = transactionTerminatedEvent.getClientTransaction().getDialog();
}else if (event instanceof DialogTerminatedEvent) { }else if (event instanceof DialogTerminatedEvent) {
DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event; DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event;
this.type = "dialogTerminated"; this.type = EventResultType.dialogTerminated;
this.msg = "会话已结束"; this.msg = "会话已结束";
this.statusCode = -1024; this.statusCode = -1024;
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
this.dialog = dialogTerminatedEvent.getDialog(); this.dialog = dialogTerminatedEvent.getDialog();
}else if (event instanceof DeviceNotFoundEvent) { }else if (event instanceof DeviceNotFoundEvent) {
DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event; DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
this.type = "deviceNotFoundEvent"; this.type = EventResultType.deviceNotFoundEvent;
this.msg = "设备未找到"; this.msg = "设备未找到";
this.statusCode = -1024; this.statusCode = -1024;
this.dialog = deviceNotFoundEvent.getDialog(); this.dialog = deviceNotFoundEvent.getDialog();

View File

@ -1,28 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire;
import org.springframework.context.ApplicationEvent;
/**
* 平台心跳超时事件
*/
public class PlatformKeepaliveExpireEvent extends ApplicationEvent {
/**
* Add default serial version ID
*/
private static final long serialVersionUID = 1L;
private String platformGbID;
public PlatformKeepaliveExpireEvent(Object source) {
super(source);
}
public String getPlatformGbID() {
return platformGbID;
}
public void setPlatformGbID(String platformGbID) {
this.platformGbID = platformGbID;
}
}

View File

@ -1,87 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.sip.message.Response;
/**
* @description: 平台心跳超时事件
* @author: panll
* @date: 2020年11月5日 10:00
*/
@Component
public class PlatformKeepaliveExpireEventLister implements ApplicationListener<PlatformKeepaliveExpireEvent> {
private final static Logger logger = LoggerFactory.getLogger(PlatformKeepaliveExpireEventLister.class);
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform;
@Autowired
private SipSubscribe sipSubscribe;
@Autowired
private EventPublisher publisher;
@Override
public void onApplicationEvent(@NotNull PlatformKeepaliveExpireEvent event) {
if (logger.isDebugEnabled()) {
logger.debug("平台心跳到期事件事件触发平台国标ID" + event.getPlatformGbID());
}
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID());
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(event.getPlatformGbID());
if (parentPlatformCatch == null) {
return;
}
if (parentPlatform == null) {
logger.debug("平台心跳到期事件事件触发,但平台已经删除!!! 平台国标ID" + event.getPlatformGbID());
return;
}
parentPlatformCatch.setParentPlatform(parentPlatform);
// 发送心跳
if (parentPlatformCatch.getKeepAliveReply() >= 3) {
// 有3次未收到心跳回复, 设置平台状态为离线, 开始重新注册
logger.warn("有3次未收到心跳回复,标记设置平台状态为离线, 并重新注册 平台国标ID" + event.getPlatformGbID());
storager.updateParentPlatformStatus(event.getPlatformGbID(), false);
publisher.platformNotRegisterEventPublish(event.getPlatformGbID());
parentPlatformCatch.setKeepAliveReply(0);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
}else {
// 再次发送心跳
String callId = sipCommanderForPlatform.keepalive(parentPlatform);
parentPlatformCatch.setKeepAliveReply( parentPlatformCatch.getKeepAliveReply() + 1);
// 存储心跳信息, 并设置状态为未回复, 如果多次过期仍未收到回复,则认为上级平台已经离线
redisCatchStorage.updatePlatformKeepalive(parentPlatform);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
sipSubscribe.addOkSubscribe(callId, (SipSubscribe.EventResult eventResult) ->{
if (eventResult.statusCode == Response.OK) {
// 收到心跳响应信息,
parentPlatformCatch.setKeepAliveReply(0);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
}
} );
}
}
}

View File

@ -1,24 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
import org.springframework.context.ApplicationEvent;
public class PlatformCycleRegisterEvent extends ApplicationEvent {
/**
* Add default serial version ID
*/
private static final long serialVersionUID = 1L;
private String platformGbID;
public String getPlatformGbID() {
return platformGbID;
}
public void setPlatformGbID(String platformGbID) {
this.platformGbID = platformGbID;
}
public PlatformCycleRegisterEvent(Object source) {
super(source);
}
}

View File

@ -1,46 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.util.Timer;
import java.util.TimerTask;
@Component
public class PlatformCycleRegisterEventLister implements ApplicationListener<PlatformCycleRegisterEvent> {
private final static Logger logger = LoggerFactory.getLogger(PlatformCycleRegisterEventLister.class);
@Autowired
private IVideoManagerStorage storager;
@Autowired
private ISIPCommanderForPlatform sipCommanderFroPlatform;
@Autowired
private DynamicTask dynamicTask;
@Override
public void onApplicationEvent(PlatformCycleRegisterEvent event) {
logger.info("上级平台周期注册事件");
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID());
if (parentPlatform == null) {
logger.info("[ 平台未注册事件 ] 平台已经删除!!! 平台国标ID" + event.getPlatformGbID());
return;
}
String taskKey = "platform-cycle-register" + parentPlatform.getServerGBId();;
SipSubscribe.Event okEvent = (responseEvent)->{
dynamicTask.stop(taskKey);
};
dynamicTask.startCron(taskKey, ()->{
logger.info("[平台注册]再次向平台注册平台国标ID" + event.getPlatformGbID());
sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
}, Integer.parseInt(parentPlatform.getExpires())* 1000);
}
}

View File

@ -1,25 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
import org.springframework.context.ApplicationEvent;
public class PlatformNotRegisterEvent extends ApplicationEvent {
/**
* Add default serial version ID
*/
private static final long serialVersionUID = 1L;
private String platformGbID;
public PlatformNotRegisterEvent(Object source) {
super(source);
}
public String getPlatformGbID() {
return platformGbID;
}
public void setPlatformGbID(String platformGbID) {
this.platformGbID = platformGbID;
}
}

View File

@ -1,90 +0,0 @@
package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @description: 平台未注册事件,来源有二:
* 1平台新添加
* 2平台心跳超时
* @author: panll
* @date: 2020年11月24日 10:00
*/
@Component
public class PlatformNotRegisterEventLister implements ApplicationListener<PlatformNotRegisterEvent> {
private final static Logger logger = LoggerFactory.getLogger(PlatformNotRegisterEventLister.class);
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IMediaServerService mediaServerService;
@Autowired
private SIPCommanderFroPlatform sipCommanderFroPlatform;
@Autowired
private ZLMRTPServerFactory zlmrtpServerFactory;
@Autowired
private SipConfig config;
@Autowired
private DynamicTask dynamicTask;
// @Autowired
// private RedisUtil redis;
@Override
public void onApplicationEvent(PlatformNotRegisterEvent event) {
logger.info("[ 平台未注册事件 ]平台国标ID" + event.getPlatformGbID());
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformGbID());
if (parentPlatform == null) {
logger.info("[ 平台未注册事件 ] 平台已经删除!!! 平台国标ID" + event.getPlatformGbID());
return;
}
// 查询是否有推流 如果有则都停止
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID());
if (sendRtpItems != null && sendRtpItems.size() > 0) {
logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流", event.getPlatformGbID());
for (SendRtpItem sendRtpItem : sendRtpItems) {
redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId(), null, null);
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
Map<String, Object> param = new HashMap<>();
param.put("vhost", "__defaultVhost__");
param.put("app", sendRtpItem.getApp());
param.put("stream", sendRtpItem.getStreamId());
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
}
}
String taskKey = "platform-not-register-" + parentPlatform.getServerGBId();
SipSubscribe.Event okEvent = (responseEvent)->{
dynamicTask.stop(taskKey);
};
dynamicTask.startCron(taskKey, ()->{
logger.info("[平台注册]再次向平台注册平台国标ID" + event.getPlatformGbID());
sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
}, config.getRegisterTimeInterval()* 1000);
}
}

View File

@ -30,23 +30,10 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
@Autowired @Autowired
private IVideoManagerStorage storager; private IVideoManagerStorage storager;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IMediaServerService mediaServerService;
@Autowired @Autowired
private SIPCommanderFroPlatform sipCommanderFroPlatform; private SIPCommanderFroPlatform sipCommanderFroPlatform;
@Autowired
private ZLMRTPServerFactory zlmrtpServerFactory;
@Autowired
private SipConfig config;
@Autowired
private UserSetting userSetting;
@Autowired @Autowired
private IGbStreamService gbStreamService; private IGbStreamService gbStreamService;

View File

@ -60,7 +60,6 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
// TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId()); List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
if (gbStreams.size() == 0) { if (gbStreams.size() == 0) {
logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId());
return; return;
} }
for (DeviceChannel deviceChannel : gbStreams) { for (DeviceChannel deviceChannel : gbStreams) {

View File

@ -71,7 +71,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
@Override @Override
@Async @Async
public void processRequest(RequestEvent requestEvent) { public void processRequest(RequestEvent requestEvent) {
logger.debug("\n收到请求\n{}", requestEvent.getRequest());
String method = requestEvent.getRequest().getMethod(); String method = requestEvent.getRequest().getMethod();
ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
if (sipRequestProcessor == null) { if (sipRequestProcessor == null) {
@ -90,7 +89,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
@Async @Async
public void processResponse(ResponseEvent responseEvent) { public void processResponse(ResponseEvent responseEvent) {
Response response = responseEvent.getResponse(); Response response = responseEvent.getResponse();
logger.debug("\n收到响应\n{}", responseEvent.getResponse());
int status = response.getStatusCode(); int status = response.getStatusCode();
if (((status >= 200) && (status < 300)) || status == Response.UNAUTHORIZED) { // Success! if (((status >= 200) && (status < 300)) || status == Response.UNAUTHORIZED) { // Success!
@ -114,7 +112,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
} else if ((status >= 100) && (status < 200)) { } else if ((status >= 100) && (status < 200)) {
// 增加其它无需回复的响应如101180等 // 增加其它无需回复的响应如101180等
} else { } else {
logger.warn("接收到失败的response响应status" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); logger.warn("接收到失败的response响应status" + status + ",message:" + response.getReasonPhrase());
if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) { if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);
if (callIdHeader != null) { if (callIdHeader != null) {

View File

@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
@ -98,7 +98,7 @@ public interface ISIPCommander {
* @param device 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
/** /**
* 请求回放视频流 * 请求回放视频流

View File

@ -15,7 +15,7 @@ public interface ISIPCommanderForPlatform {
* @return * @return
*/ */
boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain); boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister);
/** /**
* 向上级平台注销 * 向上级平台注销
@ -30,7 +30,7 @@ public interface ISIPCommanderForPlatform {
* @param parentPlatform * @param parentPlatform
* @return callId(作为接受回复的判定) * @return callId(作为接受回复的判定)
*/ */
String keepalive(ParentPlatform parentPlatform); String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
/** /**

View File

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.MessageFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -75,7 +76,7 @@ public class SIPRequestHeaderPlarformProvider {
} }
public Request createRegisterRequest(@NotNull ParentPlatform platform, long CSeq, String fromTag, String viaTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { public Request createRegisterRequest(@NotNull ParentPlatform platform, long CSeq, String fromTag, String viaTag, CallIdHeader callIdHeader, boolean isRegister) throws ParseException, InvalidArgumentException, PeerUnavailableException {
Request request = null; Request request = null;
String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort(); String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
//请求行 //请求行
@ -109,18 +110,20 @@ public class SIPRequestHeaderPlarformProvider {
.createSipURI(platform.getDeviceGBId(), sipAddress)); .createSipURI(platform.getDeviceGBId(), sipAddress));
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
ExpiresHeader expires = sipFactory.createHeaderFactory().createExpiresHeader(Integer.parseInt(platform.getExpires())); ExpiresHeader expires = sipFactory.createHeaderFactory().createExpiresHeader(isRegister ? platform.getExpires() : 0);
request.addHeader(expires); request.addHeader(expires);
UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory);
request.addHeader(userAgentHeader);
return request; return request;
} }
public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String viaTag, public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String viaTag,
String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader) throws ParseException, PeerUnavailableException, InvalidArgumentException { String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader, boolean isRegister) throws ParseException, PeerUnavailableException, InvalidArgumentException {
Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader); Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader, isRegister);
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
if (www == null) { if (www == null) {
AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest"); AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest");

View File

@ -12,6 +12,7 @@ import javax.sip.message.Request;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
@ -266,15 +267,7 @@ public class SIPRequestHeaderProvider {
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
.createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort())); .createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort()));
infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
List<String> agentParam = new ArrayList<>(); UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory);
agentParam.add("wvp-pro");
// TODO 添加版本信息以及日期
UserAgentHeader userAgentHeader = null;
try {
userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
} catch (ParseException e) {
throw new RuntimeException(e);
}
infoRequest.addHeader(userAgentHeader); infoRequest.addHeader(userAgentHeader);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application",

View File

@ -10,12 +10,12 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@ -33,19 +33,15 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.*; import javax.sip.*;
import javax.sip.address.Address; import javax.sip.address.Address;
import javax.sip.address.SipURI; import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.*; import javax.sip.header.*;
import javax.sip.message.Request; import javax.sip.message.Request;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
/** /**
* @description:设备能力接口用于定义设备的控制查询能力 * @description:设备能力接口用于定义设备的控制查询能力
@ -88,7 +84,7 @@ public class SIPCommander implements ISIPCommander {
private UserSetting userSetting; private UserSetting userSetting;
@Autowired @Autowired
private ZLMHttpHookSubscribe subscribe; private ZlmHttpHookSubscribe subscribe;
@Autowired @Autowired
private SipSubscribe sipSubscribe; private SipSubscribe sipSubscribe;
@ -351,7 +347,7 @@ public class SIPCommander implements ISIPCommander {
*/ */
@Override @Override
public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
String stream = ssrcInfo.getStream(); String stream = ssrcInfo.getStream();
try { try {
if (device == null) { if (device == null) {
@ -640,7 +636,7 @@ public class SIPCommander implements ISIPCommander {
hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
subscribe.removeSubscribe(hookSubscribe); subscribe.removeSubscribe(hookSubscribe);
hookSubscribe.getContent().put("regist", false); hookSubscribe.getContent().put("regist", false);
hookSubscribe.getContent().put("schema", "rtmp"); hookSubscribe.getContent().put("schema", "rtsp");
// 添加流注销的订阅注销了后向设备发送bye // 添加流注销的订阅注销了后向设备发送bye
subscribe.addSubscribe(hookSubscribe, subscribe.addSubscribe(hookSubscribe,
(MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{ (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{
@ -780,15 +776,7 @@ public class SIPCommander implements ISIPCommander {
// 增加Contact header // 增加Contact header
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort())); Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
List<String> agentParam = new ArrayList<>(); UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory);
agentParam.add("wvp-pro");
// TODO 添加版本信息以及日期
UserAgentHeader userAgentHeader = null;
try {
userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
} catch (ParseException e) {
throw new RuntimeException(e);
}
byeRequest.addHeader(userAgentHeader); byeRequest.addHeader(userAgentHeader);
ClientTransaction clientTransaction = null; ClientTransaction clientTransaction = null;
if("TCP".equals(protocol)) { if("TCP".equals(protocol)) {
@ -1680,14 +1668,11 @@ public class SIPCommander implements ISIPCommander {
clientTransaction = udpSipProvider.getNewClientTransaction(request); clientTransaction = udpSipProvider.getNewClientTransaction(request);
} }
if (request.getHeader(UserAgentHeader.NAME) == null) { if (request.getHeader(UserAgentHeader.NAME) == null) {
List<String> agentParam = new ArrayList<>();
agentParam.add("wvp-pro");
// TODO 添加版本信息以及日期
UserAgentHeader userAgentHeader = null; UserAgentHeader userAgentHeader = null;
try { try {
userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory);
} catch (ParseException e) { } catch (ParseException e) {
throw new RuntimeException(e); logger.error("添加UserAgentHeader失败", e);
} }
request.addHeader(userAgentHeader); request.addHeader(userAgentHeader);
} }

View File

@ -4,6 +4,8 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider;
import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
@ -75,28 +77,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
@Override @Override
public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
return register(parentPlatform, null, null, errorEvent, okEvent, false); return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
} }
@Override @Override
public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); return register(parentPlatform, null, null, errorEvent, okEvent, false, false);
parentPlatform.setExpires("0");
if (parentPlatformCatch != null) {
parentPlatformCatch.setParentPlatform(parentPlatform);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
}
return register(parentPlatform, null, null, errorEvent, okEvent, false);
} }
@Override @Override
public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) { SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) {
try { try {
Request request; Request request;
String tm = Long.toString(System.currentTimeMillis()); String tm = Long.toString(System.currentTimeMillis());
if (!registerAgain ) { if (!registerAgain ) {
// //callid
CallIdHeader callIdHeader = null; CallIdHeader callIdHeader = null;
if(parentPlatform.getTransport().equals("TCP")) { if(parentPlatform.getTransport().equals("TCP")) {
callIdHeader = tcpSipProvider.getNewCallId(); callIdHeader = tcpSipProvider.getNewCallId();
@ -107,10 +102,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform,
redisCatchStorage.getCSEQ(), "FromRegister" + tm, redisCatchStorage.getCSEQ(), "FromRegister" + tm,
"z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), callIdHeader); "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), callIdHeader, isRegister);
// callid 写入缓存 等注册成功可以更新状态 // callid 写入缓存 等注册成功可以更新状态
String callIdFromHeader = callIdHeader.getCallId(); String callIdFromHeader = callIdHeader.getCallId();
redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, parentPlatform.getServerGBId()); redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister));
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{ sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{
if (event != null) { if (event != null) {
@ -127,7 +122,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else { }else {
CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, "FromRegister" + tm, null, callId, www, callIdHeader); request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, "FromRegister" + tm, null, callId, www, callIdHeader, isRegister);
} }
transmitRequest(parentPlatform, request, null, okEvent); transmitRequest(parentPlatform, request, null, okEvent);
@ -145,7 +140,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
@Override @Override
public String keepalive(ParentPlatform parentPlatform) { public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
String callId = null; String callId = null;
try { try {
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
@ -168,7 +163,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
UUID.randomUUID().toString().replace("-", ""), UUID.randomUUID().toString().replace("-", ""),
null, null,
callIdHeader); callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request, errorEvent, okEvent);
callId = callIdHeader.getCallId(); callId = callIdHeader.getCallId();
} catch (ParseException | InvalidArgumentException | SipException e) { } catch (ParseException | InvalidArgumentException | SipException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -59,6 +59,9 @@ public abstract class SIPRequestProcessorParent {
public ServerTransaction getServerTransaction(RequestEvent evt) { public ServerTransaction getServerTransaction(RequestEvent evt) {
Request request = evt.getRequest(); Request request = evt.getRequest();
ServerTransaction serverTransaction = evt.getServerTransaction(); ServerTransaction serverTransaction = evt.getServerTransaction();
if (serverTransaction != null) {
System.out.println(serverTransaction.getState().toString());
}
// 判断TCP还是UDP // 判断TCP还是UDP
boolean isTcp = false; boolean isTcp = false;
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
@ -86,6 +89,8 @@ public abstract class SIPRequestProcessorParent {
logger.error(e.getMessage()); logger.error(e.getMessage());
} catch (TransactionUnavailableException e) { } catch (TransactionUnavailableException e) {
logger.error(e.getMessage()); logger.error(e.getMessage());
}finally {
} }
} }
return serverTransaction; return serverTransaction;
@ -182,6 +187,10 @@ public abstract class SIPRequestProcessorParent {
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
)); ));
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
ServerTransaction serverTransaction = getServerTransaction(evt);
if (serverTransaction == null) {
}
getServerTransaction(evt).sendResponse(response); getServerTransaction(evt).sendResponse(response);
} }

View File

@ -4,12 +4,14 @@ import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
@ -66,7 +68,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
private IMediaServerService mediaServerService; private IMediaServerService mediaServerService;
@Autowired @Autowired
private ZLMHttpHookSubscribe subscribe; private ZlmHttpHookSubscribe subscribe;
@Autowired @Autowired
private DynamicTask dynamicTask; private DynamicTask dynamicTask;

View File

@ -19,7 +19,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
@ -50,7 +50,6 @@ import org.springframework.stereotype.Component;
import javax.sdp.*; import javax.sdp.*;
import javax.sip.*; import javax.sip.*;
import javax.sip.address.SipURI;
import javax.sip.header.CallIdHeader; import javax.sip.header.CallIdHeader;
import javax.sip.message.Request; import javax.sip.message.Request;
import javax.sip.message.Response; import javax.sip.message.Response;
@ -337,7 +336,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
Long finalStartTime = startTime; Long finalStartTime = startTime;
Long finalStopTime = stopTime; Long finalStopTime = stopTime;
ZLMHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> { ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON) -> {
String app = responseJSON.getString("app"); String app = responseJSON.getString("app");
String stream = responseJSON.getString("stream"); String stream = responseJSON.getString("stream");
logger.info("[上级点播]下级已经开始推流。 回复200OK(SDP) {}/{}", app, stream); logger.info("[上级点播]下级已经开始推流。 回复200OK(SDP) {}/{}", app, stream);
@ -440,6 +439,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
streamId = String.format("%s_%s", device.getDeviceId(), channelId); streamId = String.format("%s_%s", device.getDeviceId(), channelId);
} }
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
logger.info(JSONObject.toJSONString(ssrcInfo));
sendRtpItem.setStreamId(ssrcInfo.getStream()); sendRtpItem.setStreamId(ssrcInfo.getStream());
// 写入redis 超时时回复 // 写入redis 超时时回复
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);

View File

@ -180,7 +180,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException { private void processNotifyCatalogList(RequestEvent evt, Element rootElement) throws SipException {
System.out.println(evt.getRequest().toString());
String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
String deviceId = XmlUtil.getText(rootElement, "DeviceID"); String deviceId = XmlUtil.getText(rootElement, "DeviceID");
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);

View File

@ -164,7 +164,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
} }
} }
if (channelId.equals(sipConfig.getId())) { if ("7".equals(deviceAlarm.getAlarmMethod()) ) {
// 发送给平台的报警信息 发送redis通知 // 发送给平台的报警信息 发送redis通知
AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));

View File

@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
import com.genersoft.iot.vmp.gb28181.utils.HeaderUtils;
import gov.nist.javax.sip.ResponseEventExt; import gov.nist.javax.sip.ResponseEventExt;
import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPDialog;
@ -103,15 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
} }
requestURI.setPort(event.getRemotePort()); requestURI.setPort(event.getRemotePort());
reqAck.setRequestURI(requestURI); reqAck.setRequestURI(requestURI);
List<String> agentParam = new ArrayList<>(); UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory);
agentParam.add("wvp-pro");
// TODO 添加版本信息以及日期
UserAgentHeader userAgentHeader = null;
try {
userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
} catch (ParseException e) {
throw new RuntimeException(e);
}
reqAck.addHeader(userAgentHeader); reqAck.addHeader(userAgentHeader);
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort())); Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));

View File

@ -6,8 +6,10 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -44,6 +46,9 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
@Autowired @Autowired
private SubscribeHolder subscribeHolder; private SubscribeHolder subscribeHolder;
@Autowired
private IPlatformService platformService;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
// 添加消息处理的订阅 // 添加消息处理的订阅
@ -60,48 +65,39 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
Response response = evt.getResponse(); Response response = evt.getResponse();
CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME); CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
String callId = callIdHeader.getCallId(); String callId = callIdHeader.getCallId();
PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId);
String platformGBId = redisCatchStorage.queryPlatformRegisterInfo(callId); if (platformRegisterInfo == null) {
if (platformGBId == null) { logger.info(String.format("[国标级联]未找到callId %s 的注册/注销平台id", callId ));
logger.info(String.format("未找到callId %s 的注册/注销平台id", callId ));
return; return;
} }
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId); ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformRegisterInfo.getPlatformId());
if (parentPlatformCatch == null) { if (parentPlatformCatch == null) {
logger.warn(String.format("[收到注册/注销%S请求]平台:%s但是平台缓存信息未查询到!!!", response.getStatusCode(),platformGBId)); logger.warn(String.format("[国标级联]收到注册/注销%S请求平台:%s但是平台缓存信息未查询到!!!", response.getStatusCode(),platformRegisterInfo.getPlatformId()));
return; return;
} }
String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "注销" : "注册";
logger.info(String.format("[%s %S响应]%s ", action, response.getStatusCode(), platformGBId )); String action = platformRegisterInfo.isRegister() ? "注册" : "注销";
logger.info(String.format("[国标级联]%s %S响应,%s ", action, response.getStatusCode(), platformRegisterInfo.getPlatformId() ));
ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform(); ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform();
if (parentPlatform == null) { if (parentPlatform == null) {
logger.warn(String.format("收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformGBId, action, response.getStatusCode())); logger.warn(String.format("[国标级联]收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformRegisterInfo.getPlatformId(), action, response.getStatusCode()));
return; return;
} }
if (response.getStatusCode() == 401) { if (response.getStatusCode() == Response.UNAUTHORIZED) {
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true); sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister());
}else if (response.getStatusCode() == 200){ }else if (response.getStatusCode() == Response.OK){
// 注册/注销成功
logger.info(String.format("%s %s成功", platformGBId, action)); if (platformRegisterInfo.isRegister()) {
platformService.online(parentPlatform);
}else {
platformService.offline(parentPlatform);
}
// 注册/注销成功移除缓存的信息
redisCatchStorage.delPlatformRegisterInfo(callId); redisCatchStorage.delPlatformRegisterInfo(callId);
redisCatchStorage.delPlatformCatchInfo(platformGBId);
// 取回Expires设置避免注销过程中被置为0
ParentPlatform parentPlatformTmp = storager.queryParentPlatByServerGBId(platformGBId);
if (parentPlatformTmp != null) {
parentPlatformTmp.setStatus("注册".equals(action));
redisCatchStorage.updatePlatformRegister(parentPlatformTmp);
redisCatchStorage.updatePlatformKeepalive(parentPlatformTmp);
parentPlatformCatch.setParentPlatform(parentPlatformTmp);
}
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
storager.updateParentPlatformStatus(platformGBId, "注册".equals(action));
if ("注销".equals(action)) {
subscribeHolder.removeCatalogSubscribe(platformGBId);
subscribeHolder.removeMobilePositionSubscribe(platformGBId);
}
} }
} }

View File

@ -0,0 +1,22 @@
package com.genersoft.iot.vmp.gb28181.utils;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
import javax.sip.header.UserAgentHeader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
/**
* 生成header的工具类
* @author lin
*/
public class HeaderUtils {
public static UserAgentHeader createUserAgentHeader(SipFactory sipFactory) throws PeerUnavailableException, ParseException {
List<String> agentParam = new ArrayList<>();
agentParam.add("WVP PRO");
// TODO 添加版本信息以及日期
return sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
}
}

View File

@ -50,7 +50,7 @@ public class AssistRESTfulUtils {
if (mediaServerItem == null) { if (mediaServerItem == null) {
return null; return null;
} }
if (ObjectUtils.isEmpty(mediaServerItem.getRecordAssistPort())) { if (mediaServerItem.getRecordAssistPort() > 0) {
logger.warn("未启用Assist服务"); logger.warn("未启用Assist服务");
return null; return null;
} }

View File

@ -7,12 +7,10 @@ import java.util.Map;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.media.zlm.dto.*; import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@ -20,10 +18,11 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -49,6 +48,9 @@ public class ZLMHttpHookListener {
@Autowired @Autowired
private SIPCommander cmder; private SIPCommander cmder;
@Autowired
private SIPCommanderFroPlatform commanderFroPlatform;
@Autowired @Autowired
private IPlayService playService; private IPlayService playService;
@ -77,7 +79,7 @@ public class ZLMHttpHookListener {
private ZLMMediaListManager zlmMediaListManager; private ZLMMediaListManager zlmMediaListManager;
@Autowired @Autowired
private ZLMHttpHookSubscribe subscribe; private ZlmHttpHookSubscribe subscribe;
@Autowired @Autowired
private UserSetting userSetting; private UserSetting userSetting;
@ -91,6 +93,10 @@ public class ZLMHttpHookListener {
@Autowired @Autowired
private AssistRESTfulUtils assistRESTfulUtils; private AssistRESTfulUtils assistRESTfulUtils;
@Qualifier("taskExecutor")
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
/** /**
* 服务器定时上报时间上报间隔可配置默认10s上报一次 * 服务器定时上报时间上报间隔可配置默认10s上报一次
* *
@ -101,9 +107,9 @@ public class ZLMHttpHookListener {
logger.info("[ ZLM HOOK ] on_server_keepalive API调用参数" + json.toString()); logger.info("[ ZLM HOOK ] on_server_keepalive API调用参数" + json.toString());
String mediaServerId = json.getString("mediaServerId"); String mediaServerId = json.getString("mediaServerId");
List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
if (subscribes != null && subscribes.size() > 0) { if (subscribes != null && subscribes.size() > 0) {
for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
subscribe.response(null, json); subscribe.response(null, json);
} }
} }
@ -167,7 +173,7 @@ public class ZLMHttpHookListener {
logger.debug("[ ZLM HOOK ]on_play API调用参数" + JSON.toJSONString(param)); logger.debug("[ ZLM HOOK ]on_play API调用参数" + JSON.toJSONString(param));
} }
String mediaServerId = param.getMediaServerId(); String mediaServerId = param.getMediaServerId();
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json); ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json);
if (subscribe != null ) { if (subscribe != null ) {
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (mediaInfo != null) { if (mediaInfo != null) {
@ -237,9 +243,11 @@ public class ZLMHttpHookListener {
// 鉴权通过 // 鉴权通过
redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
// 通知assist新的callId // 通知assist新的callId
if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) { taskExecutor.execute(()->{
assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null); if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {
} assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
}
});
}else { }else {
zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId()); zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId());
} }
@ -252,7 +260,7 @@ public class ZLMHttpHookListener {
} }
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
if (subscribe != null) { if (subscribe != null) {
if (mediaInfo != null) { if (mediaInfo != null) {
subscribe.response(mediaInfo, json); subscribe.response(mediaInfo, json);
@ -376,7 +384,7 @@ public class ZLMHttpHookListener {
logger.debug("[ ZLM HOOK ]on_shell_login API调用参数" + json.toString()); logger.debug("[ ZLM HOOK ]on_shell_login API调用参数" + json.toString());
} }
String mediaServerId = json.getString("mediaServerId"); String mediaServerId = json.getString("mediaServerId");
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_shell_login, json); ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_shell_login, json);
if (subscribe != null ) { if (subscribe != null ) {
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (mediaInfo != null) { if (mediaInfo != null) {
@ -402,7 +410,7 @@ public class ZLMHttpHookListener {
logger.info("[ ZLM HOOK ]on_stream_changed API调用参数" + JSONObject.toJSONString(item)); logger.info("[ ZLM HOOK ]on_stream_changed API调用参数" + JSONObject.toJSONString(item));
String mediaServerId = item.getMediaServerId(); String mediaServerId = item.getMediaServerId();
JSONObject json = (JSONObject) JSON.toJSON(item); JSONObject json = (JSONObject) JSON.toJSON(item);
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json);
if (subscribe != null ) { if (subscribe != null ) {
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (mediaInfo != null) { if (mediaInfo != null) {
@ -415,19 +423,24 @@ public class ZLMHttpHookListener {
String schema = item.getSchema(); String schema = item.getSchema();
List<MediaItem.MediaTrack> tracks = item.getTracks(); List<MediaItem.MediaTrack> tracks = item.getTracks();
boolean regist = item.isRegist(); boolean regist = item.isRegist();
if (regist) { if (item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); || item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
if (streamAuthorityInfo == null) { || item.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item); if (regist) {
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
if (streamAuthorityInfo == null) {
streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item);
}else {
streamAuthorityInfo.setOriginType(item.getOriginType());
streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr());
}
redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo);
}else { }else {
streamAuthorityInfo.setOriginType(item.getOriginType()); redisCatchStorage.removeStreamAuthorityInfo(app, stream);
streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr());
} }
redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo);
}else {
redisCatchStorage.removeStreamAuthorityInfo(app, stream);
} }
if ("rtmp".equals(schema)){
if ("rtsp".equals(schema)){
logger.info("on_stream_changed注册->{}, app->{}, stream->{}", regist, app, stream); logger.info("on_stream_changed注册->{}, app->{}, stream->{}", regist, app, stream);
if (regist) { if (regist) {
mediaServerService.addCount(mediaServerId); mediaServerService.addCount(mediaServerId);
@ -523,17 +536,21 @@ public class ZLMHttpHookListener {
if ("rtp".equals(app)){ if ("rtp".equals(app)){
ret.put("close", true); ret.put("close", true);
StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(streamId); StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(streamId);
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, null, streamId);
if (streamInfoForPlayCatch != null) { if (streamInfoForPlayCatch != null) {
// 如果在给上级推流也不停止 // 收到无人观看说明流也没有在往上级推送
if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) { if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
ret.put("close", false); List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(streamInfoForPlayCatch.getChannelId());
} else { if (sendRtpItems.size() > 0) {
cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(), for (SendRtpItem sendRtpItem : sendRtpItems) {
streamInfoForPlayCatch.getStream(), null); ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
redisCatchStorage.stopPlay(streamInfoForPlayCatch); commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); }
}
} }
cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
streamInfoForPlayCatch.getStream(), null);
redisCatchStorage.stopPlay(streamInfoForPlayCatch);
storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
}else{ }else{
StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null); StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
if (streamInfoForPlayBackCatch != null) { if (streamInfoForPlayBackCatch != null) {
@ -615,9 +632,9 @@ public class ZLMHttpHookListener {
} }
String remoteAddr = request.getRemoteAddr(); String remoteAddr = request.getRemoteAddr();
jsonObject.put("ip", remoteAddr); jsonObject.put("ip", remoteAddr);
List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started); List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started);
if (subscribes != null && subscribes.size() > 0) { if (subscribes != null && subscribes.size() > 0) {
for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
subscribe.response(null, jsonObject); subscribe.response(null, jsonObject);
} }
} }

View File

@ -1,30 +1,24 @@
package com.genersoft.iot.vmp.media.zlm; package com.genersoft.iot.vmp.media.zlm;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.media.zlm.dto.*; import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper; import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
import com.genersoft.iot.vmp.storager.dao.StreamPushMapper; import com.genersoft.iot.vmp.storager.dao.StreamPushMapper;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import org.checkerframework.checker.units.qual.C;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* @author lin * @author lin
@ -59,7 +53,7 @@ public class ZLMMediaListManager {
private StreamPushMapper streamPushMapper; private StreamPushMapper streamPushMapper;
@Autowired @Autowired
private ZLMHttpHookSubscribe subscribe; private ZlmHttpHookSubscribe subscribe;
@Autowired @Autowired
private UserSetting userSetting; private UserSetting userSetting;

View File

@ -92,6 +92,7 @@ public class ZLMRTPServerFactory {
int result = -1; int result = -1;
// 查询此rtp server 是否已经存在 // 查询此rtp server 是否已经存在
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
logger.info(JSONObject.toJSONString(rtpInfo));
if(rtpInfo.getInteger("code") == 0){ if(rtpInfo.getInteger("code") == 0){
if (rtpInfo.getBoolean("exist")) { if (rtpInfo.getBoolean("exist")) {
result = rtpInfo.getInteger("local_port"); result = rtpInfo.getInteger("local_port");
@ -113,7 +114,7 @@ public class ZLMRTPServerFactory {
} }
param.put("ssrc", ssrc); param.put("ssrc", ssrc);
JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
logger.info(JSONObject.toJSONString(openRtpServerResultJson));
if (openRtpServerResultJson != null) { if (openRtpServerResultJson != null) {
if (openRtpServerResultJson.getInteger("code") == 0) { if (openRtpServerResultJson.getInteger("code") == 0) {
result= openRtpServerResultJson.getInteger("port"); result= openRtpServerResultJson.getInteger("port");
@ -277,7 +278,7 @@ public class ZLMRTPServerFactory {
* 查询待转推的流是否就绪 * 查询待转推的流是否就绪
*/ */
public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) {
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtmp", streamId); JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtsp", streamId);
return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
} }
@ -297,7 +298,7 @@ public class ZLMRTPServerFactory {
* @return * @return
*/ */
public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) {
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId);
if (mediaInfo == null) { if (mediaInfo == null) {
return 0; return 0;
} }

View File

@ -8,7 +8,6 @@ import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForServerStarted; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForServerStarted;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -19,9 +18,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
@Component @Component
@Order(value=1) @Order(value=1)
@ -35,7 +32,7 @@ public class ZLMRunner implements CommandLineRunner {
private ZLMRESTfulUtils zlmresTfulUtils; private ZLMRESTfulUtils zlmresTfulUtils;
@Autowired @Autowired
private ZLMHttpHookSubscribe hookSubscribe; private ZlmHttpHookSubscribe hookSubscribe;
@Autowired @Autowired
private EventPublisher publisher; private EventPublisher publisher;
@ -62,8 +59,6 @@ public class ZLMRunner implements CommandLineRunner {
} }
mediaServerService.syncCatchFromDatabase(); mediaServerService.syncCatchFromDatabase();
HookSubscribeForServerStarted hookSubscribeForServerStarted = HookSubscribeFactory.on_server_started(); HookSubscribeForServerStarted hookSubscribeForServerStarted = HookSubscribeFactory.on_server_started();
// Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.SECONDS.toSeconds(60));
// hookSubscribeForStreamChange.setExpires(expiresInstant);
// 订阅 zlm启动事件, 新的zlm也会从这里进入系统 // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
hookSubscribe.addSubscribe(hookSubscribeForServerStarted, hookSubscribe.addSubscribe(hookSubscribeForServerStarted,
(MediaServerItem mediaServerItem, JSONObject response)->{ (MediaServerItem mediaServerItem, JSONObject response)->{

View File

@ -4,6 +4,9 @@ import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.HookType; import com.genersoft.iot.vmp.media.zlm.dto.HookType;
import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -13,21 +16,22 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* @description:针对 ZLMediaServer的hook事件订阅 * ZLMediaServer的hook事件订阅
* @author: pan * @author lin
* @date: 2020年12月2日 21:17:32
*/ */
@Component @Component
public class ZLMHttpHookSubscribe { public class ZlmHttpHookSubscribe {
private final static Logger logger = LoggerFactory.getLogger(ZlmHttpHookSubscribe.class);
@FunctionalInterface @FunctionalInterface
public interface Event{ public interface Event{
void response(MediaServerItem mediaServerItem, JSONObject response); void response(MediaServerItem mediaServerItem, JSONObject response);
} }
private Map<HookType, Map<IHookSubscribe, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>(); private Map<HookType, Map<IHookSubscribe, ZlmHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
public void addSubscribe(IHookSubscribe hookSubscribe, ZLMHttpHookSubscribe.Event event) { public void addSubscribe(IHookSubscribe hookSubscribe, ZlmHttpHookSubscribe.Event event) {
if (hookSubscribe.getExpires() == null) { if (hookSubscribe.getExpires() == null) {
// 默认5分钟过期 // 默认5分钟过期
Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(5)); Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(5));
@ -36,8 +40,8 @@ public class ZLMHttpHookSubscribe {
allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event); allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event);
} }
public ZLMHttpHookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) { public ZlmHttpHookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) {
ZLMHttpHookSubscribe.Event event= null; ZlmHttpHookSubscribe.Event event= null;
Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type); Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
if (eventMap == null) { if (eventMap == null) {
return null; return null;
@ -69,8 +73,8 @@ public class ZLMHttpHookSubscribe {
Set<Map.Entry<IHookSubscribe, Event>> entries = eventMap.entrySet(); Set<Map.Entry<IHookSubscribe, Event>> entries = eventMap.entrySet();
if (entries.size() > 0) { if (entries.size() > 0) {
List<Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>(); List<Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>();
for (Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event> entry : entries) { for (Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event> entry : entries) {
JSONObject content = entry.getKey().getContent(); JSONObject content = entry.getKey().getContent();
if (content == null || content.size() == 0) { if (content == null || content.size() == 0) {
entriesToRemove.add(entry); entriesToRemove.add(entry);
@ -87,13 +91,13 @@ public class ZLMHttpHookSubscribe {
result = result && content.getString(s).equals(hookSubscribe.getContent().getString(s)); result = result && content.getString(s).equals(hookSubscribe.getContent().getString(s));
} }
} }
if (null != result && result){ if (result){
entriesToRemove.add(entry); entriesToRemove.add(entry);
} }
} }
if (!CollectionUtils.isEmpty(entriesToRemove)) { if (!CollectionUtils.isEmpty(entriesToRemove)) {
for (Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event> entry : entriesToRemove) { for (Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event> entry : entriesToRemove) {
entries.remove(entry); entries.remove(entry);
} }
} }
@ -106,12 +110,12 @@ public class ZLMHttpHookSubscribe {
* @param type * @param type
* @return * @return
*/ */
public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) { public List<ZlmHttpHookSubscribe.Event> getSubscribes(HookType type) {
Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type); Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
if (eventMap == null) { if (eventMap == null) {
return null; return null;
} }
List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>(); List<ZlmHttpHookSubscribe.Event> result = new ArrayList<>();
for (IHookSubscribe key : eventMap.keySet()) { for (IHookSubscribe key : eventMap.keySet()) {
result.add(eventMap.get(key)); result.add(eventMap.get(key));
} }
@ -127,5 +131,28 @@ public class ZLMHttpHookSubscribe {
return result; return result;
} }
/**
* 对订阅数据进行过期清理
*/
@Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
public void execute(){
logger.info("[hook订阅] 清理");
Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
int total = 0;
for (HookType hookType : allSubscribes.keySet()) {
Map<IHookSubscribe, Event> hookSubscribeEventMap = allSubscribes.get(hookType);
if (hookSubscribeEventMap.size() > 0) {
for (IHookSubscribe hookSubscribe : hookSubscribeEventMap.keySet()) {
if (hookSubscribe.getExpires().isBefore(instant)) {
// 过期的
hookSubscribeEventMap.remove(hookSubscribe);
total ++;
}
}
}
}
logger.info("[hook订阅] 清理结束,共清理{}条过期数据", total);
}
} }

View File

@ -1,72 +0,0 @@
package com.genersoft.iot.vmp.media.zlm.event;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* @description:设备心跳超时监听,借助redis过期特性进行监听监听到说明设备心跳超时发送离线事件
* @author: swwheihei
* @date: 2020年5月6日 上午11:35:46
*/
@Component
public class ZLMKeepliveTimeoutListener extends RedisKeyExpirationEventMessageListener {
private Logger logger = LoggerFactory.getLogger(ZLMKeepliveTimeoutListener.class);
@Autowired
private EventPublisher publisher;
@Autowired
private ZLMRESTfulUtils zlmresTfulUtils;
@Autowired
private UserSetting userSetting;
@Autowired
private IMediaServerService mediaServerService;
public ZLMKeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {
super(listenerContainer, userSetting);
}
/**
* 监听失效的keykey格式为keeplive_deviceId
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 获取失效的key
String expiredKey = message.toString();
String KEEPLIVEKEY_PREFIX = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_";
if(!expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){
return;
}
String mediaServerId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length());
logger.info("[zlm心跳到期]" + mediaServerId);
// 发起http请求验证zlm是否确实无法连接如果确实无法连接则发送离线事件否则不作处理
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
JSONObject mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
if (mediaServerConfig != null && mediaServerConfig.getInteger("code") == 0) {
logger.info("[zlm心跳到期]{}验证后zlm仍在线恢复心跳信息", mediaServerId);
// 添加zlm信息
mediaServerService.updateMediaServerKeepalive(mediaServerId, mediaServerConfig);
}else {
publisher.zlmOfflineEventPublish(mediaServerId);
}
}
}

View File

@ -0,0 +1,45 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.github.pagehelper.PageInfo;
/**
* 国标平台的业务类
* @author lin
*/
public interface IPlatformService {
ParentPlatform queryPlatformByServerGBId(String platformGbId);
/**
* 分页获取上级平台
* @param page
* @param count
* @return
*/
PageInfo<ParentPlatform> queryParentPlatformList(int page, int count);
/**
* 添加级联平台
* @param parentPlatform 级联平台
*/
boolean add(ParentPlatform parentPlatform);
/**
* 平台上线
* @param parentPlatform 平台信息
*/
void online(ParentPlatform parentPlatform);
/**
* 平台离线
* @param parentPlatform 平台信息
*/
void offline(ParentPlatform parentPlatform);
/**
* 向上级平台发起注册
* @param parentPlatform
*/
void login(ParentPlatform parentPlatform);
}

View File

@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback; import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo; import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
import com.genersoft.iot.vmp.service.bean.PlayBackCallback; import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
/** /**
@ -25,9 +24,9 @@ public interface IPlayService {
void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
InviteTimeOutCallback timeoutCallback, String uuid); InviteTimeOutCallback timeoutCallback, String uuid);
PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent, Runnable timeoutCallback); PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent, Runnable timeoutCallback);
MediaServerItem getNewMediaServerItem(Device device); MediaServerItem getNewMediaServerItem(Device device);

View File

@ -11,6 +11,7 @@ import java.util.Set;
import com.genersoft.iot.vmp.media.zlm.ZLMRunner; import com.genersoft.iot.vmp.media.zlm.ZLMRunner;
import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -22,7 +23,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.TransactionStatus;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
@ -42,7 +42,6 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
@ -58,6 +57,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
private final String zlmKeepaliveKeyPrefix = "zlm-keepalive_";
@Autowired @Autowired
private SipConfig sipConfig; private SipConfig sipConfig;
@ -88,10 +89,12 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Autowired @Autowired
private ZLMRTPServerFactory zlmrtpServerFactory; private ZLMRTPServerFactory zlmrtpServerFactory;
@Autowired @Autowired
private EventPublisher publisher; private EventPublisher publisher;
@Autowired
private DynamicTask dynamicTask;
/** /**
* 初始化 * 初始化
*/ */
@ -135,7 +138,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId()); logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
return null; return null;
}else { }else {
String ssrc = null; String ssrc;
if (presetSsrc != null) { if (presetSsrc != null) {
ssrc = presetSsrc; ssrc = presetSsrc;
}else { }else {
@ -404,15 +407,43 @@ public class MediaServerServiceImpl implements IMediaServerService {
if (serverItem.isAutoConfig()) { if (serverItem.isAutoConfig()) {
setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
} }
final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId();
dynamicTask.stop(zlmKeepaliveKey);
dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (serverItem.getHookAliveInterval() + 5) * 1000);
publisher.zlmOnlineEventPublish(serverItem.getId()); publisher.zlmOnlineEventPublish(serverItem.getId());
logger.info("[ZLM] 连接成功 {} - {}:{} ", logger.info("[ZLM] 连接成功 {} - {}:{} ",
zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
} }
class KeepAliveTimeoutRunnable implements Runnable{
private MediaServerItem serverItem;
public KeepAliveTimeoutRunnable(MediaServerItem serverItem) {
this.serverItem = serverItem;
}
@Override
public void run() {
logger.info("[zlm心跳到期]" + serverItem.getId());
// 发起http请求验证zlm是否确实无法连接如果确实无法连接则发送离线事件否则不作处理
JSONObject mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(serverItem);
if (mediaServerConfig != null && mediaServerConfig.getInteger("code") == 0) {
logger.info("[zlm心跳到期]{}验证后zlm仍在线恢复心跳信息,请检查zlm是否可以正常向wvp发送心跳", serverItem.getId());
// 添加zlm信息
updateMediaServerKeepalive(serverItem.getId(), mediaServerConfig);
}else {
publisher.zlmOfflineEventPublish(serverItem.getId());
}
}
}
@Override @Override
public void zlmServerOffline(String mediaServerId) { public void zlmServerOffline(String mediaServerId) {
delete(mediaServerId); delete(mediaServerId);
final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerId;
dynamicTask.stop(zlmKeepaliveKey);
} }
@Override @Override
@ -423,7 +454,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
if (RedisUtil.zScore(key, serverItem.getId()) == null) { // 不存在则设置默认值 已存在则重置 if (RedisUtil.zScore(key, serverItem.getId()) == null) { // 不存在则设置默认值 已存在则重置
RedisUtil.zAdd(key, serverItem.getId(), 0L); RedisUtil.zAdd(key, serverItem.getId(), 0L);
// 查询服务流数量 // 查询服务流数量
zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{ zlmresTfulUtils.getMediaList(serverItem, null, null, "rtsp",(mediaList ->{
Integer code = mediaList.getInteger("code"); Integer code = mediaList.getInteger("code");
if (code == 0) { if (code == 0) {
JSONArray data = mediaList.getJSONArray("data"); JSONArray data = mediaList.getJSONArray("data");
@ -435,7 +466,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
}else { }else {
clearRTPServer(serverItem); clearRTPServer(serverItem);
} }
} }
@ -471,7 +501,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
} }
// 获取分数最低的及并发最低的 // 获取分数最低的及并发最低的
Set<Object> objects = RedisUtil.ZRange(key, 0, -1); Set<Object> objects = RedisUtil.zRange(key, 0, -1);
ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects); ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects);
String mediaServerId = (String)mediaServerObjectS.get(0); String mediaServerId = (String)mediaServerObjectS.get(0);
@ -489,10 +519,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
String protocol = sslEnabled ? "https" : "http"; String protocol = sslEnabled ? "https" : "http";
String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
String recordHookPrex = null;
if (mediaServerItem.getRecordAssistPort() != 0) {
recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaServerItem.getRecordAssistPort());
}
Map<String, Object> param = new HashMap<>(); Map<String, Object> param = new HashMap<>();
param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"); param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s");
@ -501,7 +528,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
param.put("hook.on_play",String.format("%s/on_play", hookPrex)); param.put("hook.on_play",String.format("%s/on_play", hookPrex));
param.put("hook.on_http_access",String.format("%s/on_http_access", hookPrex)); param.put("hook.on_http_access",String.format("%s/on_http_access", hookPrex));
param.put("hook.on_publish", String.format("%s/on_publish", hookPrex)); param.put("hook.on_publish", String.format("%s/on_publish", hookPrex));
param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): "");
param.put("hook.on_record_ts",String.format("%s/on_record_ts", hookPrex)); param.put("hook.on_record_ts",String.format("%s/on_record_ts", hookPrex));
param.put("hook.on_rtsp_auth",String.format("%s/on_rtsp_auth", hookPrex)); param.put("hook.on_rtsp_auth",String.format("%s/on_rtsp_auth", hookPrex));
param.put("hook.on_rtsp_realm",String.format("%s/on_rtsp_realm", hookPrex)); param.put("hook.on_rtsp_realm",String.format("%s/on_rtsp_realm", hookPrex));
@ -511,6 +537,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex)); param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex)); param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex)); param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));
if (mediaServerItem.getRecordAssistPort() > 0) {
param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort()));
}else {
param.put("hook.on_record_mp4","");
}
param.put("hook.timeoutSec","20"); param.put("hook.timeoutSec","20");
param.put("general.streamNoneReaderDelayMS",mediaServerItem.getStreamNoneReaderDelayMS()==-1?"3600000":mediaServerItem.getStreamNoneReaderDelayMS() ); param.put("general.streamNoneReaderDelayMS",mediaServerItem.getStreamNoneReaderDelayMS()==-1?"3600000":mediaServerItem.getStreamNoneReaderDelayMS() );
// 推流断开后可以在超时时间内重新连接上继续推流这样播放器会接着播放 // 推流断开后可以在超时时间内重新连接上继续推流这样播放器会接着播放
@ -631,9 +662,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
return; return;
} }
} }
String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId; final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId();
int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2; dynamicTask.stop(zlmKeepaliveKey);
RedisUtil.set(key, data, hookAliveInterval); dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(mediaServerItem), (mediaServerItem.getHookAliveInterval() + 5) * 1000);
} }
private MediaServerItem getOneFromDatabase(String mediaServerId) { private MediaServerItem getOneFromDatabase(String mediaServerId) {

View File

@ -108,6 +108,7 @@ public class MediaServiceImpl implements IMediaService {
streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam)); streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam)); streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam)); streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app, stream, callIdParam));
streamInfoResult.setRtc(String.format("http://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play%s", mediaInfo.getStreamIp(), mediaInfo.getHttpPort(), app, stream, ObjectUtils.isEmpty(callId)?"":"&callId=" + callId));
if (mediaInfo.getHttpSSlPort() != 0) { if (mediaInfo.getHttpSSlPort() != 0) {
streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam)); streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam)); streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
@ -118,7 +119,7 @@ public class MediaServiceImpl implements IMediaService {
streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam)); streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam)); streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam)); streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app, stream, callIdParam));
streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=%s%s", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app, stream, isPlay?"play":"push", ObjectUtils.isEmpty(callId)?"":"&callId=" + callId)); streamInfoResult.setRtcs(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play%s", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app, stream, ObjectUtils.isEmpty(callId)?"":"&callId=" + callId));
} }
streamInfoResult.setTracks(tracks); streamInfoResult.setTracks(tracks);

View File

@ -0,0 +1,232 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.sip.TimeoutEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author lin
*/
@Service
public class PlatformServiceImpl implements IPlatformService {
private final static String REGISTER_KEY_PREFIX = "platform_register_";
private final static String KEEPALIVE_KEY_PREFIX = "platform_keepalive_";
private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
@Autowired
private ParentPlatformMapper platformMapper;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IMediaServerService mediaServerService;
@Autowired
private SIPCommanderFroPlatform commanderForPlatform;
@Autowired
private DynamicTask dynamicTask;
@Autowired
private ZLMRTPServerFactory zlmrtpServerFactory;
@Autowired
private SubscribeHolder subscribeHolder;
@Override
public ParentPlatform queryPlatformByServerGBId(String platformGbId) {
return platformMapper.getParentPlatByServerGBId(platformGbId);
}
@Override
public PageInfo<ParentPlatform> queryParentPlatformList(int page, int count) {
PageHelper.startPage(page, count);
List<ParentPlatform> all = platformMapper.getParentPlatformList();
return new PageInfo<>(all);
}
@Override
public boolean add(ParentPlatform parentPlatform) {
if (parentPlatform.getCatalogGroup() == 0) {
// 每次发送目录的数量默认为1
parentPlatform.setCatalogGroup(1);
}
if (parentPlatform.getAdministrativeDivision() == null) {
// 行政区划默认去编号的前6位
parentPlatform.setAdministrativeDivision(parentPlatform.getServerGBId().substring(0,6));
}
parentPlatform.setCatalogId(parentPlatform.getDeviceGBId());
int result = platformMapper.addParentPlatform(parentPlatform);
// 添加缓存
ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch();
parentPlatformCatch.setParentPlatform(parentPlatform);
parentPlatformCatch.setId(parentPlatform.getServerGBId());
parentPlatformCatch.setParentPlatform(parentPlatform);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
if (parentPlatform.isEnable()) {
// 保存时启用就发送注册
// 注册成功时由程序直接调用了online方法
commanderForPlatform.register(parentPlatform, eventResult -> {
logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
}, null);
}
return result > 0;
}
@Override
public void online(ParentPlatform parentPlatform) {
logger.info("[国标级联]{}, 平台上线/更新注册", parentPlatform.getServerGBId());
platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true);
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
if (parentPlatformCatch != null) {
parentPlatformCatch.getParentPlatform().setStatus(true);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
}else {
parentPlatformCatch = new ParentPlatformCatch();
parentPlatformCatch.setParentPlatform(parentPlatform);
parentPlatformCatch.setId(parentPlatform.getServerGBId());
parentPlatform.setStatus(true);
parentPlatformCatch.setParentPlatform(parentPlatform);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
}
final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
if (dynamicTask.contains(registerTaskKey)) {
dynamicTask.stop(registerTaskKey);
}
// 添加注册任务
dynamicTask.startDelay(registerTaskKey,
// 注册失败注册成功时由程序直接调用了online方法
()->commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null),
parentPlatform.getExpires()*1000);
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
if (!dynamicTask.contains(keepaliveTaskKey)) {
// 添加心跳任务
dynamicTask.startCron(keepaliveTaskKey,
()-> commanderForPlatform.keepalive(parentPlatform, eventResult -> {
// 心跳失败
if (eventResult.type == SipSubscribe.EventResultType.timeout) {
// 心跳超时
ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
// 此时是第三次心跳超时 平台离线
if (platformCatch.getKeepAliveReply() == 2) {
// 设置平台离线并重新注册
offline(parentPlatform);
logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId());
commanderForPlatform.register(parentPlatform, eventResult1 -> {
logger.info("[国标级联] {}三次心跳超时后再次发起注册仍然失败开始定时发起注册间隔为1分钟", parentPlatform.getServerGBId());
// 添加注册任务
dynamicTask.startCron(registerTaskKey,
// 注册失败注册成功时由程序直接调用了online方法
()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
60*1000);
}, null);
}
}else {
logger.warn("[国标级联]发送心跳收到错误code {}, msg: {}", eventResult.statusCode, eventResult.msg);
}
}, eventResult -> {
// 心跳成功
// 清空之前的心跳超时计数
ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
if (platformCatch.getKeepAliveReply() > 0) {
platformCatch.setKeepAliveReply(0);
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
}
}),
parentPlatform.getExpires()*1000);
}
}
@Override
public void offline(ParentPlatform parentPlatform) {
logger.info("[平台离线]{}", parentPlatform.getServerGBId());
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
parentPlatformCatch.setKeepAliveReply(0);
parentPlatformCatch.setRegisterAliveReply(0);
ParentPlatform parentPlatformInCatch = parentPlatformCatch.getParentPlatform();
parentPlatformInCatch.setStatus(false);
parentPlatformCatch.setParentPlatform(parentPlatformInCatch);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), false);
// 停止所有推流
logger.info("[平台离线] {}, 停止所有推流", parentPlatform.getServerGBId());
stopAllPush(parentPlatform.getServerGBId());
// 清除注册定时
logger.info("[平台离线] {}, 停止定时注册任务", parentPlatform.getServerGBId());
final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
if (dynamicTask.contains(registerTaskKey)) {
dynamicTask.stop(registerTaskKey);
}
// 清除心跳定时
logger.info("[平台离线] {}, 停止定时发送心跳任务", parentPlatform.getServerGBId());
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
if (dynamicTask.contains(keepaliveTaskKey)) {
// 添加心跳任务
dynamicTask.stop(keepaliveTaskKey);
}
// 停止目录订阅回复
logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId());
subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
}
private void stopAllPush(String platformId) {
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(platformId);
if (sendRtpItems != null && sendRtpItems.size() > 0) {
for (SendRtpItem sendRtpItem : sendRtpItems) {
redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null);
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
Map<String, Object> param = new HashMap<>(3);
param.put("vhost", "__defaultVhost__");
param.put("app", sendRtpItem.getApp());
param.put("stream", sendRtpItem.getStreamId());
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
}
}
}
@Override
public void login(ParentPlatform parentPlatform) {
final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
commanderForPlatform.register(parentPlatform, eventResult1 -> {
logger.info("[国标级联] {}开始定时发起注册间隔为1分钟", parentPlatform.getServerGBId());
// 添加注册任务
dynamicTask.startCron(registerTaskKey,
// 注册失败注册成功时由程序直接调用了online方法
()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
60*1000);
}, null);
}
}

View File

@ -37,7 +37,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
@ -128,7 +128,7 @@ public class PlayServiceImpl implements IPlayService {
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
@Autowired @Autowired
private ZLMHttpHookSubscribe subscribe; private ZlmHttpHookSubscribe subscribe;
@Qualifier("taskExecutor") @Qualifier("taskExecutor")
@ -139,7 +139,7 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId,
ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
Runnable timeoutCallback) { Runnable timeoutCallback) {
if (mediaServerItem == null) { if (mediaServerItem == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
@ -222,6 +222,7 @@ public class PlayServiceImpl implements IPlayService {
streamId = String.format("%s_%s", device.getDeviceId(), channelId); streamId = String.format("%s_%s", device.getDeviceId(), channelId);
} }
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false);
logger.info(JSONObject.toJSONString(ssrcInfo));
play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{ play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{
if (hookEvent != null) { if (hookEvent != null) {
hookEvent.response(mediaServerItem, response); hookEvent.response(mediaServerItem, response);
@ -257,8 +258,8 @@ public class PlayServiceImpl implements IPlayService {
@Override @Override
public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
InviteTimeOutCallback timeoutCallback, String uuid) { InviteTimeOutCallback timeoutCallback, String uuid) {
String streamId = null; String streamId = null;
if (mediaServerItem.isRtpEnable()) { if (mediaServerItem.isRtpEnable()) {
@ -333,7 +334,7 @@ public class PlayServiceImpl implements IPlayService {
// 单端口模式streamId也有变化需要重新设置监听 // 单端口模式streamId也有变化需要重新设置监听
if (!mediaServerItem.isRtpEnable()) { if (!mediaServerItem.isRtpEnable()) {
// 添加订阅 // 添加订阅
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId()); HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
subscribe.removeSubscribe(hookSubscribe); subscribe.removeSubscribe(hookSubscribe);
hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{ subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
@ -609,7 +610,7 @@ public class PlayServiceImpl implements IPlayService {
logger.warn("查询录像信息时发现节点已离线"); logger.warn("查询录像信息时发现节点已离线");
return null; return null;
} }
if (mediaServerItem.getRecordAssistPort() != 0) { if (mediaServerItem.getRecordAssistPort() > 0) {
JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null);
if (jsonObject != null && jsonObject.getInteger("code") == 0) { if (jsonObject != null && jsonObject.getInteger("code") == 0) {
long duration = jsonObject.getLong("data"); long duration = jsonObject.getLong("data");
@ -802,7 +803,7 @@ public class PlayServiceImpl implements IPlayService {
// for (SendRtpItem sendRtpItem : sendRtpItems) { // for (SendRtpItem sendRtpItem : sendRtpItems) {
// if (sendRtpItem.getMediaServerId().equals(mediaServerId)) { // if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
// if (mediaListMap.get(sendRtpItem.getStreamId()) == null) { // if (mediaListMap.get(sendRtpItem.getStreamId()) == null) {
// ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); // ParentPlatform platform = storager.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
// sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId()); // sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
// } // }
// } // }

View File

@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -12,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import java.util.List;
@Component @Component
@ -37,8 +42,6 @@ public class RedisAlarmMsgListener implements MessageListener {
return; return;
} }
String gbId = alarmChannelMessage.getGbId(); String gbId = alarmChannelMessage.getGbId();
Device device = storage.queryVideoDevice(gbId);
ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
DeviceAlarm deviceAlarm = new DeviceAlarm(); DeviceAlarm deviceAlarm = new DeviceAlarm();
deviceAlarm.setCreateTime(DateUtil.getNow()); deviceAlarm.setCreateTime(DateUtil.getNow());
@ -46,18 +49,29 @@ public class RedisAlarmMsgListener implements MessageListener {
deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
deviceAlarm.setAlarmPriority("1"); deviceAlarm.setAlarmPriority("1");
deviceAlarm.setAlarmTime(DateUtil.getNow()); deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601());
deviceAlarm.setAlarmType("1"); deviceAlarm.setAlarmType("1");
deviceAlarm.setLongitude(0); deviceAlarm.setLongitude(0);
deviceAlarm.setLatitude(0); deviceAlarm.setLatitude(0);
if (ObjectUtils.isEmpty(gbId)) {
if (device != null && platform == null) { // 发送给所有的上级
commander.sendAlarmMessage(device, deviceAlarm); List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
}else if (device == null && platform != null){ if (parentPlatforms.size() > 0) {
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); for (ParentPlatform parentPlatform : parentPlatforms) {
commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
}
}
}else { }else {
logger.warn("无法确定" + gbId + "是平台还是设备"); Device device = storage.queryVideoDevice(gbId);
ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
if (device != null && platform == null) {
commander.sendAlarmMessage(device, deviceAlarm);
}else if (device == null && platform != null){
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
}else {
logger.warn("无法确定" + gbId + "是平台还是设备");
}
} }
} }
} }

View File

@ -5,12 +5,11 @@ import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.*; import com.genersoft.iot.vmp.service.bean.*;
@ -24,9 +23,6 @@ import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -86,7 +82,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
private ZLMMediaListManager mediaListManager; private ZLMMediaListManager mediaListManager;
@Autowired @Autowired
private ZLMHttpHookSubscribe subscribe; private ZlmHttpHookSubscribe subscribe;
public interface PlayMsgCallback{ public interface PlayMsgCallback{
@ -271,7 +267,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
}, userSetting.getPlatformPlayTimeout()); }, userSetting.getPlatformPlayTimeout());
// 添加订阅 // 添加订阅
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(content.getApp(), content.getStream(), true, "rtmp", mediaServerItem.getId()); HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(content.getApp(), content.getStream(), true, "rtsp", mediaServerItem.getId());
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{ subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);

View File

@ -295,7 +295,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if (jsonObject == null) { if (jsonObject == null) {
return false; return false;
} }
System.out.println(jsonObject);
if (jsonObject.getInteger("code") == 0) { if (jsonObject.getInteger("code") == 0) {
result = true; result = true;
streamProxy.setEnable(true); streamProxy.setEnable(true);
@ -421,7 +420,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if(data != null && data.size() > 0) { if(data != null && data.size() > 0) {
for (int i = 0; i < data.size(); i++) { for (int i = 0; i < data.size(); i++) {
JSONObject streamJSONObj = data.getJSONObject(i); JSONObject streamJSONObj = data.getJSONObject(i);
if ("rtmp".equals(streamJSONObj.getString("schema"))) { if ("rtsp".equals(streamJSONObj.getString("schema"))) {
StreamInfo streamInfo = new StreamInfo(); StreamInfo streamInfo = new StreamInfo();
String app = streamJSONObj.getString("app"); String app = streamJSONObj.getString("app");
String stream = streamJSONObj.getString("stream"); String stream = streamJSONObj.getString("stream");

View File

@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -61,17 +62,13 @@ public interface IRedisCatchStorage {
void delPlatformCatchInfo(String platformGbId); void delPlatformCatchInfo(String platformGbId);
void updatePlatformKeepalive(ParentPlatform parentPlatform);
void delPlatformKeepalive(String platformGbId); void delPlatformKeepalive(String platformGbId);
void updatePlatformRegister(ParentPlatform parentPlatform);
void delPlatformRegister(String platformGbId); void delPlatformRegister(String platformGbId);
void updatePlatformRegisterInfo(String callId, String platformGbId); void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo);
String queryPlatformRegisterInfo(String callId); PlatformRegisterInfo queryPlatformRegisterInfo(String callId);
void delPlatformRegisterInfo(String callId); void delPlatformRegisterInfo(String callId);
@ -237,4 +234,6 @@ public interface IRedisCatchStorage {
* 发送redis消息 查询所有推流设备的状态 * 发送redis消息 查询所有推流设备的状态
*/ */
void sendStreamPushRequestedMsgForStatus(); void sendStreamPushRequestedMsgForStatus();
List<SendRtpItem> querySendRTPServerByChnnelId(String channelId);
} }

View File

@ -170,15 +170,6 @@ public interface IVideoManagerStorage {
*/ */
boolean deleteParentPlatform(ParentPlatform parentPlatform); boolean deleteParentPlatform(ParentPlatform parentPlatform);
/**
* 分页获取上级平台
* @param page
* @param count
* @return
*/
PageInfo<ParentPlatform> queryParentPlatformList(int page, int count);
/** /**
* 获取所有已启用的平台 * 获取所有已启用的平台
* @return * @return

View File

@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.storager.dao.dto;
/**
* 平台发送注册/注销消息时缓存此消息
* @author lin
*/
public class PlatformRegisterInfo {
/**
* 平台Id
*/
private String platformId;
/**
* 是否时注册false为注销
*/
private boolean register;
public static PlatformRegisterInfo getInstance(String platformId, boolean register) {
PlatformRegisterInfo platformRegisterInfo = new PlatformRegisterInfo();
platformRegisterInfo.setPlatformId(platformId);
platformRegisterInfo.setRegister(register);
return platformRegisterInfo;
}
public String getPlatformId() {
return platformId;
}
public void setPlatformId(String platformId) {
this.platformId = platformId;
}
public boolean isRegister() {
return register;
}
public void setRegister(boolean register) {
this.register = register;
}
}

View File

@ -16,11 +16,13 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; 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.DateUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.*; import java.util.*;
@ -289,18 +291,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
RedisUtil.set(key, parentPlatformCatch); RedisUtil.set(key, parentPlatformCatch);
} }
@Override
public void updatePlatformKeepalive(ParentPlatform parentPlatform) {
String key = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + parentPlatform.getServerGBId();
RedisUtil.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
}
@Override
public void updatePlatformRegister(ParentPlatform parentPlatform) {
String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_" + parentPlatform.getServerGBId();
RedisUtil.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
}
@Override @Override
public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) { public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) {
return (ParentPlatformCatch)RedisUtil.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId); return (ParentPlatformCatch)RedisUtil.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
@ -323,15 +313,15 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override @Override
public void updatePlatformRegisterInfo(String callId, String platformGbId) { public void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo) {
String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId; String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId;
RedisUtil.set(key, platformGbId, 30); RedisUtil.set(key, platformRegisterInfo, 30);
} }
@Override @Override
public String queryPlatformRegisterInfo(String callId) { public PlatformRegisterInfo queryPlatformRegisterInfo(String callId) {
return (String)RedisUtil.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId); return (PlatformRegisterInfo)RedisUtil.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
} }
@Override @Override
@ -379,6 +369,24 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
} }
} }
@Override
public List<SendRtpItem> querySendRTPServerByChnnelId(String channelId) {
if (channelId == null) {
return null;
}
String platformGbId = "*";
String callId = "*";
String streamId = "*";
String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_" + platformGbId
+ "_" + channelId + "_" + streamId + "_" + callId;
List<Object> scan = RedisUtil.scan(key);
List<SendRtpItem> result = new ArrayList<>();
for (Object o : scan) {
result.add((SendRtpItem) RedisUtil.get((String) o));
}
return result;
}
@Override @Override
public List<SendRtpItem> querySendRTPServer(String platformGbId) { public List<SendRtpItem> querySendRTPServer(String platformGbId) {
if (platformGbId == null) { if (platformGbId == null) {

View File

@ -457,13 +457,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
return result > 0; return result > 0;
} }
@Override
public PageInfo<ParentPlatform> queryParentPlatformList(int page, int count) {
PageHelper.startPage(page, count);
List<ParentPlatform> all = platformMapper.getParentPlatformList();
return new PageInfo<>(all);
}
@Override @Override
public ParentPlatform queryParentPlatByServerGBId(String platformGbId) { public ParentPlatform queryParentPlatByServerGBId(String platformGbId) {
return platformMapper.getParentPlatByServerGBId(platformGbId); return platformMapper.getParentPlatByServerGBId(platformGbId);

View File

@ -82,4 +82,9 @@ public class DateUtil {
return false; return false;
} }
} }
public static String getNowForISO8601() {
LocalDateTime nowDateTime = LocalDateTime.now();
return formatterISO8601.format(nowDateTime);
}
} }

View File

@ -33,11 +33,11 @@ public class SpringBeanFactory implements ApplicationContextAware {
/** /**
* 获取对象 这里重写了bean方法起主要作用 * 获取对象 这里重写了bean方法起主要作用
*/ */
public static Object getBean(String beanId) throws BeansException { public static <T> T getBean(String beanId) throws BeansException {
if (applicationContext == null) { if (applicationContext == null) {
return null; return null;
} }
return applicationContext.getBean(beanId); return (T) applicationContext.getBean(beanId);
} }
/** /**

View File

@ -5,15 +5,14 @@ import java.util.concurrent.TimeUnit;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import org.springframework.beans.factory.annotation.Autowired; import gov.nist.javax.sip.stack.UDPMessageChannel;
import org.springframework.data.redis.core.*; import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
/** /**
* @description:Redis工具类 * Redis工具类
* @author: swwheihei * @author swwheihei
* @date: 2020年5月6日 下午8:27:29 * @date 2020年5月6日 下午8:27:29
*/ */
@SuppressWarnings(value = {"rawtypes", "unchecked"}) @SuppressWarnings(value = {"rawtypes", "unchecked"})
public class RedisUtil { public class RedisUtil {
@ -21,9 +20,9 @@ public class RedisUtil {
private static RedisTemplate redisTemplate; private static RedisTemplate redisTemplate;
static { static {
redisTemplate = (RedisTemplate)SpringBeanFactory.getBean("redisTemplate"); redisTemplate = SpringBeanFactory.getBean("redisTemplate");
} }
/** /**
* 指定缓存失效时间 * 指定缓存失效时间
* @param key * @param key
@ -31,6 +30,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean expire(String key, long time) { public static boolean expire(String key, long time) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
if (time > 0) { if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS); redisTemplate.expire(key, time, TimeUnit.SECONDS);
@ -45,9 +47,11 @@ public class RedisUtil {
/** /**
* 根据 key 获取过期时间 * 根据 key 获取过期时间
* @param key * @param key
* @return
*/ */
public static long getExpire(String key) { public static long getExpire(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.getExpire(key, TimeUnit.SECONDS); return redisTemplate.getExpire(key, TimeUnit.SECONDS);
} }
@ -57,6 +61,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean hasKey(String key) { public static boolean hasKey(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.hasKey(key); return redisTemplate.hasKey(key);
} catch (Exception e) { } catch (Exception e) {
@ -71,6 +78,9 @@ public class RedisUtil {
* @param key 一个或者多个 * @param key 一个或者多个
*/ */
public static boolean del(String... key) { public static boolean del(String... key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
if (key != null && key.length > 0) { if (key != null && key.length > 0) {
if (key.length == 1) { if (key.length == 1) {
@ -95,6 +105,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Object get(String key) { public static Object get(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return key == null ? null : redisTemplate.opsForValue().get(key); return key == null ? null : redisTemplate.opsForValue().get(key);
} }
@ -105,6 +118,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean set(String key, Object value) { public static boolean set(String key, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForValue().set(key, value); redisTemplate.opsForValue().set(key, value);
return true; return true;
@ -122,6 +138,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean set(String key, Object value, long time) { public static boolean set(String key, Object value, long time) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
if (time > 0) { if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
@ -142,6 +161,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static long incr(String key, long delta) { public static long incr(String key, long delta) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
if (delta < 0) { if (delta < 0) {
throw new RuntimeException("递增因子必须大于 0"); throw new RuntimeException("递增因子必须大于 0");
} }
@ -155,6 +177,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static long decr(String key, long delta) { public static long decr(String key, long delta) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
if (delta < 0) { if (delta < 0) {
throw new RuntimeException("递减因子必须大于 0"); throw new RuntimeException("递减因子必须大于 0");
} }
@ -170,6 +195,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Object hget(String key, String item) { public static Object hget(String key, String item) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForHash().get(key, item); return redisTemplate.opsForHash().get(key, item);
} }
@ -179,6 +207,9 @@ public class RedisUtil {
* @return 对应的多个键值 * @return 对应的多个键值
*/ */
public static Map<Object, Object> hmget(String key) { public static Map<Object, Object> hmget(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForHash().entries(key); return redisTemplate.opsForHash().entries(key);
} }
@ -189,6 +220,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean hmset(String key, Map<Object, Object> map) { public static boolean hmset(String key, Map<Object, Object> map) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForHash().putAll(key, map); redisTemplate.opsForHash().putAll(key, map);
return true; return true;
@ -206,6 +240,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean hmset(String key, Map<Object, Object> map, long time) { public static boolean hmset(String key, Map<Object, Object> map, long time) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForHash().putAll(key, map); redisTemplate.opsForHash().putAll(key, map);
if (time > 0) { if (time > 0) {
@ -226,6 +263,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean hset(String key, String item, Object value) { public static boolean hset(String key, String item, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForHash().put(key, item, value); redisTemplate.opsForHash().put(key, item, value);
return true; return true;
@ -244,6 +284,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean hset(String key, String item, Object value, long time) { public static boolean hset(String key, String item, Object value, long time) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForHash().put(key, item, value); redisTemplate.opsForHash().put(key, item, value);
if (time > 0) { if (time > 0) {
@ -262,6 +305,9 @@ public class RedisUtil {
* @param item 可以多个no null * @param item 可以多个no null
*/ */
public static void hdel(String key, Object... item) { public static void hdel(String key, Object... item) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
redisTemplate.opsForHash().delete(key, item); redisTemplate.opsForHash().delete(key, item);
} }
@ -272,6 +318,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean hHasKey(String key, String item) { public static boolean hHasKey(String key, String item) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForHash().hasKey(key, item); return redisTemplate.opsForHash().hasKey(key, item);
} }
@ -283,6 +332,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Double hincr(String key, String item, Double by) { public static Double hincr(String key, String item, Double by) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForHash().increment(key, item, by); return redisTemplate.opsForHash().increment(key, item, by);
} }
@ -294,6 +346,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Double hdecr(String key, String item, Double by) { public static Double hdecr(String key, String item, Double by) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForHash().increment(key, item, -by); return redisTemplate.opsForHash().increment(key, item, -by);
} }
@ -305,6 +360,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Set<Object> sGet(String key) { public static Set<Object> sGet(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForSet().members(key); return redisTemplate.opsForSet().members(key);
} catch (Exception e) { } catch (Exception e) {
@ -320,6 +378,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean sHasKey(String key, Object value) { public static boolean sHasKey(String key, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForSet().isMember(key, value); return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) { } catch (Exception e) {
@ -335,6 +396,9 @@ public class RedisUtil {
* @return 成功个数 * @return 成功个数
*/ */
public static long sSet(String key, Object... values) { public static long sSet(String key, Object... values) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForSet().add(key, values); return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) { } catch (Exception e) {
@ -351,6 +415,9 @@ public class RedisUtil {
* @return 成功放入个数 * @return 成功放入个数
*/ */
public static long sSet(String key, long time, Object... values) { public static long sSet(String key, long time, Object... values) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
long count = redisTemplate.opsForSet().add(key, values); long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) { if (time > 0) {
@ -369,6 +436,9 @@ public class RedisUtil {
* @return 长度 * @return 长度
*/ */
public static long sGetSetSize(String key) { public static long sGetSetSize(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForSet().size(key); return redisTemplate.opsForSet().size(key);
} catch (Exception e) { } catch (Exception e) {
@ -384,6 +454,9 @@ public class RedisUtil {
* @return 成功移除个数 * @return 成功移除个数
*/ */
public static long setRemove(String key, Object... values) { public static long setRemove(String key, Object... values) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForSet().remove(key, values); return redisTemplate.opsForSet().remove(key, values);
} catch (Exception e) { } catch (Exception e) {
@ -401,6 +474,9 @@ public class RedisUtil {
* @param score * @param score
*/ */
public static void zAdd(Object key, Object value, double score) { public static void zAdd(Object key, Object value, double score) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
redisTemplate.opsForZSet().add(key, value, score); redisTemplate.opsForZSet().add(key, value, score);
} }
@ -411,6 +487,9 @@ public class RedisUtil {
* @param value * @param value
*/ */
public static void zRemove(Object key, Object value) { public static void zRemove(Object key, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
redisTemplate.opsForZSet().remove(key, value); redisTemplate.opsForZSet().remove(key, value);
} }
@ -422,6 +501,9 @@ public class RedisUtil {
* @param delta -1 表示减 1 表示加1 * @param delta -1 表示减 1 表示加1
*/ */
public static Double zIncrScore(Object key, Object value, double delta) { public static Double zIncrScore(Object key, Object value, double delta) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().incrementScore(key, value, delta); return redisTemplate.opsForZSet().incrementScore(key, value, delta);
} }
@ -433,6 +515,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Double zScore(Object key, Object value) { public static Double zScore(Object key, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().score(key, value); return redisTemplate.opsForZSet().score(key, value);
} }
@ -444,6 +529,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Long zRank(Object key, Object value) { public static Long zRank(Object key, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().rank(key, value); return redisTemplate.opsForZSet().rank(key, value);
} }
@ -454,6 +542,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Long zSize(Object key) { public static Long zSize(Object key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().zCard(key); return redisTemplate.opsForZSet().zCard(key);
} }
@ -467,7 +558,10 @@ public class RedisUtil {
* @param end * @param end
* @return * @return
*/ */
public static Set<Object> ZRange(Object key, int start, int end) { public static Set<Object> zRange(Object key, int start, int end) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().range(key, start, end); return redisTemplate.opsForZSet().range(key, start, end);
} }
/** /**
@ -479,6 +573,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) { public static Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().rangeWithScores(key, start, end); return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
} }
/** /**
@ -492,6 +589,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Set<String> zRevRange(Object key, int start, int end) { public static Set<String> zRevRange(Object key, int start, int end) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().reverseRange(key, start, end); return redisTemplate.opsForZSet().reverseRange(key, start, end);
} }
/** /**
@ -503,6 +603,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Set<String> zSortRange(Object key, int min, int max) { public static Set<String> zSortRange(Object key, int min, int max) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForZSet().rangeByScore(key, min, max); return redisTemplate.opsForZSet().rangeByScore(key, min, max);
} }
@ -517,6 +620,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static List<Object> lGet(String key, long start, long end) { public static List<Object> lGet(String key, long start, long end) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForList().range(key, start, end); return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) { } catch (Exception e) {
@ -531,6 +637,9 @@ public class RedisUtil {
* @return 长度 * @return 长度
*/ */
public static long lGetListSize(String key) { public static long lGetListSize(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForList().size(key); return redisTemplate.opsForList().size(key);
} catch (Exception e) { } catch (Exception e) {
@ -548,6 +657,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Object lGetIndex(String key, long index) { public static Object lGetIndex(String key, long index) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForList().index(key, index); return redisTemplate.opsForList().index(key, index);
} catch (Exception e) { } catch (Exception e) {
@ -563,6 +675,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean lSet(String key, Object value) { public static boolean lSet(String key, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForList().rightPush(key, value); redisTemplate.opsForList().rightPush(key, value);
return true; return true;
@ -580,6 +695,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean lSet(String key, Object value, long time) { public static boolean lSet(String key, Object value, long time) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForList().rightPush(key, value); redisTemplate.opsForList().rightPush(key, value);
if (time > 0) { if (time > 0) {
@ -599,6 +717,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean lSetList(String key, List<Object> values) { public static boolean lSetList(String key, List<Object> values) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForList().rightPushAll(key, values); redisTemplate.opsForList().rightPushAll(key, values);
return true; return true;
@ -616,6 +737,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean lSetList(String key, List<Object> values, long time) { public static boolean lSetList(String key, List<Object> values, long time) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForList().rightPushAll(key, values); redisTemplate.opsForList().rightPushAll(key, values);
if (time > 0) { if (time > 0) {
@ -636,6 +760,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static boolean lUpdateIndex(String key, long index, Object value) { public static boolean lUpdateIndex(String key, long index, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
redisTemplate.opsForList().set(key, index, value); redisTemplate.opsForList().set(key, index, value);
return true; return true;
@ -655,6 +782,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static long lRemove(String key, long count, Object value) { public static long lRemove(String key, long count, Object value) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
return redisTemplate.opsForList().remove(key, count, value); return redisTemplate.opsForList().remove(key, count, value);
} catch (Exception e) { } catch (Exception e) {
@ -669,6 +799,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Object lLeftPop(String key) { public static Object lLeftPop(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForList().leftPop(key); return redisTemplate.opsForList().leftPop(key);
} }
@ -678,6 +811,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static Object lrightPop(String key) { public static Object lrightPop(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
return redisTemplate.opsForList().rightPop(key); return redisTemplate.opsForList().rightPop(key);
} }
@ -687,6 +823,9 @@ public class RedisUtil {
* @return true / false * @return true / false
*/ */
public static List<Object> keys(String key) { public static List<Object> keys(String key) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
try { try {
Set<String> set = redisTemplate.keys(key); Set<String> set = redisTemplate.keys(key);
return new ArrayList<>(set); return new ArrayList<>(set);
@ -727,6 +866,9 @@ public class RedisUtil {
* @return * @return
*/ */
public static List<Object> scan(String query) { public static List<Object> scan(String query) {
if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
Set<String> resultKeys = (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> { Set<String> resultKeys = (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
ScanOptions scanOptions = ScanOptions.scanOptions().match("*" + query + "*").count(1000).build(); ScanOptions scanOptions = ScanOptions.scanOptions().match("*" + query + "*").count(1000).build();
Cursor<byte[]> scan = connection.scan(scanOptions); Cursor<byte[]> scan = connection.scan(scanOptions);
@ -743,9 +885,10 @@ public class RedisUtil {
// ============================== 消息发送与订阅 ============================== // ============================== 消息发送与订阅 ==============================
public static void convertAndSend(String channel, JSONObject msg) { public static void convertAndSend(String channel, JSONObject msg) {
// redisTemplate.convertAndSend(channel, msg); if (redisTemplate == null) {
redisTemplate = SpringBeanFactory.getBean("redisTemplate");
}
redisTemplate.convertAndSend(channel, msg); redisTemplate.convertAndSend(channel, msg);
} }
} }

View File

@ -9,14 +9,13 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
import com.genersoft.iot.vmp.gb28181.bean.TreeType;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformChannelService; import com.genersoft.iot.vmp.service.IPlatformChannelService;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -26,10 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
@ -70,6 +66,9 @@ public class PlatformController {
@Autowired @Autowired
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
@Autowired
private IPlatformService platformService;
/** /**
* 获取国标服务的配置 * 获取国标服务的配置
* *
@ -95,8 +94,7 @@ public class PlatformController {
@Parameter(name = "id", description = "平台国标编号", required = true) @Parameter(name = "id", description = "平台国标编号", required = true)
@GetMapping("/info/{id}") @GetMapping("/info/{id}")
public ParentPlatform getPlatform(@PathVariable String id) { public ParentPlatform getPlatform(@PathVariable String id) {
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(id); ParentPlatform parentPlatform = platformService.queryPlatformByServerGBId(id);
WVPResult<ParentPlatform> wvpResult = new WVPResult<>();
if (parentPlatform != null) { if (parentPlatform != null) {
return parentPlatform; return parentPlatform;
} else { } else {
@ -117,7 +115,7 @@ public class PlatformController {
@Parameter(name = "count", description = "每页条数", required = true) @Parameter(name = "count", description = "每页条数", required = true)
public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count) { public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count) {
PageInfo<ParentPlatform> parentPlatformPageInfo = storager.queryParentPlatformList(page, count); PageInfo<ParentPlatform> parentPlatformPageInfo = platformService.queryParentPlatformList(page, count);
if (parentPlatformPageInfo.getList().size() > 0) { if (parentPlatformPageInfo.getList().size() > 0) {
for (ParentPlatform platform : parentPlatformPageInfo.getList()) { for (ParentPlatform platform : parentPlatformPageInfo.getList()) {
platform.setMobilePositionSubscribe(subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()) != null); platform.setMobilePositionSubscribe(subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()) != null);
@ -136,7 +134,7 @@ public class PlatformController {
@Operation(summary = "添加上级平台信息") @Operation(summary = "添加上级平台信息")
@PostMapping("/add") @PostMapping("/add")
@ResponseBody @ResponseBody
public String addPlatform(@RequestBody ParentPlatform parentPlatform) { public void addPlatform(@RequestBody ParentPlatform parentPlatform) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("保存上级平台信息API调用"); logger.debug("保存上级平台信息API调用");
@ -158,32 +156,16 @@ public class PlatformController {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "error severPort"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "error severPort");
} }
ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId()); ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
if (parentPlatformOld != null) { if (parentPlatformOld != null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台 " + parentPlatform.getServerGBId() + " 已存在"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台 " + parentPlatform.getServerGBId() + " 已存在");
} }
parentPlatform.setCreateTime(DateUtil.getNow()); parentPlatform.setCreateTime(DateUtil.getNow());
parentPlatform.setUpdateTime(DateUtil.getNow()); parentPlatform.setUpdateTime(DateUtil.getNow());
boolean updateResult = storager.updateParentPlatform(parentPlatform); boolean updateResult = platformService.add(parentPlatform);
if (updateResult) { if (!updateResult) {
// 保存时启用就发送注册
if (parentPlatform.isEnable()) {
if (parentPlatformOld != null && parentPlatformOld.isStatus()) {
commanderForPlatform.unregister(parentPlatformOld, null, eventResult -> {
// 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null);
});
} else {
// 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null);
}
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
commanderForPlatform.unregister(parentPlatform, null, null);
}
return null;
} else {
throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败"); throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败");
} }
} }
@ -197,7 +179,7 @@ public class PlatformController {
@Operation(summary = "保存上级平台信息") @Operation(summary = "保存上级平台信息")
@PostMapping("/save") @PostMapping("/save")
@ResponseBody @ResponseBody
public String savePlatform(@RequestBody ParentPlatform parentPlatform) { public void savePlatform(@RequestBody ParentPlatform parentPlatform) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("保存上级平台信息API调用"); logger.debug("保存上级平台信息API调用");
@ -247,7 +229,6 @@ public class PlatformController {
// 停止订阅相关的定时任务 // 停止订阅相关的定时任务
subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
} }
return null;
} else { } else {
throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败"); throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败");
} }

View File

@ -8,24 +8,21 @@ import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.VersionInfo; import com.genersoft.iot.vmp.conf.VersionInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.ehcache.xml.model.ThreadPoolsType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.sip.ListeningPoint; import javax.sip.ListeningPoint;
@ -42,7 +39,7 @@ import java.util.List;
public class ServerController { public class ServerController {
@Autowired @Autowired
private ZLMHttpHookSubscribe zlmHttpHookSubscribe; private ZlmHttpHookSubscribe zlmHttpHookSubscribe;
@Autowired @Autowired
private IMediaServerService mediaServerService; private IMediaServerService mediaServerService;

View File

@ -5,6 +5,7 @@ import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadSheet;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.security.SecurityUtils; import com.genersoft.iot.vmp.conf.security.SecurityUtils;
import com.genersoft.iot.vmp.conf.security.dto.LoginUser; import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.bean.GbStream;
@ -17,6 +18,7 @@ import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler; import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler;
import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam; import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto; import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -95,11 +97,9 @@ public class StreamPushController {
@PostMapping(value = "/save_to_gb") @PostMapping(value = "/save_to_gb")
@ResponseBody @ResponseBody
@Operation(summary = "将推流添加到国标") @Operation(summary = "将推流添加到国标")
public Object saveToGB(@RequestBody GbStream stream){ public void saveToGB(@RequestBody GbStream stream){
if (streamPushService.saveToGB(stream)){ if (!streamPushService.saveToGB(stream)){
return "success"; throw new ControllerException(ErrorCode.ERROR100);
}else {
return "fail";
} }
} }
@ -107,11 +107,9 @@ public class StreamPushController {
@DeleteMapping(value = "/remove_form_gb") @DeleteMapping(value = "/remove_form_gb")
@ResponseBody @ResponseBody
@Operation(summary = "将推流移出到国标") @Operation(summary = "将推流移出到国标")
public Object removeFormGB(@RequestBody GbStream stream){ public void removeFormGB(@RequestBody GbStream stream){
if (streamPushService.removeFromGB(stream)){ if (!streamPushService.removeFromGB(stream)){
return "success"; throw new ControllerException(ErrorCode.ERROR100);
}else {
return "fail";
} }
} }
@ -121,25 +119,21 @@ public class StreamPushController {
@Operation(summary = "中止一个推流") @Operation(summary = "中止一个推流")
@Parameter(name = "app", description = "应用名", required = true) @Parameter(name = "app", description = "应用名", required = true)
@Parameter(name = "stream", description = "流id", required = true) @Parameter(name = "stream", description = "流id", required = true)
public Object stop(String app, String streamId){ public void stop(String app, String streamId){
if (streamPushService.stop(app, streamId)){ if (!streamPushService.stop(app, streamId)){
return "success"; throw new ControllerException(ErrorCode.ERROR100);
}else {
return "fail";
} }
} }
@DeleteMapping(value = "/batchStop") @DeleteMapping(value = "/batchStop")
@ResponseBody @ResponseBody
@Operation(summary = "中止多个推流") @Operation(summary = "中止多个推流")
public Object batchStop(@RequestBody BatchGBStreamParam batchGBStreamParam){ public void batchStop(@RequestBody BatchGBStreamParam batchGBStreamParam){
if (batchGBStreamParam.getGbStreams().size() == 0) { if (batchGBStreamParam.getGbStreams().size() == 0) {
return "fail"; throw new ControllerException(ErrorCode.ERROR100);
} }
if (streamPushService.batchStop(batchGBStreamParam.getGbStreams())){ if (!streamPushService.batchStop(batchGBStreamParam.getGbStreams())){
return "success"; throw new ControllerException(ErrorCode.ERROR100);
}else {
return "fail";
} }
} }
@ -249,7 +243,7 @@ public class StreamPushController {
@Parameter(name = "app", description = "应用名", required = true) @Parameter(name = "app", description = "应用名", required = true)
@Parameter(name = "stream", description = "流id", required = true) @Parameter(name = "stream", description = "流id", required = true)
@Parameter(name = "mediaServerId", description = "媒体服务器id") @Parameter(name = "mediaServerId", description = "媒体服务器id")
public WVPResult<StreamInfo> getPlayUrl(@RequestParam String app,@RequestParam String stream, public StreamInfo getPlayUrl(@RequestParam String app,@RequestParam String stream,
@RequestParam(required = false) String mediaServerId){ @RequestParam(required = false) String mediaServerId){
boolean authority = false; boolean authority = false;
// 是否登陆用户, 登陆用户返回完整信息 // 是否登陆用户, 登陆用户返回完整信息
@ -257,52 +251,38 @@ public class StreamPushController {
if (userInfo!= null) { if (userInfo!= null) {
authority = true; authority = true;
} }
WVPResult<StreamInfo> result = new WVPResult<>();
StreamPushItem push = streamPushService.getPush(app, stream); StreamPushItem push = streamPushService.getPush(app, stream);
if (push != null && !push.isSelf()) { if (push != null && !push.isSelf()) {
result.setCode(-1); throw new ControllerException(ErrorCode.ERROR100.getCode(), "来自其他平台的推流信息");
result.setMsg("来自其他平台的推流信息");
return result;
} }
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
if (streamInfo != null){ if (streamInfo == null){
result.setCode(0); throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取播放地址失败");
result.setMsg("success");
result.setData(streamInfo);
}else {
result.setCode(-1);
result.setMsg("获取播放地址失败");
} }
return streamInfo;
return result;
} }
/** /**
* 获取推流播放地址 * 添加推流信息
* @param stream 推流信息 * @param stream 推流信息
* @return * @return
*/ */
@PostMapping(value = "/add") @PostMapping(value = "/add")
@ResponseBody @ResponseBody
@Operation(summary = "停止视频回放") @Operation(summary = "添加推流信息")
public WVPResult<StreamInfo> add(@RequestBody StreamPushItem stream){ public void add(@RequestBody StreamPushItem stream){
if (ObjectUtils.isEmpty(stream.getGbId())) { if (ObjectUtils.isEmpty(stream.getGbId())) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "国标ID不可为空");
return new WVPResult<>(400, "国标ID不可为空", null);
} }
if (ObjectUtils.isEmpty(stream.getApp()) && ObjectUtils.isEmpty(stream.getStream())) { if (ObjectUtils.isEmpty(stream.getApp()) && ObjectUtils.isEmpty(stream.getStream())) {
return new WVPResult<>(400, "app或stream不可为空", null); throw new ControllerException(ErrorCode.ERROR400.getCode(), "app或stream不可为空");
} }
stream.setStatus(false); stream.setStatus(false);
stream.setPushIng(false); stream.setPushIng(false);
stream.setAliveSecond(0L); stream.setAliveSecond(0L);
stream.setTotalReaderCount("0"); stream.setTotalReaderCount("0");
boolean result = streamPushService.add(stream); if (!streamPushService.add(stream)) {
throw new ControllerException(ErrorCode.ERROR100);
if (result) {
return new WVPResult<>(0, "success", null);
}else {
return new WVPResult<>(-1, "fail", null);
} }
} }
} }

View File

@ -179,8 +179,6 @@ user-settings:
platform-play-timeout: 60000 platform-play-timeout: 60000
# 是否开启接口鉴权 # 是否开启接口鉴权
interface-authentication: true interface-authentication: true
# 自动配置redis 可以过期事件
redis-config: true
# 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录 # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
interface-authentication-excludes: interface-authentication-excludes:
- /api/v1/** - /api/v1/**

View File

@ -77,25 +77,35 @@
</encoder> </encoder>
</appender> </appender>
<!-- 生成 SIP日志追加 -->
<appender name="sipRollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--历史日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/sip-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>50MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别 --> <!-- 日志输出级别 -->
<root level="INFO"> <root level="INFO">
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
<appender-ref ref="RollingFile" />
<appender-ref ref="RollingFileError" />
</root> </root>
<!-- <logger name="com.genersoft.iot.vmp.storager.dao" level="INFO">--> <logger name="GB28181_SIP" level="debug" additivity="true">
<!-- <appender-ref ref="STDOUT"/>--> <appender-ref ref="RollingFileError"/>
<!-- </logger>--> <appender-ref ref="sipRollingFile"/>
<!-- <logger name="com.genersoft.iot.vmp.gb28181" level="INFO">--> </logger>
<!-- <appender-ref ref="STDOUT"/>-->
<!-- </logger>-->
<!--记录druid-sql的记录--> <!--记录druid-sql的记录-->
<logger name="druid.sql.Statement" level="debug" additivity="true"> <logger name="com.genersoft.iot.vmp.storager.dao" level="info" additivity="true">
<!--AppenderRef ref="Console"/--> <!--AppenderRef ref="Console"/-->
<!-- <appender-ref ref="RollingFile"/>-->
<appender-ref ref="RollingFileError"/> <appender-ref ref="RollingFileError"/>
<appender-ref ref="druidSqlRollingFile"/> <appender-ref ref="druidSqlRollingFile"/>
</logger> </logger>

View File

@ -1,7 +1,11 @@
<template> <template>
<div id="app" style="width: 100%"> <div id="app" style="width: 100%">
<div class="page-header"> <div class="page-header">
<div class="page-title">云端录像</div> <div class="page-title">
<el-page-header v-if="recordDetail" @back="backToList" content="云端录像"></el-page-header>
<div v-if="!recordDetail">云端录像</div>
</div>
<div class="page-header-btn"> <div class="page-header-btn">
节点选择: 节点选择:
<el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail"> <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail">
@ -183,7 +187,7 @@
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
} },
} }

View File

@ -1,7 +1,9 @@
<template> <template>
<div id="recordDetail"> <div id="recordDetail">
<el-container> <el-container>
<el-aside width="300px"> <el-aside width="300px">
<div class="record-list-box-box"> <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> <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 class="record-list-box" :style="recordListStyle"> <div class="record-list-box" :style="recordListStyle">
@ -423,6 +425,9 @@
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
},
goBack(){
this.$router.push('/cloudRecord');
} }
} }
}; };

View File

@ -66,10 +66,6 @@ export default {
// //
toLogin(){ toLogin(){
//
//./js/sha1.min.js
// //
let loginParam = { let loginParam = {
username: this.username, username: this.username,
@ -78,12 +74,17 @@ export default {
var that = this; var that = this;
// //
this.isLoging = true; this.isLoging = true;
let timeoutTask = setTimeout(()=>{
that.$message.error("登录超时");
that.isLoging = false;
}, 1000)
this.$axios({ this.$axios({
method: 'get', method: 'get',
url:"/api/user/login", url:"/api/user/login",
params: loginParam params: loginParam
}).then(function (res) { }).then(function (res) {
window.clearTimeout(timeoutTask)
console.log(JSON.stringify(res)); console.log(JSON.stringify(res));
if (res.data.code === 0 ) { if (res.data.code === 0 ) {
that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ; that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ;
@ -99,6 +100,8 @@ export default {
}); });
} }
}).catch(function (error) { }).catch(function (error) {
console.log(error)
window.clearTimeout(timeoutTask)
that.$message.error(error.response.data.msg); that.$message.error(error.response.data.msg);
that.isLoging = false; that.isLoging = false;
}); });

View File

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

View File

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

View File

@ -386,7 +386,7 @@ export default {
if (tab.name === "codec") { if (tab.name === "codec") {
this.$axios({ this.$axios({
method: 'get', method: 'get',
url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app='+ this.app +'&stream='+ this.streamId
}).then(function (res) { }).then(function (res) {
that.tracksLoading = false; that.tracksLoading = false;
if (res.data.code == 0 && res.data.tracks) { if (res.data.code == 0 && res.data.tracks) {

View File

@ -268,30 +268,29 @@ export default {
} }
}, },
saveForm: function (){ saveForm: function (){
var that = this; this.$axios({
that.$axios({
method: 'post', method: 'post',
url: this.saveUrl, url: this.saveUrl,
data: that.platform data: this.platform
}).then(function (res) { }).then((res) =>{
if (res.data.code === 0) { if (res.data.code === 0) {
that.$message({ this.$message({
showClose: true, showClose: true,
message: "保存成功", message: "保存成功",
type: "success", type: "success",
}); });
that.showDialog = false; this.showDialog = false;
if (that.listChangeCallback != null) { if (this.listChangeCallback != null) {
that.listChangeCallback(); this.listChangeCallback();
} }
}else { }else {
that.$message({ this.$message({
showClose: true, showClose: true,
message: res.data.msg, message: res.data.msg,
type: "error", type: "error",
}); });
} }
}).catch(function (error) { }).catch((error)=> {
console.log(error); console.log(error);
}); });
}, },
@ -328,7 +327,7 @@ export default {
var result = false; var result = false;
var that = this; var that = this;
await that.$axios({ await that.$axios({
method: 'post', method: 'get',
url:`/api/platform/exit/${deviceGbId}`}) url:`/api/platform/exit/${deviceGbId}`})
.then(function (res) { .then(function (res) {
if (res.data.code === 0) { if (res.data.code === 0) {

View File

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