mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-05-26 23:17:50 +08:00
Compare commits
15 Commits
4b885af4c5
...
14b18794bc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14b18794bc | ||
|
|
a1a5c53fad | ||
|
|
7c7ef34045 | ||
|
|
243f7f62b7 | ||
|
|
b0b5a0f5e0 | ||
|
|
706806a138 | ||
|
|
83f603238a | ||
|
|
7bb0cc19f4 | ||
|
|
1d172cb387 | ||
|
|
bcf08d27fa | ||
|
|
29ac4850f4 | ||
|
|
dd17462b68 | ||
|
|
a1ba811962 | ||
|
|
bfc063e4f7 | ||
|
|
b05f770a57 |
@ -0,0 +1,7 @@
|
|||||||
|
package com.genersoft.iot.vmp.common;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
|
||||||
|
public interface SubscribeCallback{
|
||||||
|
public void run(String deviceId, SipTransactionInfo transactionInfo);
|
||||||
|
}
|
||||||
@ -1,13 +1,13 @@
|
|||||||
package com.genersoft.iot.vmp.common;
|
package com.genersoft.iot.vmp.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 定义常量
|
* @description: 定义常量
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年5月30日 下午3:04:04
|
* @date: 2019年5月30日 下午3:04:04
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class VideoManagerConstants {
|
public class VideoManagerConstants {
|
||||||
|
|
||||||
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
|
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
|
||||||
|
|
||||||
public static final String WVP_SERVER_LIST = "VMP_SERVER_LIST";
|
public static final String WVP_SERVER_LIST = "VMP_SERVER_LIST";
|
||||||
@ -22,10 +22,6 @@ public class VideoManagerConstants {
|
|||||||
|
|
||||||
public static final String INVITE_PREFIX = "VMP_GB_INVITE_INFO";
|
public static final String INVITE_PREFIX = "VMP_GB_INVITE_INFO";
|
||||||
|
|
||||||
public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_";
|
|
||||||
|
|
||||||
public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_";
|
|
||||||
|
|
||||||
public static final String SEND_RTP_PORT = "VM_SEND_RTP_PORT:";
|
public static final String SEND_RTP_PORT = "VM_SEND_RTP_PORT:";
|
||||||
public static final String SEND_RTP_INFO_CALLID = "VMP_SEND_RTP_INFO:CALL_ID:";
|
public static final String SEND_RTP_INFO_CALLID = "VMP_SEND_RTP_INFO:CALL_ID:";
|
||||||
public static final String SEND_RTP_INFO_STREAM = "VMP_SEND_RTP_INFO:STREAM:";
|
public static final String SEND_RTP_INFO_STREAM = "VMP_SEND_RTP_INFO:STREAM:";
|
||||||
|
|||||||
@ -1,71 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.conf;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatch;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.CommandLineRunner;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统启动时控制上级平台重新注册
|
|
||||||
* @author lin
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@Order(value=13)
|
|
||||||
public class SipPlatformRunner implements CommandLineRunner {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IPlatformService platformService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISIPCommanderForPlatform sipCommanderForPlatform;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserSetting userSetting;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(String... args) throws Exception {
|
|
||||||
// 获取所有启用的平台
|
|
||||||
List<Platform> parentPlatforms = platformService.queryEnablePlatformList(userSetting.getServerId());
|
|
||||||
|
|
||||||
for (Platform platform : parentPlatforms) {
|
|
||||||
|
|
||||||
PlatformCatch platformCatchOld = redisCatchStorage.queryPlatformCatchInfo(platform.getServerGBId());
|
|
||||||
|
|
||||||
// 更新缓存
|
|
||||||
PlatformCatch platformCatch = new PlatformCatch();
|
|
||||||
platformCatch.setPlatform(platform);
|
|
||||||
platformCatch.setId(platform.getServerGBId());
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
|
||||||
if (platformCatchOld != null) {
|
|
||||||
// 取消订阅
|
|
||||||
try {
|
|
||||||
log.info("[平台主动注销] {}({})", platform.getName(), platform.getServerGBId());
|
|
||||||
sipCommanderForPlatform.unregister(platform, platformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
|
|
||||||
platformService.login(platform);
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
|
||||||
platformService.offline(platform, true);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
platformService.login(platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置平台离线
|
|
||||||
platformService.offline(platform, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -16,7 +16,7 @@ import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
|||||||
* @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
* @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2019年5月30日 上午10:58:25
|
* @date: 2019年5月30日 上午10:58:25
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@Order(value=1)
|
@Order(value=1)
|
||||||
@ -38,7 +38,6 @@ public class RedisMsgListenConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RedisCloseStreamMsgListener redisCloseStreamMsgListener;
|
private RedisCloseStreamMsgListener redisCloseStreamMsgListener;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisRpcConfig redisRpcConfig;
|
private RedisRpcConfig redisRpcConfig;
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ public class RedisMsgListenConfig {
|
|||||||
/**
|
/**
|
||||||
* redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
|
* redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
|
||||||
* 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
|
* 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
|
||||||
*
|
*
|
||||||
* @param connectionFactory
|
* @param connectionFactory
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,18 +1,23 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过redis分发报警消息
|
* 通过redis分发报警消息
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
public class AlarmChannelMessage {
|
public class AlarmChannelMessage {
|
||||||
/**
|
/**
|
||||||
* 国标编号
|
* 通道国标编号
|
||||||
*/
|
*/
|
||||||
private String gbId;
|
private String gbId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 报警编号
|
* 报警编号
|
||||||
*/
|
*/
|
||||||
private int alarmSn;
|
private int alarmSn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 告警类型
|
* 告警类型
|
||||||
*/
|
*/
|
||||||
@ -22,36 +27,4 @@ public class AlarmChannelMessage {
|
|||||||
* 报警描述
|
* 报警描述
|
||||||
*/
|
*/
|
||||||
private String alarmDescription;
|
private String alarmDescription;
|
||||||
|
|
||||||
public String getGbId() {
|
|
||||||
return gbId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGbId(String gbId) {
|
|
||||||
this.gbId = gbId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAlarmSn() {
|
|
||||||
return alarmSn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarmSn(int alarmSn) {
|
|
||||||
this.alarmSn = alarmSn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAlarmType() {
|
|
||||||
return alarmType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarmType(int alarmType) {
|
|
||||||
this.alarmType = alarmType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAlarmDescription() {
|
|
||||||
return alarmDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarmDescription(String alarmDescription) {
|
|
||||||
this.alarmDescription = alarmDescription;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
public interface PlatformKeepaliveCallback {
|
||||||
|
public void run(String platformServerGbId, int failCount);
|
||||||
|
}
|
||||||
@ -1,13 +1,17 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
import gov.nist.javax.sip.message.SIPResponse;
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
public class SipTransactionInfo {
|
public class SipTransactionInfo {
|
||||||
|
|
||||||
private String callId;
|
private String callId;
|
||||||
private String fromTag;
|
private String fromTag;
|
||||||
private String toTag;
|
private String toTag;
|
||||||
private String viaBranch;
|
private String viaBranch;
|
||||||
|
private int expires;
|
||||||
|
private String user;
|
||||||
|
|
||||||
// 自己是否媒体流发送者
|
// 自己是否媒体流发送者
|
||||||
private boolean asSender;
|
private boolean asSender;
|
||||||
@ -31,43 +35,4 @@ public class SipTransactionInfo {
|
|||||||
public SipTransactionInfo() {
|
public SipTransactionInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCallId() {
|
|
||||||
return callId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallId(String callId) {
|
|
||||||
this.callId = callId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFromTag() {
|
|
||||||
return fromTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFromTag(String fromTag) {
|
|
||||||
this.fromTag = fromTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToTag() {
|
|
||||||
return toTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToTag(String toTag) {
|
|
||||||
this.toTag = toTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getViaBranch() {
|
|
||||||
return viaBranch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setViaBranch(String viaBranch) {
|
|
||||||
this.viaBranch = viaBranch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAsSender() {
|
|
||||||
return asSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAsSender(boolean asSender) {
|
|
||||||
this.asSender = asSender;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|
||||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lin
|
* @author lin
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class SubscribeHolder {
|
public class SubscribeHolder {
|
||||||
|
|
||||||
@ -23,107 +24,97 @@ public class SubscribeHolder {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserSetting userSetting;
|
private UserSetting userSetting;
|
||||||
|
|
||||||
private final String taskOverduePrefix = "subscribe_overdue_";
|
@Autowired
|
||||||
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
|
|
||||||
private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
|
private final String prefix = "VMP_SUBSCRIBE_OVERDUE";
|
||||||
|
|
||||||
public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
|
public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
|
||||||
catalogMap.put(platformId, subscribeInfo);
|
log.info("[国标级联] 添加目录订阅,平台: {}, 有效期: {}", platformId, subscribeInfo.getExpires());
|
||||||
|
|
||||||
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "catalog", platformId);
|
||||||
if (subscribeInfo.getExpires() > 0) {
|
if (subscribeInfo.getExpires() > 0) {
|
||||||
// 添加订阅到期
|
Duration duration = Duration.ofSeconds(subscribeInfo.getExpires());
|
||||||
String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
|
redisTemplate.opsForValue().set(key, subscribeInfo, duration);
|
||||||
// 添加任务处理订阅过期
|
}else {
|
||||||
dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
|
redisTemplate.opsForValue().set(key, subscribeInfo);
|
||||||
subscribeInfo.getExpires() * 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubscribeInfo getCatalogSubscribe(String platformId) {
|
public SubscribeInfo getCatalogSubscribe(String platformId) {
|
||||||
if (platformId == null) {
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "catalog", platformId);
|
||||||
return null;
|
return (SubscribeInfo)redisTemplate.opsForValue().get(key);
|
||||||
}
|
|
||||||
return catalogMap.get(platformId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeCatalogSubscribe(String platformId) {
|
public void removeCatalogSubscribe(String platformId) {
|
||||||
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "catalog", platformId);
|
||||||
catalogMap.remove(platformId);
|
redisTemplate.delete(key);
|
||||||
String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
|
|
||||||
Runnable runnable = dynamicTask.get(taskOverdueKey);
|
|
||||||
if (runnable instanceof ISubscribeTask) {
|
|
||||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
|
||||||
subscribeTask.stop(null);
|
|
||||||
}
|
|
||||||
// 添加任务处理订阅过期
|
|
||||||
dynamicTask.stop(taskOverdueKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo, Runnable gpsTask) {
|
public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo, Runnable gpsTask) {
|
||||||
mobilePositionMap.put(platformId, subscribeInfo);
|
log.info("[国标级联] 添加移动位置订阅,平台: {}, 有效期: {}s", platformId, subscribeInfo.getExpires());
|
||||||
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId;
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "mobilePosition", platformId);
|
||||||
// 添加任务处理GPS定时推送
|
if (subscribeInfo.getExpires() > 0) {
|
||||||
|
Duration duration = Duration.ofSeconds(subscribeInfo.getExpires());
|
||||||
|
redisTemplate.opsForValue().set(key, subscribeInfo, duration);
|
||||||
|
}else {
|
||||||
|
redisTemplate.opsForValue().set(key, subscribeInfo);
|
||||||
|
}
|
||||||
int cycleForCatalog;
|
int cycleForCatalog;
|
||||||
if (subscribeInfo.getGpsInterval() <= 0) {
|
if (subscribeInfo.getGpsInterval() <= 0) {
|
||||||
cycleForCatalog = 5;
|
cycleForCatalog = 5;
|
||||||
}else {
|
}else {
|
||||||
cycleForCatalog = subscribeInfo.getGpsInterval();
|
cycleForCatalog = subscribeInfo.getGpsInterval();
|
||||||
}
|
}
|
||||||
dynamicTask.startCron(key, gpsTask,
|
dynamicTask.startCron(
|
||||||
|
key,
|
||||||
|
() -> {
|
||||||
|
SubscribeInfo subscribe = getMobilePositionSubscribe(platformId);
|
||||||
|
if (subscribe != null) {
|
||||||
|
gpsTask.run();
|
||||||
|
}else {
|
||||||
|
dynamicTask.stop(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
cycleForCatalog * 1000);
|
cycleForCatalog * 1000);
|
||||||
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
|
|
||||||
if (subscribeInfo.getExpires() > 0) {
|
|
||||||
// 添加任务处理订阅过期
|
|
||||||
dynamicTask.startDelay(taskOverdueKey, () -> {
|
|
||||||
removeMobilePositionSubscribe(subscribeInfo.getId());
|
|
||||||
},
|
|
||||||
subscribeInfo.getExpires() * 1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubscribeInfo getMobilePositionSubscribe(String platformId) {
|
public SubscribeInfo getMobilePositionSubscribe(String platformId) {
|
||||||
return mobilePositionMap.get(platformId);
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "mobilePosition", platformId);
|
||||||
|
return (SubscribeInfo)redisTemplate.opsForValue().get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeMobilePositionSubscribe(String platformId) {
|
public void removeMobilePositionSubscribe(String platformId) {
|
||||||
mobilePositionMap.remove(platformId);
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "mobilePosition", platformId);
|
||||||
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId;
|
redisTemplate.delete(key);
|
||||||
// 结束任务处理GPS定时推送
|
|
||||||
dynamicTask.stop(key);
|
|
||||||
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
|
|
||||||
Runnable runnable = dynamicTask.get(taskOverdueKey);
|
|
||||||
if (runnable instanceof ISubscribeTask) {
|
|
||||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
|
||||||
subscribeTask.stop(null);
|
|
||||||
}
|
|
||||||
// 添加任务处理订阅过期
|
|
||||||
dynamicTask.stop(taskOverdueKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAllCatalogSubscribePlatform() {
|
public List<String> getAllCatalogSubscribePlatform(List<Platform> platformList) {
|
||||||
List<String> platforms = new ArrayList<>();
|
if (platformList == null || platformList.isEmpty()) {
|
||||||
if(catalogMap.size() > 0) {
|
return new ArrayList<>();
|
||||||
for (String key : catalogMap.keySet()) {
|
}
|
||||||
platforms.add(catalogMap.get(key).getId());
|
List<String> result = new ArrayList<>();
|
||||||
|
for (Platform platform : platformList) {
|
||||||
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "catalog", platform.getServerGBId());
|
||||||
|
if (redisTemplate.hasKey(key)) {
|
||||||
|
result.add(platform.getServerId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return platforms;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAllMobilePositionSubscribePlatform() {
|
public List<String> getAllMobilePositionSubscribePlatform(List<Platform> platformList) {
|
||||||
List<String> platforms = new ArrayList<>();
|
if (platformList == null || platformList.isEmpty()) {
|
||||||
if(!mobilePositionMap.isEmpty()) {
|
return new ArrayList<>();
|
||||||
for (String key : mobilePositionMap.keySet()) {
|
}
|
||||||
platforms.add(mobilePositionMap.get(key).getId());
|
List<String> result = new ArrayList<>();
|
||||||
|
for (Platform platform : platformList) {
|
||||||
|
String key = String.format("%s_%s_%s_%s", prefix, userSetting.getServerId(), "mobilePosition", platform.getServerGBId());
|
||||||
|
if (redisTemplate.hasKey(key)) {
|
||||||
|
result.add(platform.getServerId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return platforms;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAllSubscribe(String platformId) {
|
|
||||||
removeMobilePositionSubscribe(platformId);
|
|
||||||
removeCatalogSubscribe(platformId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,36 +1,19 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
|
||||||
import gov.nist.javax.sip.message.SIPResponse;
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.sip.header.*;
|
import javax.sip.header.EventHeader;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SubscribeInfo {
|
public class SubscribeInfo {
|
||||||
|
|
||||||
|
|
||||||
public SubscribeInfo(SIPRequest request, String id) {
|
|
||||||
this.id = id;
|
|
||||||
this.request = request;
|
|
||||||
this.expires = request.getExpires().getExpires();
|
|
||||||
EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
|
|
||||||
this.eventId = eventHeader.getEventId();
|
|
||||||
this.eventType = eventHeader.getEventType();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public SubscribeInfo() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private SIPRequest request;
|
|
||||||
private int expires;
|
private int expires;
|
||||||
private String eventId;
|
private String eventId;
|
||||||
private String eventType;
|
private String eventType;
|
||||||
private SIPResponse response;
|
private SipTransactionInfo transactionInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 以下为可选字段
|
* 以下为可选字段
|
||||||
@ -55,6 +38,16 @@ public class SubscribeInfo {
|
|||||||
private String simulatedCallId;
|
private String simulatedCallId;
|
||||||
|
|
||||||
|
|
||||||
|
public static SubscribeInfo getInstance(SIPResponse response, String id, int expires, EventHeader eventHeader){
|
||||||
|
SubscribeInfo subscribeInfo = new SubscribeInfo();
|
||||||
|
subscribeInfo.id = id;
|
||||||
|
subscribeInfo.transactionInfo = new SipTransactionInfo(response);
|
||||||
|
|
||||||
|
subscribeInfo.expires = expires;
|
||||||
|
subscribeInfo.eventId = eventHeader.getEventId();
|
||||||
|
subscribeInfo.eventType = eventHeader.getEventType();
|
||||||
|
return subscribeInfo;
|
||||||
|
}
|
||||||
public static SubscribeInfo buildSimulated(String platFormServerId, String platFormServerIp){
|
public static SubscribeInfo buildSimulated(String platFormServerId, String platFormServerIp){
|
||||||
SubscribeInfo subscribeInfo = new SubscribeInfo();
|
SubscribeInfo subscribeInfo = new SubscribeInfo();
|
||||||
subscribeInfo.setId(platFormServerId);
|
subscribeInfo.setId(platFormServerId);
|
||||||
|
|||||||
@ -11,9 +11,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
|
|||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
||||||
@ -40,9 +37,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Tag(name = "国标设备查询", description = "国标设备查询")
|
@Tag(name = "国标设备查询", description = "国标设备查询")
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@ -144,28 +138,10 @@ public class DeviceQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清除redis记录
|
// 清除redis记录
|
||||||
boolean isSuccess = deviceService.delete(deviceId);
|
deviceService.delete(deviceId);
|
||||||
if (isSuccess) {
|
JSONObject json = new JSONObject();
|
||||||
inviteStreamService.clearInviteInfo(deviceId);
|
json.put("deviceId", deviceId);
|
||||||
// 停止此设备的订阅更新
|
return json.toString();
|
||||||
Set<String> allKeys = dynamicTask.getAllKeys();
|
|
||||||
for (String key : allKeys) {
|
|
||||||
if (key.startsWith(deviceId)) {
|
|
||||||
Runnable runnable = dynamicTask.get(key);
|
|
||||||
if (runnable instanceof ISubscribeTask) {
|
|
||||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
|
||||||
subscribeTask.stop(null);
|
|
||||||
}
|
|
||||||
dynamicTask.stop(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("deviceId", deviceId);
|
|
||||||
return json.toString();
|
|
||||||
} else {
|
|
||||||
log.warn("设备信息删除API调用失败!");
|
|
||||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备信息删除API调用失败!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
@ -358,28 +334,6 @@ public class DeviceQuery {
|
|||||||
return wvpResult;
|
return wvpResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{deviceId}/subscribe_info")
|
|
||||||
@Operation(summary = "获取设备的订阅状态", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
|
||||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
|
||||||
public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) {
|
|
||||||
Set<String> allKeys = dynamicTask.getAllKeys();
|
|
||||||
Map<String, Integer> dialogStateMap = new HashMap<>();
|
|
||||||
for (String key : allKeys) {
|
|
||||||
if (key.startsWith(deviceId)) {
|
|
||||||
ISubscribeTask subscribeTask = (ISubscribeTask)dynamicTask.get(key);
|
|
||||||
if (subscribeTask instanceof CatalogSubscribeTask) {
|
|
||||||
dialogStateMap.put("catalog", 1);
|
|
||||||
}else if (subscribeTask instanceof MobilePositionSubscribeTask) {
|
|
||||||
dialogStateMap.put("mobilePosition", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WVPResult<Map<String, Integer>> wvpResult = new WVPResult<>();
|
|
||||||
wvpResult.setCode(0);
|
|
||||||
wvpResult.setData(dialogStateMap);
|
|
||||||
return wvpResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/snap/{deviceId}/{channelId}")
|
@GetMapping("/snap/{deviceId}/{channelId}")
|
||||||
@Operation(summary = "请求截图")
|
@Operation(summary = "请求截图")
|
||||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
|||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
import com.genersoft.iot.vmp.service.IMobilePositionService;
|
import com.genersoft.iot.vmp.service.IMobilePositionService;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||||
import com.github.pagehelper.util.StringUtil;
|
import com.github.pagehelper.util.StringUtil;
|
||||||
@ -37,10 +37,10 @@ public class MobilePositionController {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IMobilePositionService mobilePositionService;
|
private IMobilePositionService mobilePositionService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SIPCommander cmder;
|
private ISIPCommander cmder;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
|
|||||||
@ -123,23 +123,27 @@ public interface DeviceMapper {
|
|||||||
@Update(value = {" <script>" +
|
@Update(value = {" <script>" +
|
||||||
"UPDATE wvp_device " +
|
"UPDATE wvp_device " +
|
||||||
"SET update_time=#{updateTime}" +
|
"SET update_time=#{updateTime}" +
|
||||||
"<if test=\"name != null\">, name=#{name}</if>" +
|
", name=#{name}" +
|
||||||
"<if test=\"manufacturer != null\">, manufacturer=#{manufacturer}</if>" +
|
", manufacturer=#{manufacturer}" +
|
||||||
"<if test=\"model != null\">, model=#{model}</if>" +
|
", model=#{model}" +
|
||||||
"<if test=\"firmware != null\">, firmware=#{firmware}</if>" +
|
", firmware=#{firmware}" +
|
||||||
"<if test=\"transport != null\">, transport=#{transport}</if>" +
|
", transport=#{transport}" +
|
||||||
"<if test=\"ip != null\">, ip=#{ip}</if>" +
|
", ip=#{ip}" +
|
||||||
"<if test=\"localIp != null\">, local_ip=#{localIp}</if>" +
|
", local_ip=#{localIp}" +
|
||||||
"<if test=\"port != null\">, port=#{port}</if>" +
|
", port=#{port}" +
|
||||||
"<if test=\"hostAddress != null\">, host_address=#{hostAddress}</if>" +
|
", host_address=#{hostAddress}" +
|
||||||
"<if test=\"onLine != null\">, on_line=#{onLine}</if>" +
|
", on_line=#{onLine}" +
|
||||||
"<if test=\"registerTime != null\">, register_time=#{registerTime}</if>" +
|
", register_time=#{registerTime}" +
|
||||||
"<if test=\"keepaliveTime != null\">, keepalive_time=#{keepaliveTime}</if>" +
|
", keepalive_time=#{keepaliveTime}" +
|
||||||
"<if test=\"heartBeatInterval != null\">, heart_beat_interval=#{heartBeatInterval}</if>" +
|
", heart_beat_interval=#{heartBeatInterval}" +
|
||||||
"<if test=\"positionCapability != null\">, position_capability=#{positionCapability}</if>" +
|
", position_capability=#{positionCapability}" +
|
||||||
"<if test=\"heartBeatCount != null\">, heart_beat_count=#{heartBeatCount}</if>" +
|
", heart_beat_count=#{heartBeatCount}" +
|
||||||
"<if test=\"expires != null\">, expires=#{expires}</if>" +
|
", subscribe_cycle_for_catalog=#{subscribeCycleForCatalog}" +
|
||||||
"<if test=\"serverId != null\">, server_id=#{serverId}</if>" +
|
", subscribe_cycle_for_mobile_position=#{subscribeCycleForMobilePosition}" +
|
||||||
|
", mobile_position_submission_interval=#{mobilePositionSubmissionInterval}" +
|
||||||
|
", subscribe_cycle_for_alarm=#{subscribeCycleForAlarm}" +
|
||||||
|
", expires=#{expires}" +
|
||||||
|
", server_id=#{serverId}" +
|
||||||
"WHERE device_id=#{deviceId}"+
|
"WHERE device_id=#{deviceId}"+
|
||||||
" </script>"})
|
" </script>"})
|
||||||
int update(Device device);
|
int update(Device device);
|
||||||
|
|||||||
@ -78,7 +78,7 @@ public interface PlatformMapper {
|
|||||||
List<Platform> queryList(@Param("query") String query);
|
List<Platform> queryList(@Param("query") String query);
|
||||||
|
|
||||||
@Select("SELECT * FROM wvp_platform WHERE server_id=#{serverId} and enable=#{enable} ")
|
@Select("SELECT * FROM wvp_platform WHERE server_id=#{serverId} and enable=#{enable} ")
|
||||||
List<Platform> queryEnableParentPlatformList(@Param("serverId") String serverId, @Param("enable") boolean enable);
|
List<Platform> queryEnableParentPlatformListByServerId(@Param("serverId") String serverId, @Param("enable") boolean enable);
|
||||||
|
|
||||||
@Select("SELECT * FROM wvp_platform WHERE enable=true and as_message_channel=true")
|
@Select("SELECT * FROM wvp_platform WHERE enable=true and as_message_channel=true")
|
||||||
List<Platform> queryEnablePlatformListWithAsMessageChannel();
|
List<Platform> queryEnablePlatformListWithAsMessageChannel();
|
||||||
@ -89,12 +89,22 @@ public interface PlatformMapper {
|
|||||||
@Select("SELECT * FROM wvp_platform WHERE id=#{id}")
|
@Select("SELECT * FROM wvp_platform WHERE id=#{id}")
|
||||||
Platform query(int id);
|
Platform query(int id);
|
||||||
|
|
||||||
@Update("UPDATE wvp_platform SET status=#{online} WHERE server_gb_id=#{platformGbID}" )
|
@Update("UPDATE wvp_platform SET status=#{online} WHERE id=#{id}" )
|
||||||
int updateStatus(@Param("platformGbID") String platformGbID, @Param("online") boolean online);
|
int updateStatus(@Param("id") int id, @Param("online") boolean online);
|
||||||
|
|
||||||
@Select("SELECT server_id FROM wvp_platform WHERE enable=true and server_id != #{serverId} group by server_id")
|
@Select("SELECT server_id FROM wvp_platform WHERE enable=true and server_id != #{serverId} group by server_id")
|
||||||
List<String> queryServerIdsWithEnableAndNotInServer(@Param("serverId") String serverId);
|
List<String> queryServerIdsWithEnableAndNotInServer(@Param("serverId") String serverId);
|
||||||
|
|
||||||
@Select("SELECT * FROM wvp_platform WHERE server_id = #{serverId}")
|
@Select("SELECT * FROM wvp_platform WHERE server_id = #{serverId}")
|
||||||
List<Platform> queryByServerId(@Param("serverId") String serverId);
|
List<Platform> queryByServerId(@Param("serverId") String serverId);
|
||||||
|
|
||||||
|
@Select("SELECT * FROM wvp_platform ")
|
||||||
|
List<Platform> queryAll();
|
||||||
|
|
||||||
|
@Select("SELECT * FROM wvp_platform WHERE enable=true and server_id = #{serverId}")
|
||||||
|
List<Platform> queryServerIdsWithEnableAndServer(@Param("serverId") String serverId);
|
||||||
|
|
||||||
|
@Update("UPDATE wvp_platform SET status=false" )
|
||||||
|
void offlineAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.event.sip;
|
package com.genersoft.iot.vmp.gb28181.event.sip;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -27,6 +28,8 @@ public class SipEvent implements Delayed {
|
|||||||
*/
|
*/
|
||||||
private long delay;
|
private long delay;
|
||||||
|
|
||||||
|
private SipTransactionInfo sipTransactionInfo;
|
||||||
|
|
||||||
public static SipEvent getInstance(String key, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, long delay) {
|
public static SipEvent getInstance(String key, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent, long delay) {
|
||||||
SipEvent sipEvent = new SipEvent();
|
SipEvent sipEvent = new SipEvent();
|
||||||
sipEvent.setKey(key);
|
sipEvent.setKey(key);
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
|
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
|
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -26,6 +27,9 @@ import java.util.Map;
|
|||||||
@Component
|
@Component
|
||||||
public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlatformService platformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPlatformChannelService platformChannelService;
|
private IPlatformChannelService platformChannelService;
|
||||||
|
|
||||||
@ -50,8 +54,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}else {
|
}else {
|
||||||
|
List<Platform> allPlatform = platformService.queryAll();
|
||||||
// 获取所用订阅
|
// 获取所用订阅
|
||||||
List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform();
|
List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform(allPlatform);
|
||||||
if (event.getChannels() != null) {
|
if (event.getChannels() != null) {
|
||||||
if (!platforms.isEmpty()) {
|
if (!platforms.isEmpty()) {
|
||||||
for (CommonGBChannel deviceChannel : event.getChannels()) {
|
for (CommonGBChannel deviceChannel : event.getChannels()) {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
|
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
|
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderForPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderForPlatform;
|
||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -24,6 +25,9 @@ import java.util.List;
|
|||||||
@Component
|
@Component
|
||||||
public class MobilePositionEventLister implements ApplicationListener<MobilePositionEvent> {
|
public class MobilePositionEventLister implements ApplicationListener<MobilePositionEvent> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlatformService platformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPlatformChannelService platformChannelService;
|
private IPlatformChannelService platformChannelService;
|
||||||
|
|
||||||
@ -38,9 +42,9 @@ public class MobilePositionEventLister implements ApplicationListener<MobilePosi
|
|||||||
if (event.getMobilePosition().getChannelId() == 0) {
|
if (event.getMobilePosition().getChannelId() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
List<Platform> allPlatforms = platformService.queryAll();
|
||||||
// 获取所用订阅
|
// 获取所用订阅
|
||||||
List<String> platforms = subscribeHolder.getAllMobilePositionSubscribePlatform();
|
List<String> platforms = subscribeHolder.getAllMobilePositionSubscribePlatform(allPlatforms);
|
||||||
if (platforms.isEmpty()) {
|
if (platforms.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -65,4 +69,3 @@ public class MobilePositionEventLister implements ApplicationListener<MobilePosi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ public interface IDeviceService {
|
|||||||
* @param device 设备信息
|
* @param device 设备信息
|
||||||
* @return 布尔
|
* @return 布尔
|
||||||
*/
|
*/
|
||||||
boolean addCatalogSubscribe(Device device);
|
boolean addCatalogSubscribe(Device device, SipTransactionInfo transactionInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除目录订阅
|
* 移除目录订阅
|
||||||
@ -46,7 +46,7 @@ public interface IDeviceService {
|
|||||||
* @param device 设备信息
|
* @param device 设备信息
|
||||||
* @return 布尔
|
* @return 布尔
|
||||||
*/
|
*/
|
||||||
boolean addMobilePositionSubscribe(Device device);
|
boolean addMobilePositionSubscribe(Device device, SipTransactionInfo transactionInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除移动位置订阅
|
* 移除移动位置订阅
|
||||||
|
|||||||
@ -48,4 +48,6 @@ public interface IPlatformChannelService {
|
|||||||
void checkRegionAdd(List<CommonGBChannel> channelList);
|
void checkRegionAdd(List<CommonGBChannel> channelList);
|
||||||
|
|
||||||
void checkRegionRemove(List<CommonGBChannel> channelList, List<Region> regionList);
|
void checkRegionRemove(List<CommonGBChannel> channelList, List<Region> regionList);
|
||||||
|
|
||||||
|
List<Platform> queryByPlatformBySharChannelId(String gbId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,13 +53,7 @@ public interface IPlatformService {
|
|||||||
* 平台离线
|
* 平台离线
|
||||||
* @param parentPlatform 平台信息
|
* @param parentPlatform 平台信息
|
||||||
*/
|
*/
|
||||||
void offline(Platform parentPlatform, boolean stopRegisterTask);
|
void offline(Platform parentPlatform);
|
||||||
|
|
||||||
/**
|
|
||||||
* 向上级平台发起注册
|
|
||||||
* @param parentPlatform
|
|
||||||
*/
|
|
||||||
void login(Platform parentPlatform);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向上级平台发送位置订阅
|
* 向上级平台发送位置订阅
|
||||||
@ -85,4 +79,7 @@ public interface IPlatformService {
|
|||||||
List<Platform> queryEnablePlatformList(String serverId);
|
List<Platform> queryEnablePlatformList(String serverId);
|
||||||
|
|
||||||
void delete(Integer platformId, CommonCallback<Object> callback);
|
void delete(Integer platformId, CommonCallback<Object> callback);
|
||||||
|
|
||||||
|
List<Platform> queryAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,9 +15,11 @@ import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
|||||||
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
|
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.SubscribeTask;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.SubscribeTaskInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.SubscribeTaskRunner;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.impl.SubscribeTaskForCatalog;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.impl.SubscribeTaskForMobilPosition;
|
||||||
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.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
|
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
|
||||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||||
@ -32,13 +34,18 @@ import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
|
|||||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
|
import javax.sip.ResponseEvent;
|
||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
@ -53,7 +60,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class DeviceServiceImpl implements IDeviceService {
|
@Order(value=16)
|
||||||
|
public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DynamicTask dynamicTask;
|
private DynamicTask dynamicTask;
|
||||||
@ -100,10 +108,46 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IRedisRpcService redisRpcService;
|
private IRedisRpcService redisRpcService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SubscribeTaskRunner subscribeTaskRunner;
|
||||||
|
|
||||||
private Device getDeviceByDeviceIdFromDb(String deviceId) {
|
private Device getDeviceByDeviceIdFromDb(String deviceId) {
|
||||||
return deviceMapper.getDeviceByDeviceId(deviceId);
|
return deviceMapper.getDeviceByDeviceId(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
// TODO 处理设备离线
|
||||||
|
|
||||||
|
// 处理订阅任务
|
||||||
|
List<SubscribeTaskInfo> taskInfoList = subscribeTaskRunner.getAllTaskInfo();
|
||||||
|
if (!taskInfoList.isEmpty()) {
|
||||||
|
for (SubscribeTaskInfo taskInfo : taskInfoList) {
|
||||||
|
if (taskInfo == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Device device = getDeviceByDeviceId(taskInfo.getDeviceId());
|
||||||
|
if (device == null || !device.isOnLine()) {
|
||||||
|
subscribeTaskRunner.removeSubscribe(taskInfo.getKey());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (SubscribeTaskForCatalog.name.equals(taskInfo.getName())) {
|
||||||
|
device.setSubscribeCycleForCatalog((int)taskInfo.getExpireTime());
|
||||||
|
SubscribeTask subscribeTask = SubscribeTaskForCatalog.getInstance(device, this::catalogSubscribeExpire, taskInfo.getTransactionInfo());
|
||||||
|
if (subscribeTask != null) {
|
||||||
|
subscribeTaskRunner.addSubscribe(subscribeTask);
|
||||||
|
}
|
||||||
|
}else if (SubscribeTaskForMobilPosition.name.equals(taskInfo.getName())) {
|
||||||
|
device.setSubscribeCycleForMobilePosition((int)taskInfo.getExpireTime());
|
||||||
|
SubscribeTask subscribeTask = SubscribeTaskForMobilPosition.getInstance(device, this::mobilPositionSubscribeExpire, taskInfo.getTransactionInfo());
|
||||||
|
if (subscribeTask != null) {
|
||||||
|
subscribeTaskRunner.addSubscribe(subscribeTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void online(Device device, SipTransactionInfo sipTransactionInfo) {
|
public void online(Device device, SipTransactionInfo sipTransactionInfo) {
|
||||||
log.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort());
|
log.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort());
|
||||||
@ -164,12 +208,12 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
// TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
|
// TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
|
||||||
}
|
}
|
||||||
// 上线添加订阅
|
// 上线添加订阅
|
||||||
if (device.getSubscribeCycleForCatalog() > 0) {
|
if (device.getSubscribeCycleForCatalog() > 0 && !subscribeTaskRunner.containsKey(SubscribeTaskForCatalog.getKey(device))) {
|
||||||
// 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
|
// 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
|
||||||
addCatalogSubscribe(device);
|
addCatalogSubscribe(device, null);
|
||||||
}
|
}
|
||||||
if (device.getSubscribeCycleForMobilePosition() > 0) {
|
if (device.getSubscribeCycleForMobilePosition() > 0 && !subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
||||||
addMobilePositionSubscribe(device);
|
addMobilePositionSubscribe(device, null);
|
||||||
}
|
}
|
||||||
if (userSetting.getDeviceStatusNotify()) {
|
if (userSetting.getDeviceStatusNotify()) {
|
||||||
// 发送redis消息
|
// 发送redis消息
|
||||||
@ -254,98 +298,173 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// 订阅丢失检查
|
||||||
public boolean addCatalogSubscribe(Device device) {
|
@Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
|
||||||
if (device == null || device.getSubscribeCycleForCatalog() < 0) {
|
public void lostCheck(){
|
||||||
return false;
|
// 获取所有设备
|
||||||
|
List<Device> deviceList = redisCatchStorage.getAllDevices();
|
||||||
|
if (deviceList.isEmpty()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
log.info("[添加目录订阅] 设备{}", device.getDeviceId());
|
for (Device device : deviceList) {
|
||||||
// 添加目录订阅
|
if (device == null || !device.isOnLine()) {
|
||||||
CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander, dynamicTask);
|
continue;
|
||||||
// 刷新订阅
|
}
|
||||||
int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
|
if (device.getSubscribeCycleForCatalog() > 0 && !subscribeTaskRunner.containsKey(SubscribeTaskForCatalog.getKey(device))) {
|
||||||
// 设置最小值为30
|
log.info("[订阅丢失] 目录订阅, 编号: {}, 重新发起订阅", device.getDeviceId());
|
||||||
dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000);
|
addCatalogSubscribe(device, null);
|
||||||
|
}
|
||||||
|
if (device.getSubscribeCycleForMobilePosition() > 0 && !subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
||||||
|
log.info("[订阅丢失] 移动位置订阅, 编号: {}, 重新发起订阅", device.getDeviceId());
|
||||||
|
addMobilePositionSubscribe(device, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
catalogSubscribeTask.run();
|
private void catalogSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
||||||
return true;
|
log.info("[目录订阅] 到期, 编号: {}", deviceId);
|
||||||
|
Device device = getDeviceByDeviceId(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
log.info("[目录订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (device.getSubscribeCycleForCatalog() > 0) {
|
||||||
|
addCatalogSubscribe(device, transactionInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mobilPositionSubscribeExpire(String deviceId, SipTransactionInfo transactionInfo) {
|
||||||
|
log.info("[移动位置订阅] 到期, 编号: {}", deviceId);
|
||||||
|
Device device = getDeviceByDeviceId(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
log.info("[移动位置订阅] 到期, 编号: {}, 设备不存在, 忽略", deviceId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (device.getSubscribeCycleForMobilePosition() > 0) {
|
||||||
|
addMobilePositionSubscribe(device, transactionInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback) {
|
public boolean addCatalogSubscribe(@NotNull Device device, SipTransactionInfo transactionInfo) {
|
||||||
if (device == null || device.getSubscribeCycleForCatalog() < 0) {
|
if (device == null || device.getSubscribeCycleForCatalog() < 0) {
|
||||||
if (callback != null) {
|
|
||||||
callback.run(false);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
log.info("[移除目录订阅]: {}", device.getDeviceId());
|
log.info("[添加目录订阅] 设备 {}", device.getDeviceId());
|
||||||
String taskKey = device.getDeviceId() + "catalog";
|
try {
|
||||||
if (device.isOnLine()) {
|
sipCommander.catalogSubscribe(device, transactionInfo, eventResult -> {
|
||||||
Runnable runnable = dynamicTask.get(taskKey);
|
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||||
if (runnable instanceof ISubscribeTask) {
|
// 成功
|
||||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
log.info("[目录订阅]成功: {}", device.getDeviceId());
|
||||||
subscribeTask.stop(callback);
|
if (!subscribeTaskRunner.containsKey(SubscribeTaskForCatalog.getKey(device))) {
|
||||||
}else {
|
SIPResponse response = (SIPResponse) event.getResponse();
|
||||||
log.info("[移除目录订阅]失败,未找到订阅任务 : {}", device.getDeviceId());
|
SipTransactionInfo transactionInfoForResonse = new SipTransactionInfo(response);
|
||||||
if (callback != null) {
|
SubscribeTask subscribeTask = SubscribeTaskForCatalog.getInstance(device, this::catalogSubscribeExpire, transactionInfoForResonse);
|
||||||
callback.run(false);
|
if (subscribeTask != null) {
|
||||||
|
subscribeTaskRunner.addSubscribe(subscribeTask);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
subscribeTaskRunner.updateDelay(SubscribeTaskForCatalog.getKey(device), (device.getSubscribeCycleForCatalog() * 1000L - 500L) + System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}else {
|
},eventResult -> {
|
||||||
log.info("[移除目录订阅订阅]失败,设备已经离线 : {}", device.getDeviceId());
|
// 失败
|
||||||
if (callback != null) {
|
log.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||||
callback.run(false);
|
});
|
||||||
}
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
|
log.error("[命令发送失败] 目录订阅: {}", e.getMessage());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
dynamicTask.stop(taskKey);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addMobilePositionSubscribe(Device device) {
|
public boolean removeCatalogSubscribe(@NotNull Device device, CommonCallback<Boolean> callback) {
|
||||||
if (device == null || device.getSubscribeCycleForMobilePosition() < 0) {
|
log.info("[移除目录订阅]: {}", device.getDeviceId());
|
||||||
|
String key = SubscribeTaskForCatalog.getKey(device);
|
||||||
|
if (subscribeTaskRunner.containsKey(key)) {
|
||||||
|
SipTransactionInfo transactionInfo = subscribeTaskRunner.getTransactionInfo(key);
|
||||||
|
if (transactionInfo == null) {
|
||||||
|
log.warn("[移除目录订阅] 未找到事务信息,{}", device.getDeviceId());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
device.setSubscribeCycleForCatalog(0);
|
||||||
|
sipCommander.catalogSubscribe(device, transactionInfo, eventResult -> {
|
||||||
|
// 成功
|
||||||
|
log.info("[取消目录订阅]成功: {}", device.getDeviceId());
|
||||||
|
subscribeTaskRunner.removeSubscribe(SubscribeTaskForCatalog.getKey(device));
|
||||||
|
if (callback != null) {
|
||||||
|
callback.run(true);
|
||||||
|
}
|
||||||
|
},eventResult -> {
|
||||||
|
// 失败
|
||||||
|
log.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||||
|
});
|
||||||
|
}catch (Exception e) {
|
||||||
|
// 失败
|
||||||
|
log.warn("[取消目录订阅]失败: {}-{} ", device.getDeviceId(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addMobilePositionSubscribe(@NotNull Device device, SipTransactionInfo transactionInfo) {
|
||||||
|
log.info("[添加移动位置订阅] 设备 {}", device.getDeviceId());
|
||||||
|
try {
|
||||||
|
sipCommander.mobilePositionSubscribe(device, transactionInfo, eventResult -> {
|
||||||
|
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||||
|
// 成功
|
||||||
|
log.info("[移动位置订阅]成功: {}", device.getDeviceId());
|
||||||
|
if (!subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
||||||
|
SIPResponse response = (SIPResponse) event.getResponse();
|
||||||
|
SipTransactionInfo transactionInfoForResonse = new SipTransactionInfo(response);
|
||||||
|
SubscribeTask subscribeTask = SubscribeTaskForMobilPosition.getInstance(device, this::catalogSubscribeExpire, transactionInfoForResonse);
|
||||||
|
if (subscribeTask != null) {
|
||||||
|
subscribeTaskRunner.addSubscribe(subscribeTask);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
subscribeTaskRunner.updateDelay(SubscribeTaskForMobilPosition.getKey(device), (device.getSubscribeCycleForCatalog() * 1000L - 500L) + System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
},eventResult -> {
|
||||||
|
// 失败
|
||||||
|
log.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||||
|
});
|
||||||
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
|
log.error("[命令发送失败] 移动位置订阅: {}", e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
log.info("[添加移动位置订阅] 设备{}", device.getDeviceId());
|
|
||||||
// 添加目录订阅
|
|
||||||
MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander, dynamicTask);
|
|
||||||
// 设置最小值为30
|
|
||||||
int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
|
|
||||||
// 刷新订阅
|
|
||||||
dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog * 1000);
|
|
||||||
mobilePositionSubscribeTask.run();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback) {
|
public boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback) {
|
||||||
if (device == null || device.getSubscribeCycleForCatalog() < 0) {
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
log.info("[移除移动位置订阅]: {}", device.getDeviceId());
|
log.info("[移除移动位置订阅]: {}", device.getDeviceId());
|
||||||
String taskKey = device.getDeviceId() + "mobile_position";
|
String key = SubscribeTaskForMobilPosition.getKey(device);
|
||||||
if (device.isOnLine()) {
|
if (subscribeTaskRunner.containsKey(key)) {
|
||||||
Runnable runnable = dynamicTask.get(taskKey);
|
SipTransactionInfo transactionInfo = subscribeTaskRunner.getTransactionInfo(key);
|
||||||
if (runnable instanceof ISubscribeTask) {
|
if (transactionInfo == null) {
|
||||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
log.warn("[移除移动位置订阅] 未找到事务信息,{}", device.getDeviceId());
|
||||||
subscribeTask.stop(callback);
|
|
||||||
}else {
|
|
||||||
log.info("[移除移动位置订阅]失败,未找到订阅任务 : {}", device.getDeviceId());
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}else {
|
try {
|
||||||
log.info("[移除移动位置订阅]失败,设备已经离线 : {}", device.getDeviceId());
|
device.setSubscribeCycleForMobilePosition(0);
|
||||||
if (callback != null) {
|
sipCommander.mobilePositionSubscribe(device, transactionInfo, eventResult -> {
|
||||||
callback.run(false);
|
// 成功
|
||||||
|
log.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
|
||||||
|
subscribeTaskRunner.removeSubscribe(SubscribeTaskForMobilPosition.getKey(device));
|
||||||
|
if (callback != null) {
|
||||||
|
callback.run(true);
|
||||||
|
}
|
||||||
|
},eventResult -> {
|
||||||
|
// 失败
|
||||||
|
log.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||||
|
});
|
||||||
|
}catch (Exception e) {
|
||||||
|
// 失败
|
||||||
|
log.warn("[取消移动位置订阅]失败: {}-{} ", device.getDeviceId(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dynamicTask.stop(taskKey);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,10 +618,20 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
public boolean delete(String deviceId) {
|
public boolean delete(String deviceId) {
|
||||||
Device device = getDeviceByDeviceIdFromDb(deviceId);
|
Device device = getDeviceByDeviceIdFromDb(deviceId);
|
||||||
Assert.notNull(device, "未找到设备");
|
Assert.notNull(device, "未找到设备");
|
||||||
|
if (subscribeTaskRunner.containsKey(SubscribeTaskForCatalog.getKey(device))) {
|
||||||
|
removeCatalogSubscribe(device, null);
|
||||||
|
}
|
||||||
|
if (subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
||||||
|
removeMobilePositionSubscribe(device, null);
|
||||||
|
}
|
||||||
|
// 停止状态检测
|
||||||
|
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||||
|
dynamicTask.stop(registerExpireTaskKey);
|
||||||
platformChannelMapper.delChannelForDeviceId(deviceId);
|
platformChannelMapper.delChannelForDeviceId(deviceId);
|
||||||
deviceChannelMapper.cleanChannelsByDeviceId(device.getId());
|
deviceChannelMapper.cleanChannelsByDeviceId(device.getId());
|
||||||
deviceMapper.del(deviceId);
|
deviceMapper.del(deviceId);
|
||||||
redisCatchStorage.removeDevice(deviceId);
|
redisCatchStorage.removeDevice(deviceId);
|
||||||
|
inviteStreamService.clearInviteInfo(deviceId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,20 +691,17 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
// 订阅周期不同,则先取消
|
// 订阅周期不同,则先取消
|
||||||
removeCatalogSubscribe(device, result->{
|
removeCatalogSubscribe(device, result->{
|
||||||
device.setSubscribeCycleForCatalog(cycle);
|
device.setSubscribeCycleForCatalog(cycle);
|
||||||
|
updateDevice(device);
|
||||||
if (cycle > 0) {
|
if (cycle > 0) {
|
||||||
// 开启订阅
|
// 开启订阅
|
||||||
addCatalogSubscribe(device);
|
addCatalogSubscribe(device, null);
|
||||||
}
|
}
|
||||||
// 因为是异步执行,需要在这里更新下数据
|
|
||||||
deviceMapper.updateSubscribeCatalog(device);
|
|
||||||
redisCatchStorage.updateDevice(device);
|
|
||||||
});
|
});
|
||||||
}else {
|
}else {
|
||||||
// 开启订阅
|
// 开启订阅
|
||||||
device.setSubscribeCycleForCatalog(cycle);
|
device.setSubscribeCycleForCatalog(cycle);
|
||||||
addCatalogSubscribe(device);
|
updateDevice(device);
|
||||||
deviceMapper.updateSubscribeCatalog(device);
|
addCatalogSubscribe(device, null);
|
||||||
redisCatchStorage.updateDevice(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,6 +709,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
public void subscribeMobilePosition(int id, int cycle, int interval) {
|
public void subscribeMobilePosition(int id, int cycle, int interval) {
|
||||||
Device device = deviceMapper.query(id);
|
Device device = deviceMapper.query(id);
|
||||||
Assert.notNull(device, "未找到设备");
|
Assert.notNull(device, "未找到设备");
|
||||||
|
|
||||||
if (device.getSubscribeCycleForMobilePosition() == cycle) {
|
if (device.getSubscribeCycleForMobilePosition() == cycle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -598,21 +725,16 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
device.setSubscribeCycleForMobilePosition(cycle);
|
device.setSubscribeCycleForMobilePosition(cycle);
|
||||||
device.setMobilePositionSubmissionInterval(interval);
|
device.setMobilePositionSubmissionInterval(interval);
|
||||||
if (cycle > 0) {
|
if (cycle > 0) {
|
||||||
addMobilePositionSubscribe(device);
|
addMobilePositionSubscribe(device, null);
|
||||||
}
|
}
|
||||||
// 因为是异步执行,需要在这里更新下数据
|
|
||||||
deviceMapper.updateSubscribeMobilePosition(device);
|
|
||||||
redisCatchStorage.updateDevice(device);
|
|
||||||
});
|
});
|
||||||
}else {
|
}else {
|
||||||
// 订阅未开启
|
// 订阅未开启
|
||||||
device.setSubscribeCycleForMobilePosition(cycle);
|
device.setSubscribeCycleForMobilePosition(cycle);
|
||||||
device.setMobilePositionSubmissionInterval(interval);
|
device.setMobilePositionSubmissionInterval(interval);
|
||||||
|
updateDevice(device);
|
||||||
// 开启订阅
|
// 开启订阅
|
||||||
addMobilePositionSubscribe(device);
|
addMobilePositionSubscribe(device, null);
|
||||||
// 因为是异步执行,需要在这里更新下数据
|
|
||||||
deviceMapper.updateSubscribeMobilePosition(device);
|
|
||||||
redisCatchStorage.updateDevice(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -601,4 +601,12 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
|
|||||||
public List<CommonGBChannel> queryChannelByPlatformIdAndChannelIds(Integer platformId, List<Integer> channelIds) {
|
public List<CommonGBChannel> queryChannelByPlatformIdAndChannelIds(Integer platformId, List<Integer> channelIds) {
|
||||||
return platformChannelMapper.queryShare(platformId, channelIds);
|
return platformChannelMapper.queryShare(platformId, channelIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Platform> queryByPlatformBySharChannelId(String channelDeviceId) {
|
||||||
|
CommonGBChannel commonGBChannel = commonGBChannelMapper.queryByDeviceId(channelDeviceId);
|
||||||
|
ArrayList<Integer> ids = new ArrayList<>();
|
||||||
|
ids.add(commonGBChannel.getGbId());
|
||||||
|
return platformChannelMapper.queryPlatFormListByChannelList(ids);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
|
||||||
import com.genersoft.iot.vmp.common.*;
|
import com.genersoft.iot.vmp.common.*;
|
||||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
@ -15,6 +14,10 @@ import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
|||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.platformStatus.PlatformKeepaliveTask;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.platformStatus.PlatformRegisterTask;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.platformStatus.PlatformRegisterTaskInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.platformStatus.PlatformStatusTaskRunner;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||||
@ -28,13 +31,14 @@ import com.genersoft.iot.vmp.service.ISendRtpServerService;
|
|||||||
import com.genersoft.iot.vmp.service.bean.*;
|
import com.genersoft.iot.vmp.service.bean.*;
|
||||||
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import gov.nist.javax.sip.message.SIPResponse;
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -56,7 +60,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class PlatformServiceImpl implements IPlatformService {
|
@Order(value=15)
|
||||||
|
public class PlatformServiceImpl implements IPlatformService, CommandLineRunner {
|
||||||
|
|
||||||
private final static String REGISTER_KEY_PREFIX = "platform_register_";
|
private final static String REGISTER_KEY_PREFIX = "platform_register_";
|
||||||
|
|
||||||
@ -69,7 +74,6 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SSRCFactory ssrcFactory;
|
private SSRCFactory ssrcFactory;
|
||||||
|
|
||||||
@ -109,6 +113,74 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISendRtpServerService sendRtpServerService;
|
private ISendRtpServerService sendRtpServerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlatformStatusTaskRunner statusTaskRunner;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
// 启动时 如果存在未过期的注册平台,则发送注销
|
||||||
|
List<PlatformRegisterTaskInfo> registerTaskInfoList = statusTaskRunner.getAllRegisterTaskInfo();
|
||||||
|
if (registerTaskInfoList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (PlatformRegisterTaskInfo taskInfo : registerTaskInfoList) {
|
||||||
|
log.info("[国标级联] 启动服务是发现平台注册仍在有效期,注销: {}", taskInfo.getPlatformServerId());
|
||||||
|
Platform platform = queryPlatformByServerGBId(taskInfo.getPlatformServerId());
|
||||||
|
if (platform == null) {
|
||||||
|
statusTaskRunner.removeRegisterTask(taskInfo.getPlatformServerId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sendUnRegister(platform, taskInfo.getSipTransactionInfo());
|
||||||
|
}
|
||||||
|
// 启动时所有平台默认离线
|
||||||
|
platformMapper.offlineAll();
|
||||||
|
}
|
||||||
|
@Scheduled(fixedDelay = 20, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
|
||||||
|
public void statusLostCheck(){
|
||||||
|
// 每隔20秒检测,是否存在启用但是未注册的平台,存在则发起注册
|
||||||
|
// 获取所有在线并且启用的平台
|
||||||
|
List<Platform> platformList = platformMapper.queryServerIdsWithEnableAndServer(userSetting.getServerId());
|
||||||
|
if (platformList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Platform platform : platformList) {
|
||||||
|
if (statusTaskRunner.containsRegister(platform.getServerGBId()) && statusTaskRunner.containsKeepAlive(platform.getServerGBId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (statusTaskRunner.containsRegister(platform.getServerGBId())) {
|
||||||
|
SipTransactionInfo transactionInfo = statusTaskRunner.getRegisterTransactionInfo(platform.getServerGBId());
|
||||||
|
// 注销后出发平台离线, 如果是启用的平台,那么下次丢失检测会检测到并重新注册上线
|
||||||
|
sendUnRegister(platform, transactionInfo);
|
||||||
|
}else {
|
||||||
|
statusTaskRunner.removeKeepAliveTask(platform.getServerGBId());
|
||||||
|
sendRegister(platform, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendRegister(Platform platform, SipTransactionInfo sipTransactionInfo) {
|
||||||
|
try {
|
||||||
|
commanderForPlatform.register(platform, sipTransactionInfo, eventResult -> {
|
||||||
|
log.info("[国标级联] {}({}),注册失败", platform.getName(), platform.getServerGBId());
|
||||||
|
offline(platform);
|
||||||
|
}, null);
|
||||||
|
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||||
|
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendUnRegister(Platform platform, SipTransactionInfo sipTransactionInfo) {
|
||||||
|
statusTaskRunner.removeRegisterTask(platform.getServerGBId());
|
||||||
|
statusTaskRunner.removeKeepAliveTask(platform.getServerGBId());
|
||||||
|
try {
|
||||||
|
commanderForPlatform.unregister(platform, sipTransactionInfo, null, eventResult -> {
|
||||||
|
log.info("[国标级联] 注销成功, 平台:{}", platform.getServerGBId());
|
||||||
|
});
|
||||||
|
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||||
|
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 定时监听国标级联所进行的WVP服务是否正常, 如果异常则选择新的wvp执行
|
// 定时监听国标级联所进行的WVP服务是否正常, 如果异常则选择新的wvp执行
|
||||||
@Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
|
@Scheduled(fixedDelay = 2, timeUnit = TimeUnit.SECONDS) //每3秒执行一次
|
||||||
public void execute(){
|
public void execute(){
|
||||||
@ -139,20 +211,26 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
platform.setAddress(getIpWithSameNetwork(platform.getAddress()));
|
platform.setAddress(getIpWithSameNetwork(platform.getAddress()));
|
||||||
platform.setServerId(userSetting.getServerId());
|
platform.setServerId(userSetting.getServerId());
|
||||||
platformMapper.update(platform);
|
platformMapper.update(platform);
|
||||||
// 更新redis
|
// 检查就平台是否注册到期,没有则注销,由本平台重新注册
|
||||||
redisCatchStorage.delPlatformCatchInfo(platform.getServerGBId());
|
List<PlatformRegisterTaskInfo> taskInfoList = statusTaskRunner.getRegisterTransactionInfoByServerId(serverId);
|
||||||
PlatformCatch platformCatch = new PlatformCatch();
|
boolean needUnregister = false;
|
||||||
platformCatch.setPlatform(platform);
|
SipTransactionInfo sipTransactionInfo = null;
|
||||||
platformCatch.setId(platform.getServerGBId());
|
if (!taskInfoList.isEmpty()) {
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
for (PlatformRegisterTaskInfo taskInfo : taskInfoList) {
|
||||||
// 开始注册
|
if (taskInfo.getPlatformServerId().equals(platform.getServerGBId())
|
||||||
// 注册成功时由程序直接调用了online方法
|
&& taskInfo.getSipTransactionInfo() != null) {
|
||||||
try {
|
needUnregister = true;
|
||||||
commanderForPlatform.register(platform, eventResult -> {
|
sipTransactionInfo = taskInfo.getSipTransactionInfo();
|
||||||
log.info("[国标级联] {}({}),添加向上级注册失败,请确定上级平台可用时重新保存", platform.getName(), platform.getServerGBId());
|
break;
|
||||||
}, null);
|
}
|
||||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
}
|
||||||
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
|
}
|
||||||
|
if (needUnregister) {
|
||||||
|
sendUnRegister(platform, sipTransactionInfo);
|
||||||
|
}else {
|
||||||
|
// 开始注册
|
||||||
|
// 注册成功时由程序直接调用了online方法
|
||||||
|
sendRegister(platform, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -265,25 +343,17 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
}
|
}
|
||||||
platform.setServerId(userSetting.getServerId());
|
platform.setServerId(userSetting.getServerId());
|
||||||
int result = platformMapper.add(platform);
|
int result = platformMapper.add(platform);
|
||||||
// 添加缓存
|
|
||||||
PlatformCatch platformCatch = new PlatformCatch();
|
|
||||||
platformCatch.setPlatform(platform);
|
|
||||||
platformCatch.setId(platform.getServerGBId());
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
|
||||||
if (platform.isEnable()) {
|
if (platform.isEnable()) {
|
||||||
// 保存时启用就发送注册
|
// 保存时启用就发送注册
|
||||||
// 注册成功时由程序直接调用了online方法
|
// 注册成功时由程序直接调用了online方法
|
||||||
try {
|
sendRegister(platform, null);
|
||||||
commanderForPlatform.register(platform, eventResult -> {
|
|
||||||
log.info("[国标级联] {}({}),添加向上级注册失败,请确定上级平台可用时重新保存", platform.getName(), platform.getServerGBId());
|
|
||||||
}, null);
|
|
||||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
|
||||||
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result > 0;
|
return result > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean update(Platform platform) {
|
public boolean update(Platform platform) {
|
||||||
Assert.isTrue(platform.getId() > 0, "ID必须存在");
|
Assert.isTrue(platform.getId() > 0, "ID必须存在");
|
||||||
@ -294,52 +364,15 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
if (!userSetting.getServerId().equals(platformInDb.getServerId())) {
|
if (!userSetting.getServerId().equals(platformInDb.getServerId())) {
|
||||||
return redisRpcService.updatePlatform(platformInDb.getServerId(), platform);
|
return redisRpcService.updatePlatform(platformInDb.getServerId(), platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformCatch platformCatchOld = redisCatchStorage.queryPlatformCatchInfo(platformInDb.getServerGBId());
|
|
||||||
platform.setUpdateTime(DateUtil.getNow());
|
|
||||||
|
|
||||||
// 停止心跳定时
|
|
||||||
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + platformInDb.getServerGBId();
|
|
||||||
dynamicTask.stop(keepaliveTaskKey);
|
|
||||||
// 停止注册定时
|
|
||||||
final String registerTaskKey = REGISTER_KEY_PREFIX + platformInDb.getServerGBId();
|
|
||||||
dynamicTask.stop(registerTaskKey);
|
|
||||||
// 注销旧的
|
|
||||||
try {
|
|
||||||
if (platformInDb.isStatus() && platformCatchOld != null) {
|
|
||||||
log.info("保存平台{}时发现旧平台在线,发送注销命令", platformInDb.getServerGBId());
|
|
||||||
commanderForPlatform.unregister(platformInDb, platformCatchOld.getSipTransactionInfo(), null, eventResult -> {
|
|
||||||
log.info("[国标级联] 注销成功, 平台:{}", platformInDb.getServerGBId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
|
||||||
log.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新数据库
|
// 更新数据库
|
||||||
if (platform.getCatalogGroup() == 0) {
|
if (platform.getCatalogGroup() == 0) {
|
||||||
platform.setCatalogGroup(1);
|
platform.setCatalogGroup(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
platformMapper.update(platform);
|
platformMapper.update(platform);
|
||||||
// 更新redis
|
if (statusTaskRunner.containsRegister(platformInDb.getServerGBId())) {
|
||||||
redisCatchStorage.delPlatformCatchInfo(platformInDb.getServerGBId());
|
SipTransactionInfo transactionInfo = statusTaskRunner.getRegisterTransactionInfo(platformInDb.getServerGBId());
|
||||||
PlatformCatch platformCatch = new PlatformCatch();
|
// 注销后出发平台离线, 如果是启用的平台,那么下次丢失检测会检测到并重新注册上线
|
||||||
platformCatch.setPlatform(platform);
|
sendUnRegister(platformInDb, transactionInfo);
|
||||||
platformCatch.setId(platform.getServerGBId());
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
|
||||||
// 注册
|
|
||||||
if (platform.isEnable()) {
|
|
||||||
// 保存时启用就发送注册
|
|
||||||
// 注册成功时由程序直接调用了online方法
|
|
||||||
try {
|
|
||||||
log.info("[国标级联] 平台注册 {}", platform.getDeviceGBId());
|
|
||||||
commanderForPlatform.register(platform, eventResult -> {
|
|
||||||
log.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", platform.getServerGBId());
|
|
||||||
}, null);
|
|
||||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
|
||||||
log.error("[命令发送失败] 国标级联: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -348,79 +381,22 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
@Override
|
@Override
|
||||||
public void online(Platform platform, SipTransactionInfo sipTransactionInfo) {
|
public void online(Platform platform, SipTransactionInfo sipTransactionInfo) {
|
||||||
log.info("[国标级联]:{}, 平台上线", platform.getServerGBId());
|
log.info("[国标级联]:{}, 平台上线", platform.getServerGBId());
|
||||||
final String registerFailAgainTaskKey = REGISTER_FAIL_AGAIN_KEY_PREFIX + platform.getServerGBId();
|
PlatformRegisterTask registerTask = new PlatformRegisterTask(platform.getServerGBId(), platform.getExpires() * 1000L - 500L,
|
||||||
dynamicTask.stop(registerFailAgainTaskKey);
|
sipTransactionInfo, (platformServerGbId) -> {
|
||||||
|
this.registerExpire(platformServerGbId, sipTransactionInfo);
|
||||||
|
});
|
||||||
|
statusTaskRunner.addRegisterTask(registerTask);
|
||||||
|
|
||||||
platformMapper.updateStatus(platform.getServerGBId(), true);
|
PlatformKeepaliveTask keepaliveTask = new PlatformKeepaliveTask(platform.getServerGBId(), platform.getKeepTimeout() * 1000L,
|
||||||
PlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(platform.getServerGBId());
|
this::keepaliveExpire);
|
||||||
if (platformCatch == null) {
|
statusTaskRunner.addKeepAliveTask(keepaliveTask);
|
||||||
platformCatch = new PlatformCatch();
|
|
||||||
platformCatch.setPlatform(platform);
|
|
||||||
platformCatch.setId(platform.getServerGBId());
|
|
||||||
platform.setStatus(true);
|
|
||||||
platformCatch.setPlatform(platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
platformCatch.getPlatform().setStatus(true);
|
platformMapper.updateStatus(platform.getId(), true);
|
||||||
platformCatch.setSipTransactionInfo(sipTransactionInfo);
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
|
||||||
|
|
||||||
final String registerTaskKey = REGISTER_KEY_PREFIX + platform.getServerGBId();
|
|
||||||
if (!dynamicTask.isAlive(registerTaskKey)) {
|
|
||||||
log.info("[国标级联]:{}, 添加定时注册任务", platform.getServerGBId());
|
|
||||||
// 添加注册任务
|
|
||||||
dynamicTask.startCron(registerTaskKey,
|
|
||||||
// 注册失败(注册成功时由程序直接调用了online方法)
|
|
||||||
()-> registerTask(platform, sipTransactionInfo),
|
|
||||||
platform.getExpires() * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + platform.getServerGBId();
|
|
||||||
if (!dynamicTask.contains(keepaliveTaskKey)) {
|
|
||||||
log.info("[国标级联]:{}, 添加定时心跳任务", platform.getServerGBId());
|
|
||||||
// 添加心跳任务
|
|
||||||
dynamicTask.startCron(keepaliveTaskKey,
|
|
||||||
()-> {
|
|
||||||
try {
|
|
||||||
commanderForPlatform.keepalive(platform, eventResult -> {
|
|
||||||
// 心跳失败
|
|
||||||
if (eventResult.type != SipSubscribe.EventResultType.timeout) {
|
|
||||||
log.warn("[国标级联]发送心跳收到错误,code: {}, msg: {}", eventResult.statusCode, eventResult.msg);
|
|
||||||
}
|
|
||||||
// 心跳失败
|
|
||||||
PlatformCatch platformCatchForNow = redisCatchStorage.queryPlatformCatchInfo(platform.getServerGBId());
|
|
||||||
// 此时是第三次心跳超时, 平台离线
|
|
||||||
if (platformCatchForNow.getKeepAliveReply() == 2) {
|
|
||||||
// 设置平台离线,并重新注册
|
|
||||||
log.info("[国标级联] 三次心跳失败, 平台{}({})离线", platform.getName(), platform.getServerGBId());
|
|
||||||
offline(platform, false);
|
|
||||||
}else {
|
|
||||||
platformCatchForNow.setKeepAliveReply(platformCatchForNow.getKeepAliveReply() + 1);
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatchForNow);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, eventResult -> {
|
|
||||||
// 心跳成功
|
|
||||||
// 清空之前的心跳超时计数
|
|
||||||
PlatformCatch platformCatchForNow = redisCatchStorage.queryPlatformCatchInfo(platform.getServerGBId());
|
|
||||||
if (platformCatchForNow != null && platformCatchForNow.getKeepAliveReply() > 0) {
|
|
||||||
platformCatchForNow.setKeepAliveReply(0);
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatchForNow);
|
|
||||||
}
|
|
||||||
log.info("[国标级联] 发送心跳,平台{}({}), code: {}, msg: {}", platform.getName(), platform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
|
||||||
});
|
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
|
||||||
log.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(platform.getKeepTimeout())*1000);
|
|
||||||
}
|
|
||||||
if (platform.getAutoPushChannel() != null && platform.getAutoPushChannel()) {
|
if (platform.getAutoPushChannel() != null && platform.getAutoPushChannel()) {
|
||||||
if (subscribeHolder.getCatalogSubscribe(platform.getServerGBId()) == null) {
|
if (subscribeHolder.getCatalogSubscribe(platform.getServerGBId()) == null) {
|
||||||
log.info("[国标级联]:{}, 添加自动通道推送模拟订阅信息", platform.getServerGBId());
|
log.info("[国标级联]:{}, 添加自动通道推送模拟订阅信息", platform.getServerGBId());
|
||||||
addSimulatedSubscribeInfo(platform);
|
addSimulatedSubscribeInfo(platform);
|
||||||
|
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
|
SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
|
||||||
@ -430,6 +406,65 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册到期处理
|
||||||
|
*/
|
||||||
|
private void registerExpire(String platformServerId, SipTransactionInfo transactionInfo) {
|
||||||
|
log.info("[国标级联] 注册到期, 上级平台编号: {}", platformServerId);
|
||||||
|
Platform platform = queryPlatformByServerGBId(platformServerId);
|
||||||
|
if (platform == null || !platform.isEnable()) {
|
||||||
|
log.info("[国标级联] 注册到期, 上级平台编号: {}, 平台不存在或者未启用, 忽略", platformServerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendRegister(platform, transactionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void keepaliveExpire(String platformServerId, int failCount) {
|
||||||
|
log.info("[国标级联] 心跳到期, 上级平台编号: {}", platformServerId);
|
||||||
|
Platform platform = queryPlatformByServerGBId(platformServerId);
|
||||||
|
if (platform == null || !platform.isEnable()) {
|
||||||
|
log.info("[国标级联] 心跳到期, 上级平台编号: {}, 平台不存在或者未启用, 忽略", platformServerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
commanderForPlatform.keepalive(platform, eventResult -> {
|
||||||
|
// 心跳失败
|
||||||
|
if (eventResult.type != SipSubscribe.EventResultType.timeout) {
|
||||||
|
log.warn("[国标级联] 发送心跳收到错误,code: {}, msg: {}", eventResult.statusCode, eventResult.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 心跳超时失败
|
||||||
|
if (failCount < 2) {
|
||||||
|
log.info("[国标级联] 心跳发送超时, 平台服务编号: {}", platformServerId);
|
||||||
|
PlatformKeepaliveTask keepaliveTask = new PlatformKeepaliveTask(platform.getServerGBId(), platform.getKeepTimeout() * 1000L,
|
||||||
|
this::keepaliveExpire);
|
||||||
|
keepaliveTask.setFailCount(failCount + 1);
|
||||||
|
statusTaskRunner.addKeepAliveTask(keepaliveTask);
|
||||||
|
}else {
|
||||||
|
// 心跳超时三次, 不再发送心跳, 平台离线
|
||||||
|
log.info("[国标级联] 心跳发送超时三次,平台离线, 平台服务编号: {}", platformServerId);
|
||||||
|
offline(platform);
|
||||||
|
}
|
||||||
|
}, eventResult -> {
|
||||||
|
PlatformKeepaliveTask keepaliveTask = new PlatformKeepaliveTask(platform.getServerGBId(), platform.getKeepTimeout() * 1000L,
|
||||||
|
this::keepaliveExpire);
|
||||||
|
statusTaskRunner.addKeepAliveTask(keepaliveTask);
|
||||||
|
});
|
||||||
|
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||||
|
log.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage());
|
||||||
|
if (failCount < 2) {
|
||||||
|
PlatformKeepaliveTask keepaliveTask = new PlatformKeepaliveTask(platform.getServerGBId(), platform.getKeepTimeout() * 1000L,
|
||||||
|
this::keepaliveExpire);
|
||||||
|
keepaliveTask.setFailCount(failCount + 1);
|
||||||
|
statusTaskRunner.addKeepAliveTask(keepaliveTask);
|
||||||
|
}else {
|
||||||
|
// 心跳超时三次, 不再发送心跳, 平台离线
|
||||||
|
log.info("[国标级联] 心跳发送失败三次,平台离线, 平台服务编号: {}", platformServerId);
|
||||||
|
offline(platform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSimulatedSubscribeInfo(Platform platform) {
|
public void addSimulatedSubscribeInfo(Platform platform) {
|
||||||
// 自动添加一条模拟的订阅信息
|
// 自动添加一条模拟的订阅信息
|
||||||
@ -437,87 +472,25 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
SubscribeInfo.buildSimulated(platform.getServerGBId(), platform.getServerIp()));
|
SubscribeInfo.buildSimulated(platform.getServerGBId(), platform.getServerIp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerTask(Platform platform, SipTransactionInfo sipTransactionInfo){
|
|
||||||
try {
|
|
||||||
// 不在同一个会话中续订则每次全新注册
|
|
||||||
if (!userSetting.isRegisterKeepIntDialog()) {
|
|
||||||
sipTransactionInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sipTransactionInfo == null) {
|
|
||||||
log.info("[国标级联] 平台:{}注册即将到期,开始重新注册", platform.getServerGBId());
|
|
||||||
}else {
|
|
||||||
log.info("[国标级联] 平台:{}注册即将到期,开始续订", platform.getServerGBId());
|
|
||||||
}
|
|
||||||
|
|
||||||
commanderForPlatform.register(platform, sipTransactionInfo, eventResult -> {
|
|
||||||
log.info("[国标级联] 平台:{}注册失败,{}:{}", platform.getServerGBId(),
|
|
||||||
eventResult.statusCode, eventResult.msg);
|
|
||||||
if (platform.isStatus()) {
|
|
||||||
offline(platform, false);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void offline(Platform platform, boolean stopRegister) {
|
public void offline(Platform platform) {
|
||||||
log.info("[平台离线]:{}({})", platform.getName(), platform.getServerGBId());
|
log.info("[平台离线]:{}({})", platform.getName(), platform.getServerGBId());
|
||||||
PlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(platform.getServerGBId());
|
statusTaskRunner.removeRegisterTask(platform.getServerGBId());
|
||||||
platformCatch.setKeepAliveReply(0);
|
statusTaskRunner.removeKeepAliveTask(platform.getServerGBId());
|
||||||
platformCatch.setRegisterAliveReply(0);
|
|
||||||
Platform catchPlatform = platformCatch.getPlatform();
|
subscribeHolder.removeCatalogSubscribe(platform.getServerGBId());
|
||||||
catchPlatform.setStatus(false);
|
subscribeHolder.removeMobilePositionSubscribe(platform.getServerGBId());
|
||||||
platformCatch.setPlatform(catchPlatform);
|
|
||||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
platformMapper.updateStatus(platform.getId(), false);
|
||||||
platformMapper.updateStatus(platform.getServerGBId(), false);
|
|
||||||
|
|
||||||
// 停止所有推流
|
// 停止所有推流
|
||||||
log.info("[平台离线] {}({}), 停止所有推流", platform.getName(), platform.getServerGBId());
|
log.info("[平台离线] {}({}), 停止所有推流", platform.getName(), platform.getServerGBId());
|
||||||
stopAllPush(platform.getServerGBId());
|
stopAllPush(platform.getServerGBId());
|
||||||
|
|
||||||
// 清除注册定时
|
|
||||||
log.info("[平台离线] {}({}), 停止定时注册任务", platform.getName(), platform.getServerGBId());
|
|
||||||
final String registerTaskKey = REGISTER_KEY_PREFIX + platform.getServerGBId();
|
|
||||||
if (dynamicTask.contains(registerTaskKey)) {
|
|
||||||
dynamicTask.stop(registerTaskKey);
|
|
||||||
}
|
|
||||||
// 清除心跳定时
|
|
||||||
log.info("[平台离线] {}({}), 停止定时发送心跳任务", platform.getName(), platform.getServerGBId());
|
|
||||||
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + platform.getServerGBId();
|
|
||||||
if (dynamicTask.contains(keepaliveTaskKey)) {
|
|
||||||
// 清除心跳任务
|
|
||||||
dynamicTask.stop(keepaliveTaskKey);
|
|
||||||
}
|
|
||||||
// 停止订阅回复
|
|
||||||
SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
|
|
||||||
if (catalogSubscribe != null) {
|
|
||||||
if (catalogSubscribe.getExpires() > 0) {
|
|
||||||
log.info("[平台离线] {}({}), 停止目录订阅回复", platform.getName(), platform.getServerGBId());
|
|
||||||
subscribeHolder.removeCatalogSubscribe(platform.getServerGBId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("[平台离线] {}({}), 停止移动位置订阅回复", platform.getName(), platform.getServerGBId());
|
|
||||||
subscribeHolder.removeMobilePositionSubscribe(platform.getServerGBId());
|
|
||||||
// 发起定时自动重新注册
|
|
||||||
if (!stopRegister) {
|
|
||||||
// 设置为60秒自动尝试重新注册
|
|
||||||
final String registerFailAgainTaskKey = REGISTER_FAIL_AGAIN_KEY_PREFIX + platform.getServerGBId();
|
|
||||||
Platform platformInDb = platformMapper.query(platform.getId());
|
|
||||||
if (platformInDb.isEnable()) {
|
|
||||||
dynamicTask.startCron(registerFailAgainTaskKey,
|
|
||||||
()-> registerTask(platformInDb, null),
|
|
||||||
userSetting.getRegisterAgainAfterTime() * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopAllPush(String platformId) {
|
private void stopAllPush(String platformId) {
|
||||||
List<SendRtpInfo> sendRtpItems = sendRtpServerService.queryForPlatform(platformId);
|
List<SendRtpInfo> sendRtpItems = sendRtpServerService.queryForPlatform(platformId);
|
||||||
if (sendRtpItems != null && sendRtpItems.size() > 0) {
|
if (sendRtpItems != null && !sendRtpItems.isEmpty()) {
|
||||||
for (SendRtpInfo sendRtpItem : sendRtpItems) {
|
for (SendRtpInfo sendRtpItem : sendRtpItems) {
|
||||||
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
|
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
|
||||||
sendRtpServerService.delete(sendRtpItem);
|
sendRtpServerService.delete(sendRtpItem);
|
||||||
@ -527,23 +500,6 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void login(Platform platform) {
|
|
||||||
final String registerTaskKey = REGISTER_KEY_PREFIX + platform.getServerGBId();
|
|
||||||
try {
|
|
||||||
commanderForPlatform.register(platform, eventResult1 -> {
|
|
||||||
log.info("[国标级联] {},开始定时发起注册,间隔为1分钟", platform.getServerGBId());
|
|
||||||
// 添加注册任务
|
|
||||||
dynamicTask.startCron(registerTaskKey,
|
|
||||||
// 注册失败(注册成功时由程序直接调用了online方法)
|
|
||||||
()-> log.info("[国标级联] {}({}),平台离线后持续发起注册,失败", platform.getName(), platform.getServerGBId()),
|
|
||||||
60*1000);
|
|
||||||
}, null);
|
|
||||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
|
||||||
log.error("[命令发送失败] 国标级联注册: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendNotifyMobilePosition(String platformId) {
|
public void sendNotifyMobilePosition(String platformId) {
|
||||||
Platform platform = platformMapper.getParentPlatByServerGBId(platformId);
|
Platform platform = platformMapper.getParentPlatByServerGBId(platformId);
|
||||||
@ -890,7 +846,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Platform> queryEnablePlatformList(String serverId) {
|
public List<Platform> queryEnablePlatformList(String serverId) {
|
||||||
return platformMapper.queryEnableParentPlatformList(serverId,true);
|
return platformMapper.queryEnableParentPlatformListByServerId(serverId,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -898,55 +854,23 @@ public class PlatformServiceImpl implements IPlatformService {
|
|||||||
public void delete(Integer platformId, CommonCallback<Object> callback) {
|
public void delete(Integer platformId, CommonCallback<Object> callback) {
|
||||||
Platform platform = platformMapper.query(platformId);
|
Platform platform = platformMapper.query(platformId);
|
||||||
Assert.notNull(platform, "平台不存在");
|
Assert.notNull(platform, "平台不存在");
|
||||||
// 发送离线消息,无论是否成功都删除缓存
|
if (statusTaskRunner.containsRegister(platform.getServerGBId())) {
|
||||||
PlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(platform.getServerGBId());
|
|
||||||
if (platformCatch != null) {
|
|
||||||
String key = UUID.randomUUID().toString();
|
|
||||||
dynamicTask.startDelay(key, ()->{
|
|
||||||
deletePlatformInfo(platform);
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(null);
|
|
||||||
}
|
|
||||||
}, 2000);
|
|
||||||
try {
|
try {
|
||||||
commanderForPlatform.unregister(platform, platformCatch.getSipTransactionInfo(), (event -> {
|
SipTransactionInfo transactionInfo = statusTaskRunner.getRegisterTransactionInfo(platform.getServerGBId());
|
||||||
dynamicTask.stop(key);
|
sendUnRegister(platform, transactionInfo);
|
||||||
// 移除平台相关的信息
|
}catch (Exception ignored) {}
|
||||||
deletePlatformInfo(platform);
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(null);
|
|
||||||
}
|
|
||||||
}), (event -> {
|
|
||||||
dynamicTask.stop(key);
|
|
||||||
// 移除平台相关的信息
|
|
||||||
deletePlatformInfo(platform);
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(null);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
|
||||||
log.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
deletePlatformInfo(platform);
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
platformMapper.delete(platform.getId());
|
||||||
|
|
||||||
|
statusTaskRunner.removeRegisterTask(platform.getServerGBId());
|
||||||
|
statusTaskRunner.removeKeepAliveTask(platform.getServerGBId());
|
||||||
|
|
||||||
|
subscribeHolder.removeCatalogSubscribe(platform.getServerGBId());
|
||||||
|
subscribeHolder.removeMobilePositionSubscribe(platform.getServerGBId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Override
|
||||||
public void deletePlatformInfo(Platform platform) {
|
public List<Platform> queryAll() {
|
||||||
// 删除关联的通道
|
return platformMapper.queryAll();
|
||||||
platformChannelMapper.removeChannelsByPlatformId(platform.getId());
|
|
||||||
// 删除关联的分组
|
|
||||||
platformChannelMapper.removePlatformGroupsByPlatformId(platform.getId());
|
|
||||||
// 删除关联的行政区划
|
|
||||||
platformChannelMapper.removePlatformRegionByPlatformId(platform.getId());
|
|
||||||
// 删除redis缓存
|
|
||||||
redisCatchStorage.delPlatformCatchInfo(platform.getServerGBId());
|
|
||||||
// 删除平台信息
|
|
||||||
platformMapper.delete(platform.getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.task;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lin
|
|
||||||
*/
|
|
||||||
public interface ISubscribeTask extends Runnable{
|
|
||||||
void stop(CommonCallback<Boolean> callback);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.deviceSubscribe;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.SubscribeCallback;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public abstract class SubscribeTask implements Delayed {
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
private SubscribeCallback callback;
|
||||||
|
|
||||||
|
private SipTransactionInfo transactionInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间(单位: 毫秒)
|
||||||
|
*/
|
||||||
|
private long delayTime;
|
||||||
|
|
||||||
|
public abstract void expired();
|
||||||
|
|
||||||
|
public abstract String getKey();
|
||||||
|
|
||||||
|
public abstract String getName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelay(@NotNull TimeUnit unit) {
|
||||||
|
return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull Delayed o) {
|
||||||
|
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscribeTaskInfo getInfo(){
|
||||||
|
SubscribeTaskInfo subscribeTaskInfo = new SubscribeTaskInfo();
|
||||||
|
subscribeTaskInfo.setName(getName());
|
||||||
|
subscribeTaskInfo.setTransactionInfo(transactionInfo);
|
||||||
|
subscribeTaskInfo.setDeviceId(deviceId);
|
||||||
|
subscribeTaskInfo.setKey(getKey());
|
||||||
|
return subscribeTaskInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.deviceSubscribe;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SubscribeTaskInfo {
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
private SipTransactionInfo transactionInfo;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private long expireTime;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.deviceSubscribe;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.DelayQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class SubscribeTaskRunner{
|
||||||
|
|
||||||
|
private final Map<String, SubscribeTask> subscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final DelayQueue<SubscribeTask> delayQueue = new DelayQueue<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetting userSetting;
|
||||||
|
|
||||||
|
private final String prefix = "VMP_DEVICE_SUBSCRIBE";
|
||||||
|
|
||||||
|
// 订阅过期检查
|
||||||
|
@Scheduled(fixedDelay = 500, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
public void expirationCheck(){
|
||||||
|
while (!delayQueue.isEmpty()) {
|
||||||
|
SubscribeTask take = null;
|
||||||
|
try {
|
||||||
|
take = delayQueue.take();
|
||||||
|
try {
|
||||||
|
removeSubscribe(take.getKey());
|
||||||
|
take.expired();
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("[设备订阅到期] {} 到期处理时出现异常, 设备编号: {} ", take.getName(), take.getDeviceId());
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("[设备订阅任务] ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSubscribe(SubscribeTask task) {
|
||||||
|
Duration duration = Duration.ofSeconds((task.getDelayTime() - System.currentTimeMillis())/1000);
|
||||||
|
if (duration.getSeconds() < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
subscribes.put(task.getKey(), task);
|
||||||
|
String key = String.format("%s_%s_%s", prefix, userSetting.getServerId(), task.getKey());
|
||||||
|
redisTemplate.opsForValue().set(key, task.getInfo(), duration);
|
||||||
|
delayQueue.offer(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeSubscribe(String key) {
|
||||||
|
SubscribeTask task = subscribes.get(key);
|
||||||
|
if (task == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), task.getKey());
|
||||||
|
redisTemplate.delete(redisKey);
|
||||||
|
subscribes.remove(key);
|
||||||
|
if (delayQueue.contains(task)) {
|
||||||
|
boolean remove = delayQueue.remove(task);
|
||||||
|
if (!remove) {
|
||||||
|
log.info("[移除订阅任务] 从延时队列内移除失败: {}", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SipTransactionInfo getTransactionInfo(String key) {
|
||||||
|
SubscribeTask task = subscribes.get(key);
|
||||||
|
if (task == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return task.getTransactionInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateDelay(String key, long expirationTime) {
|
||||||
|
SubscribeTask task = subscribes.get(key);
|
||||||
|
if (task == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log.info("[更新订阅任务时间] {}, 编号: {}", task.getName(), key);
|
||||||
|
if (delayQueue.contains(task)) {
|
||||||
|
boolean remove = delayQueue.remove(task);
|
||||||
|
if (!remove) {
|
||||||
|
log.info("[更新订阅任务时间] 从延时队列内移除失败: {}", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task.setDelayTime(expirationTime);
|
||||||
|
delayQueue.offer(task);
|
||||||
|
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), task.getKey());
|
||||||
|
Duration duration = Duration.ofSeconds((expirationTime - System.currentTimeMillis())/1000);
|
||||||
|
redisTemplate.expire(redisKey, duration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(String key) {
|
||||||
|
return subscribes.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SubscribeTaskInfo> getAllTaskInfo(){
|
||||||
|
String scanKey = String.format("%s_%s_*", prefix, userSetting.getServerId());
|
||||||
|
List<Object> values = RedisUtil.scan(redisTemplate, scanKey);
|
||||||
|
if (values.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<SubscribeTaskInfo> result = new ArrayList<>();
|
||||||
|
for (Object value : values) {
|
||||||
|
String redisKey = (String)value;
|
||||||
|
SubscribeTaskInfo taskInfo = (SubscribeTaskInfo)redisTemplate.opsForValue().get(redisKey);
|
||||||
|
if (taskInfo == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Long expire = redisTemplate.getExpire(redisKey);
|
||||||
|
taskInfo.setExpireTime(expire);
|
||||||
|
result.add(taskInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.SubscribeCallback;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.SubscribeTask;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class SubscribeTaskForCatalog extends SubscribeTask {
|
||||||
|
|
||||||
|
public static final String name = "catalog";
|
||||||
|
|
||||||
|
public static SubscribeTask getInstance(Device device, SubscribeCallback callback, SipTransactionInfo transactionInfo) {
|
||||||
|
if (device.getSubscribeCycleForCatalog() <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SubscribeTaskForCatalog subscribeTaskForCatalog = new SubscribeTaskForCatalog();
|
||||||
|
subscribeTaskForCatalog.setDelayTime((device.getSubscribeCycleForCatalog() * 1000L - 500L) + System.currentTimeMillis());
|
||||||
|
subscribeTaskForCatalog.setDeviceId(device.getDeviceId());
|
||||||
|
subscribeTaskForCatalog.setCallback(callback);
|
||||||
|
subscribeTaskForCatalog.setTransactionInfo(transactionInfo);
|
||||||
|
return subscribeTaskForCatalog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expired() {
|
||||||
|
if (super.getCallback() == null) {
|
||||||
|
log.info("[设备订阅到期] 目录订阅 未找到到期处理回调, 编号: {}", getDeviceId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getCallback().run(getDeviceId(), getTransactionInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return String.format("%s_%s", name, getDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getKey(Device device) {
|
||||||
|
return String.format("%s_%s", SubscribeTaskForCatalog.name, device.getDeviceId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.SubscribeCallback;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.task.deviceSubscribe.SubscribeTask;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class SubscribeTaskForMobilPosition extends SubscribeTask {
|
||||||
|
|
||||||
|
public static final String name = "mobilPosition";
|
||||||
|
|
||||||
|
public static SubscribeTask getInstance(Device device, SubscribeCallback callback, SipTransactionInfo transactionInfo) {
|
||||||
|
if (device.getSubscribeCycleForCatalog() <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SubscribeTaskForMobilPosition subscribeTaskForMobilPosition = new SubscribeTaskForMobilPosition();
|
||||||
|
subscribeTaskForMobilPosition.setDelayTime((device.getSubscribeCycleForMobilePosition() * 1000L - 500L) + System.currentTimeMillis());
|
||||||
|
subscribeTaskForMobilPosition.setDeviceId(device.getDeviceId());
|
||||||
|
subscribeTaskForMobilPosition.setCallback(callback);
|
||||||
|
subscribeTaskForMobilPosition.setTransactionInfo(transactionInfo);
|
||||||
|
return subscribeTaskForMobilPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expired() {
|
||||||
|
if (super.getCallback() == null) {
|
||||||
|
log.info("[设备订阅到期] 移动位置订阅 未找到到期处理回调, 编号: {}", getDeviceId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getCallback().run(getDeviceId(), getTransactionInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return String.format("%s_%s", name, getDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getKey(Device device) {
|
||||||
|
return String.format("%s_%s", SubscribeTaskForMobilPosition.name, device.getDeviceId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,107 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.task.impl;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
|
||||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import javax.sip.DialogState;
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 目录订阅任务
|
|
||||||
* @author lin
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class CatalogSubscribeTask implements ISubscribeTask {
|
|
||||||
private final Device device;
|
|
||||||
private final ISIPCommander sipCommander;
|
|
||||||
private SIPRequest request;
|
|
||||||
|
|
||||||
private final DynamicTask dynamicTask;
|
|
||||||
|
|
||||||
private final String taskKey = "catalog-subscribe-timeout";
|
|
||||||
|
|
||||||
|
|
||||||
public CatalogSubscribeTask(Device device, ISIPCommander sipCommander, DynamicTask dynamicTask) {
|
|
||||||
this.device = device;
|
|
||||||
this.sipCommander = sipCommander;
|
|
||||||
this.dynamicTask = dynamicTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (dynamicTask.get(taskKey) != null) {
|
|
||||||
dynamicTask.stop(taskKey);
|
|
||||||
}
|
|
||||||
SIPRequest sipRequest = null;
|
|
||||||
try {
|
|
||||||
sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
|
|
||||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
|
||||||
// 成功
|
|
||||||
log.info("[目录订阅]成功: {}", device.getDeviceId());
|
|
||||||
ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
|
|
||||||
try {
|
|
||||||
this.request.getToHeader().setTag(toHeader.getTag());
|
|
||||||
} catch (ParseException e) {
|
|
||||||
log.info("[目录订阅]成功: 但为request设置ToTag失败");
|
|
||||||
this.request = null;
|
|
||||||
}
|
|
||||||
},eventResult -> {
|
|
||||||
this.request = null;
|
|
||||||
// 失败
|
|
||||||
log.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
|
||||||
dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
|
|
||||||
});
|
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
|
||||||
log.error("[命令发送失败] 目录订阅: {}", e.getMessage());
|
|
||||||
|
|
||||||
}
|
|
||||||
if (sipRequest != null) {
|
|
||||||
this.request = sipRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop(CommonCallback<Boolean> callback) {
|
|
||||||
/**
|
|
||||||
* dialog 的各个状态
|
|
||||||
* EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
|
|
||||||
* CONFIRMED-> Confirmed Dialog状态-已确认
|
|
||||||
* COMPLETED-> Completed Dialog状态-已完成
|
|
||||||
* TERMINATED-> Terminated Dialog状态-终止
|
|
||||||
*/
|
|
||||||
log.info("取消目录订阅时dialog状态为{}", DialogState.CONFIRMED);
|
|
||||||
if (dynamicTask.get(taskKey) != null) {
|
|
||||||
dynamicTask.stop(taskKey);
|
|
||||||
}
|
|
||||||
device.setSubscribeCycleForCatalog(0);
|
|
||||||
try {
|
|
||||||
sipCommander.catalogSubscribe(device, request, eventResult -> {
|
|
||||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
|
||||||
if (event.getResponse().getRawContent() != null) {
|
|
||||||
// 成功
|
|
||||||
log.info("[取消目录订阅]成功: {}", device.getDeviceId());
|
|
||||||
}else {
|
|
||||||
// 成功
|
|
||||||
log.info("[取消目录订阅]成功: {}", device.getDeviceId());
|
|
||||||
}
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(event.getResponse().getRawContent() != null);
|
|
||||||
}
|
|
||||||
},eventResult -> {
|
|
||||||
// 失败
|
|
||||||
log.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
|
||||||
});
|
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
|
||||||
log.error("[命令发送失败] 取消目录订阅: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.task.impl;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
|
||||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.ResponseEvent;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.header.ToHeader;
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移动位置订阅的定时更新
|
|
||||||
* @author lin
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class MobilePositionSubscribeTask implements ISubscribeTask {
|
|
||||||
private final Device device;
|
|
||||||
private final ISIPCommander sipCommander;
|
|
||||||
|
|
||||||
private SIPRequest request;
|
|
||||||
private final DynamicTask dynamicTask;
|
|
||||||
private final String taskKey = "mobile-position-subscribe-timeout";
|
|
||||||
|
|
||||||
public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander, DynamicTask dynamicTask) {
|
|
||||||
this.device = device;
|
|
||||||
this.sipCommander = sipCommander;
|
|
||||||
this.dynamicTask = dynamicTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (dynamicTask.get(taskKey) != null) {
|
|
||||||
dynamicTask.stop(taskKey);
|
|
||||||
}
|
|
||||||
SIPRequest sipRequest = null;
|
|
||||||
try {
|
|
||||||
sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
|
|
||||||
// 成功
|
|
||||||
log.info("[移动位置订阅]成功: {}", device.getDeviceId());
|
|
||||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
|
||||||
ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
|
|
||||||
try {
|
|
||||||
this.request.getToHeader().setTag(toHeader.getTag());
|
|
||||||
} catch (ParseException e) {
|
|
||||||
log.info("[移动位置订阅]成功: 为request设置ToTag失败");
|
|
||||||
this.request = null;
|
|
||||||
}
|
|
||||||
},eventResult -> {
|
|
||||||
this.request = null;
|
|
||||||
// 失败
|
|
||||||
log.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
|
||||||
dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
|
|
||||||
});
|
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
|
||||||
log.error("[命令发送失败] 移动位置订阅: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
if (sipRequest != null) {
|
|
||||||
this.request = sipRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop(CommonCallback<Boolean> callback) {
|
|
||||||
/**
|
|
||||||
* dialog 的各个状态
|
|
||||||
* EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
|
|
||||||
* CONFIRMED-> Confirmed Dialog状态-已确认
|
|
||||||
* COMPLETED-> Completed Dialog状态-已完成
|
|
||||||
* TERMINATED-> Terminated Dialog状态-终止
|
|
||||||
*/
|
|
||||||
if (dynamicTask.get(taskKey) != null) {
|
|
||||||
dynamicTask.stop(taskKey);
|
|
||||||
}
|
|
||||||
device.setSubscribeCycleForMobilePosition(0);
|
|
||||||
try {
|
|
||||||
sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
|
|
||||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
|
||||||
if (event.getResponse().getRawContent() != null) {
|
|
||||||
// 成功
|
|
||||||
log.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
|
|
||||||
}else {
|
|
||||||
// 成功
|
|
||||||
log.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
|
|
||||||
}
|
|
||||||
if (callback != null) {
|
|
||||||
callback.run(event.getResponse().getRawContent() != null);
|
|
||||||
}
|
|
||||||
},eventResult -> {
|
|
||||||
// 失败
|
|
||||||
log.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
|
||||||
});
|
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
|
||||||
log.error("[命令发送失败] 取消移动位置订阅: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.platformStatus;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.PlatformKeepaliveCallback;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台心跳任务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class PlatformKeepaliveTask implements Delayed {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String platformServerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间(单位: 毫秒)
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private long delayTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 到期回调
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private PlatformKeepaliveCallback callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 心跳发送失败次数
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private int failCount;
|
||||||
|
|
||||||
|
public PlatformKeepaliveTask(String platformServerId, long delayTime, PlatformKeepaliveCallback callback) {
|
||||||
|
this.platformServerId = platformServerId;
|
||||||
|
this.delayTime = System.currentTimeMillis() + delayTime;
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expired() {
|
||||||
|
if (callback == null) {
|
||||||
|
log.info("[平台心跳到期] 未找到到期处理回调, 平台上级编号: {}", platformServerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getCallback().run(platformServerId, failCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelay(@NotNull TimeUnit unit) {
|
||||||
|
return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull Delayed o) {
|
||||||
|
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.platformStatus;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台注册任务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class PlatformRegisterTask implements Delayed {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String platformServerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间(单位: 毫秒)
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private long delayTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private SipTransactionInfo sipTransactionInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 到期回调
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private CommonCallback<String> callback;
|
||||||
|
|
||||||
|
|
||||||
|
public PlatformRegisterTask(String platformServerId, long delayTime, SipTransactionInfo sipTransactionInfo, CommonCallback<String> callback) {
|
||||||
|
this.platformServerId = platformServerId;
|
||||||
|
this.delayTime = System.currentTimeMillis() + delayTime;
|
||||||
|
this.callback = callback;
|
||||||
|
this.sipTransactionInfo = sipTransactionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expired() {
|
||||||
|
if (callback == null) {
|
||||||
|
log.info("[平台注册到期] 未找到到期处理回调, 平台上级编号: {}", platformServerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getCallback().run(platformServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelay(@NotNull TimeUnit unit) {
|
||||||
|
return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull Delayed o) {
|
||||||
|
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlatformRegisterTaskInfo getInfo() {
|
||||||
|
PlatformRegisterTaskInfo taskInfo = new PlatformRegisterTaskInfo();
|
||||||
|
taskInfo.setPlatformServerId(platformServerId);
|
||||||
|
taskInfo.setSipTransactionInfo(sipTransactionInfo);
|
||||||
|
return taskInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.platformStatus;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台注册任务可序列化的信息
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Data
|
||||||
|
public class PlatformRegisterTaskInfo{
|
||||||
|
|
||||||
|
private String platformServerId;
|
||||||
|
|
||||||
|
private SipTransactionInfo sipTransactionInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private long expireTime;
|
||||||
|
}
|
||||||
@ -0,0 +1,202 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.task.platformStatus;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.DelayQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class PlatformStatusTaskRunner {
|
||||||
|
|
||||||
|
private final Map<String, PlatformRegisterTask> registerSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final DelayQueue<PlatformRegisterTask> registerDelayQueue = new DelayQueue<>();
|
||||||
|
|
||||||
|
private final Map<String, PlatformKeepaliveTask> keepaliveSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final DelayQueue<PlatformKeepaliveTask> keepaliveTaskDelayQueue = new DelayQueue<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserSetting userSetting;
|
||||||
|
|
||||||
|
private final String prefix = "VMP_PLATFORM_STATUS";
|
||||||
|
|
||||||
|
// 订阅过期检查
|
||||||
|
@Scheduled(fixedDelay = 500, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
public void expirationCheckForRegister(){
|
||||||
|
while (!registerDelayQueue.isEmpty()) {
|
||||||
|
PlatformRegisterTask take = null;
|
||||||
|
try {
|
||||||
|
take = registerDelayQueue.take();
|
||||||
|
try {
|
||||||
|
removeRegisterTask(take.getPlatformServerId());
|
||||||
|
take.expired();
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("[平台注册到期] 到期处理时出现异常, 平台上级编号: {} ", take.getPlatformServerId());
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("[平台注册到期] ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Scheduled(fixedDelay = 500, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
public void expirationCheckForKeepalive(){
|
||||||
|
while (!keepaliveTaskDelayQueue.isEmpty()) {
|
||||||
|
PlatformKeepaliveTask take = null;
|
||||||
|
try {
|
||||||
|
take = keepaliveTaskDelayQueue.take();
|
||||||
|
try {
|
||||||
|
removeKeepAliveTask(take.getPlatformServerId());
|
||||||
|
take.expired();
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("[平台心跳到期] 到期处理时出现异常, 平台上级编号: {} ", take.getPlatformServerId());
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("[平台心跳到期] ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRegisterTask(PlatformRegisterTask task) {
|
||||||
|
Duration duration = Duration.ofSeconds((task.getDelayTime() - System.currentTimeMillis())/1000);
|
||||||
|
if (duration.getSeconds() < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
registerSubscribes.put(task.getPlatformServerId(), task);
|
||||||
|
String key = String.format("%s_%s_%s", prefix, userSetting.getServerId(), task.getPlatformServerId());
|
||||||
|
redisTemplate.opsForValue().set(key, task.getInfo(), duration);
|
||||||
|
registerDelayQueue.offer(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeRegisterTask(String platformServerId) {
|
||||||
|
PlatformRegisterTask task = registerSubscribes.get(platformServerId);
|
||||||
|
if (task != null) {
|
||||||
|
registerSubscribes.remove(platformServerId);
|
||||||
|
}
|
||||||
|
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), platformServerId);
|
||||||
|
redisTemplate.delete(redisKey);
|
||||||
|
if (registerDelayQueue.contains(task)) {
|
||||||
|
boolean remove = registerDelayQueue.remove(task);
|
||||||
|
if (!remove) {
|
||||||
|
log.info("[移除平台注册任务] 从延时队列内移除失败: {}", platformServerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SipTransactionInfo getRegisterTransactionInfo(String platformServerId) {
|
||||||
|
PlatformRegisterTask task = registerSubscribes.get(platformServerId);
|
||||||
|
if (task == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return task.getSipTransactionInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateRegisterDelay(String platformServerId, long expirationTime) {
|
||||||
|
PlatformRegisterTask task = registerSubscribes.get(platformServerId);
|
||||||
|
if (task == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log.info("[更新平台注册任务时间] 平台上级编号: {}", platformServerId);
|
||||||
|
if (registerDelayQueue.contains(task)) {
|
||||||
|
boolean remove = registerDelayQueue.remove(task);
|
||||||
|
if (!remove) {
|
||||||
|
log.info("[更新平台注册任务时间] 从延时队列内移除失败: {}", platformServerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task.setDelayTime(expirationTime);
|
||||||
|
registerDelayQueue.offer(task);
|
||||||
|
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), platformServerId);
|
||||||
|
Duration duration = Duration.ofSeconds((expirationTime - System.currentTimeMillis())/1000);
|
||||||
|
redisTemplate.expire(redisKey, duration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsRegister(String platformServerId) {
|
||||||
|
return registerSubscribes.containsKey(platformServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PlatformRegisterTaskInfo> getAllRegisterTaskInfo(){
|
||||||
|
return getRegisterTransactionInfoByServerId(userSetting.getServerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addKeepAliveTask(PlatformKeepaliveTask task) {
|
||||||
|
Duration duration = Duration.ofSeconds((task.getDelayTime() - System.currentTimeMillis())/1000);
|
||||||
|
if (duration.getSeconds() < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
keepaliveSubscribes.put(task.getPlatformServerId(), task);
|
||||||
|
keepaliveTaskDelayQueue.offer(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeKeepAliveTask(String platformServerId) {
|
||||||
|
PlatformKeepaliveTask task = keepaliveSubscribes.get(platformServerId);
|
||||||
|
if (task != null) {
|
||||||
|
keepaliveSubscribes.remove(platformServerId);
|
||||||
|
}
|
||||||
|
if (keepaliveTaskDelayQueue.contains(task)) {
|
||||||
|
boolean remove = keepaliveTaskDelayQueue.remove(task);
|
||||||
|
if (!remove) {
|
||||||
|
log.info("[移除平台心跳任务] 从延时队列内移除失败: {}", platformServerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateKeepAliveDelay(String platformServerId, long expirationTime) {
|
||||||
|
PlatformKeepaliveTask task = keepaliveSubscribes.get(platformServerId);
|
||||||
|
if (task == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log.info("[更新平台心跳任务时间] 平台上级编号: {}", platformServerId);
|
||||||
|
if (keepaliveTaskDelayQueue.contains(task)) {
|
||||||
|
boolean remove = keepaliveTaskDelayQueue.remove(task);
|
||||||
|
if (!remove) {
|
||||||
|
log.info("[更新平台心跳任务时间] 从延时队列内移除失败: {}", platformServerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task.setDelayTime(expirationTime);
|
||||||
|
keepaliveTaskDelayQueue.offer(task);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKeepAlive(String platformServerId) {
|
||||||
|
return keepaliveSubscribes.containsKey(platformServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PlatformRegisterTaskInfo> getRegisterTransactionInfoByServerId(String serverId) {
|
||||||
|
String scanKey = String.format("%s_%s_*", prefix, serverId);
|
||||||
|
List<Object> values = RedisUtil.scan(redisTemplate, scanKey);
|
||||||
|
if (values.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<PlatformRegisterTaskInfo> result = new ArrayList<>();
|
||||||
|
for (Object value : values) {
|
||||||
|
String redisKey = (String)value;
|
||||||
|
PlatformRegisterTaskInfo taskInfo = (PlatformRegisterTaskInfo)redisTemplate.opsForValue().get(redisKey);
|
||||||
|
if (taskInfo == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Long expire = redisTemplate.getExpire(redisKey);
|
||||||
|
taskInfo.setExpireTime(expire);
|
||||||
|
result.add(taskInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -84,6 +84,11 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
|
|||||||
|
|
||||||
// Success
|
// Success
|
||||||
if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
|
if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
|
||||||
|
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(response.getCSeqHeader().getMethod());
|
||||||
|
if (sipRequestProcessor != null) {
|
||||||
|
sipRequestProcessor.process(responseEvent);
|
||||||
|
}
|
||||||
|
|
||||||
CallIdHeader callIdHeader = response.getCallIdHeader();
|
CallIdHeader callIdHeader = response.getCallIdHeader();
|
||||||
CSeqHeader cSeqHeader = response.getCSeqHeader();
|
CSeqHeader cSeqHeader = response.getCSeqHeader();
|
||||||
if (callIdHeader != null) {
|
if (callIdHeader != null) {
|
||||||
@ -96,10 +101,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
|
|||||||
sipSubscribe.removeSubscribe(callIdHeader.getCallId() + cSeqHeader.getSeqNumber());
|
sipSubscribe.removeSubscribe(callIdHeader.getCallId() + cSeqHeader.getSeqNumber());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(response.getCSeqHeader().getMethod());
|
|
||||||
if (sipRequestProcessor != null) {
|
|
||||||
sipRequestProcessor.process(responseEvent);
|
|
||||||
}
|
|
||||||
} else if ((status >= Response.TRYING) && (status < Response.OK)) {
|
} else if ((status >= Response.TRYING) && (status < Response.OK)) {
|
||||||
// 增加其它无需回复的响应,如101、180等
|
// 增加其它无需回复的响应,如101、180等
|
||||||
// 更新sip订阅的时间
|
// 更新sip订阅的时间
|
||||||
|
|||||||
@ -2,21 +2,22 @@ package com.genersoft.iot.vmp.gb28181.transmit;
|
|||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||||
import gov.nist.javax.sip.SipProviderImpl;
|
import gov.nist.javax.sip.SipProviderImpl;
|
||||||
|
import gov.nist.javax.sip.address.SipUri;
|
||||||
|
import gov.nist.javax.sip.message.SIPRequest;
|
||||||
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
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.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
import javax.sip.header.CSeqHeader;
|
import javax.sip.header.*;
|
||||||
import javax.sip.header.CallIdHeader;
|
|
||||||
import javax.sip.header.UserAgentHeader;
|
|
||||||
import javax.sip.header.ViaHeader;
|
|
||||||
import javax.sip.message.Message;
|
import javax.sip.message.Message;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
@ -39,6 +40,7 @@ public class SIPSender {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipSubscribe sipSubscribe;
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@ -69,11 +71,12 @@ public class SIPSender {
|
|||||||
log.error("添加UserAgentHeader失败", e);
|
log.error("添加UserAgentHeader失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
|
CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
|
||||||
CSeqHeader cSeqHeader = (CSeqHeader) message.getHeader(CSeqHeader.NAME);
|
CSeqHeader cSeqHeader = (CSeqHeader) message.getHeader(CSeqHeader.NAME);
|
||||||
String key = callIdHeader.getCallId() + cSeqHeader.getSeqNumber();
|
String key = callIdHeader.getCallId() + cSeqHeader.getSeqNumber();
|
||||||
if (okEvent != null || errorEvent != null) {
|
if (okEvent != null || errorEvent != null) {
|
||||||
|
|
||||||
|
FromHeader fromHeader = (FromHeader) message.getHeader(FromHeader.NAME);
|
||||||
SipEvent sipEvent = SipEvent.getInstance(key, eventResult -> {
|
SipEvent sipEvent = SipEvent.getInstance(key, eventResult -> {
|
||||||
sipSubscribe.removeSubscribe(key);
|
sipSubscribe.removeSubscribe(key);
|
||||||
if(okEvent != null) {
|
if(okEvent != null) {
|
||||||
@ -85,6 +88,26 @@ public class SIPSender {
|
|||||||
errorEvent.response(eventResult);
|
errorEvent.response(eventResult);
|
||||||
}
|
}
|
||||||
}), timeout == null ? sipConfig.getTimeout() : timeout);
|
}), timeout == null ? sipConfig.getTimeout() : timeout);
|
||||||
|
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo();
|
||||||
|
sipTransactionInfo.setFromTag(fromHeader.getTag());
|
||||||
|
sipTransactionInfo.setCallId(callIdHeader.getCallId());
|
||||||
|
|
||||||
|
if (message instanceof SIPResponse) {
|
||||||
|
SIPResponse response = (SIPResponse) message;
|
||||||
|
sipTransactionInfo.setToTag(response.getToHeader().getTag());
|
||||||
|
sipTransactionInfo.setViaBranch(response.getTopmostViaHeader().getBranch());
|
||||||
|
}else if (message instanceof SIPRequest) {
|
||||||
|
SIPRequest request = (SIPRequest) message;
|
||||||
|
sipTransactionInfo.setViaBranch(request.getTopmostViaHeader().getBranch());
|
||||||
|
SipUri sipUri = (SipUri)request.getRequestLine().getUri();
|
||||||
|
sipTransactionInfo.setUser(sipUri.getUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpiresHeader expiresHeader = (ExpiresHeader) message.getHeader(ExpiresHeader.NAME);
|
||||||
|
if (expiresHeader != null) {
|
||||||
|
sipTransactionInfo.setExpires(expiresHeader.getExpires());
|
||||||
|
}
|
||||||
|
sipEvent.setSipTransactionInfo(sipTransactionInfo);
|
||||||
sipSubscribe.addSubscribe(key, sipEvent);
|
sipSubscribe.addSubscribe(key, sipEvent);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -17,16 +17,16 @@ import javax.sip.InvalidArgumentException;
|
|||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description:设备能力接口,用于定义设备的控制、查询能力
|
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午9:16:34
|
* @date: 2020年5月3日 下午9:16:34
|
||||||
*/
|
*/
|
||||||
public interface ISIPCommander {
|
public interface ISIPCommander {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云台控制,支持方向与缩放控制
|
* 云台控制,支持方向与缩放控制
|
||||||
*
|
*
|
||||||
* @param device 控制设备
|
* @param device 控制设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||||
@ -36,10 +36,10 @@ public interface ISIPCommander {
|
|||||||
* @param zoomSpeed 镜头缩放速度
|
* @param zoomSpeed 镜头缩放速度
|
||||||
*/
|
*/
|
||||||
void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
|
void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
|
* 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
|
||||||
*
|
*
|
||||||
* @param device 控制设备
|
* @param device 控制设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
* @param cmdCode 指令码
|
* @param cmdCode 指令码
|
||||||
@ -48,7 +48,7 @@ public interface ISIPCommander {
|
|||||||
* @param combineCode2 组合码2
|
* @param combineCode2 组合码2
|
||||||
*/
|
*/
|
||||||
void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
|
void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前端控制指令(用于转发上级指令)
|
* 前端控制指令(用于转发上级指令)
|
||||||
* @param device 控制设备
|
* @param device 控制设备
|
||||||
@ -66,7 +66,7 @@ public interface ISIPCommander {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求回放视频流
|
* 请求回放视频流
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channel 预览通道
|
* @param channel 预览通道
|
||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
@ -76,13 +76,13 @@ public interface ISIPCommander {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求历史媒体下载
|
* 请求历史媒体下载
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channel 预览通道
|
* @param channel 预览通道
|
||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param downloadSpeed 下载倍速参数
|
* @param downloadSpeed 下载倍速参数
|
||||||
*/
|
*/
|
||||||
void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||||
String startTime, String endTime, int downloadSpeed,
|
String startTime, String endTime, int downloadSpeed,
|
||||||
SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException;
|
SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, Long timeout) throws InvalidArgumentException, SipException, ParseException;
|
||||||
@ -116,7 +116,7 @@ public interface ISIPCommander {
|
|||||||
* 回放倍速播放
|
* 回放倍速播放
|
||||||
*/
|
*/
|
||||||
void playSpeedCmd(Device device, DeviceChannel channel, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
|
void playSpeedCmd(Device device, DeviceChannel channel, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 回放控制
|
* 回放控制
|
||||||
* @param device
|
* @param device
|
||||||
@ -138,39 +138,39 @@ public interface ISIPCommander {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 音视频录像控制
|
* 音视频录像控制
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
* @param recordCmdStr 录像命令:Record / StopRecord
|
* @param recordCmdStr 录像命令:Record / StopRecord
|
||||||
*/
|
*/
|
||||||
void recordCmd(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
void recordCmd(Device device, String channelId, String recordCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 远程启动控制命令
|
* 远程启动控制命令
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 报警布防/撤防命令
|
* 报警布防/撤防命令
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void guardCmd(Device device, String guardCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
void guardCmd(Device device, String guardCmdStr, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 报警复位命令
|
* 报警复位命令
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param alarmMethod 报警方式(可选)
|
* @param alarmMethod 报警方式(可选)
|
||||||
* @param alarmType 报警类型(可选)
|
* @param alarmType 报警类型(可选)
|
||||||
*/
|
*/
|
||||||
void alarmResetCmd(Device device, String alarmMethod, String alarmType, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
void alarmResetCmd(Device device, String alarmMethod, String alarmType, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
*/
|
*/
|
||||||
@ -184,11 +184,11 @@ public interface ISIPCommander {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备配置命令
|
* 设备配置命令
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void deviceConfigCmd(Device device);
|
void deviceConfigCmd(Device device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备配置命令:basicParam
|
* 设备配置命令:basicParam
|
||||||
*/
|
*/
|
||||||
@ -196,11 +196,11 @@ public interface ISIPCommander {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备状态
|
* 查询设备状态
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void deviceStatusQuery(Device device, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
void deviceStatusQuery(Device device, ErrorCallback<String> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备信息
|
* 查询设备信息
|
||||||
*
|
*
|
||||||
@ -209,27 +209,27 @@ public interface ISIPCommander {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void deviceInfoQuery(Device device, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
void deviceInfoQuery(Device device, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询目录列表
|
* 查询目录列表
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
|
void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询录像信息
|
* 查询录像信息
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param sn
|
* @param sn
|
||||||
*/
|
*/
|
||||||
void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询报警信息
|
* 查询报警信息
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param startPriority 报警起始级别(可选)
|
* @param startPriority 报警起始级别(可选)
|
||||||
* @param endPriority 报警终止级别(可选)
|
* @param endPriority 报警终止级别(可选)
|
||||||
@ -241,37 +241,37 @@ public interface ISIPCommander {
|
|||||||
*/
|
*/
|
||||||
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
||||||
String alarmType, String startTime, String endTime, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
String alarmType, String startTime, String endTime, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备配置
|
* 查询设备配置
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 通道编码(可选)
|
* @param channelId 通道编码(可选)
|
||||||
* @param configType 配置类型:
|
* @param configType 配置类型:
|
||||||
*/
|
*/
|
||||||
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
void deviceConfigQuery(Device device, String channelId, String configType, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备预置位置
|
* 查询设备预置位置
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询移动设备位置数据
|
* 查询移动设备位置数据
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订阅、取消订阅移动位置
|
* 订阅、取消订阅移动位置
|
||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @return true = 命令发送成功
|
* @return true = 命令发送成功
|
||||||
*/
|
*/
|
||||||
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
SIPRequest mobilePositionSubscribe(Device device, SipTransactionInfo transactionInfo, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订阅、取消订阅报警信息
|
* 订阅、取消订阅报警信息
|
||||||
@ -290,7 +290,7 @@ public interface ISIPCommander {
|
|||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @return true = 命令发送成功
|
* @return true = 命令发送成功
|
||||||
*/
|
*/
|
||||||
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
SIPRequest catalogSubscribe(Device device, SipTransactionInfo transactionInfo, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拉框控制命令
|
* 拉框控制命令
|
||||||
|
|||||||
@ -34,7 +34,7 @@ public class SIPRequestHeaderPlarformProvider {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipLayer sipLayer;
|
private SipLayer sipLayer;
|
||||||
|
|
||||||
@ -225,11 +225,11 @@ public class SIPRequestHeaderPlarformProvider {
|
|||||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
|
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
|
||||||
parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
|
parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
|
||||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse() != null ? subscribeInfo.getResponse().getToTag(): subscribeInfo.getSimulatedToTag());
|
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getTransactionInfo() != null ? subscribeInfo.getTransactionInfo() .getToTag(): subscribeInfo.getSimulatedToTag());
|
||||||
// to
|
// to
|
||||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
|
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
|
||||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest() != null ?subscribeInfo.getRequest().getFromTag(): subscribeInfo.getSimulatedFromTag());
|
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getTransactionInfo() != null ?subscribeInfo.getTransactionInfo().getFromTag(): subscribeInfo.getSimulatedFromTag());
|
||||||
|
|
||||||
// Forwards
|
// Forwards
|
||||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||||
@ -239,7 +239,7 @@ public class SIPRequestHeaderPlarformProvider {
|
|||||||
// 设置编码, 防止中文乱码
|
// 设置编码, 防止中文乱码
|
||||||
messageFactory.setDefaultContentEncodingCharset("gb2312");
|
messageFactory.setDefaultContentEncodingCharset("gb2312");
|
||||||
|
|
||||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest() != null ? subscribeInfo.getRequest().getCallIdHeader().getCallId(): subscribeInfo.getSimulatedCallId());
|
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getTransactionInfo() != null ? subscribeInfo.getTransactionInfo().getCallId(): subscribeInfo.getSimulatedCallId());
|
||||||
|
|
||||||
request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
|
request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
|
||||||
toHeader, viaHeaders, maxForwards);
|
toHeader, viaHeaders, maxForwards);
|
||||||
|
|||||||
@ -33,7 +33,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipLayer sipLayer;
|
private SipLayer sipLayer;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
|
||||||
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
// sipuri
|
// sipuri
|
||||||
@ -76,7 +76,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
//请求行
|
//请求行
|
||||||
@ -96,10 +96,10 @@ public class SIPRequestHeaderProvider {
|
|||||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
||||||
|
|
||||||
//Forwards
|
//Forwards
|
||||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||||
|
|
||||||
//ceq
|
//ceq
|
||||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||||
@ -116,7 +116,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
//请求行
|
//请求行
|
||||||
@ -134,14 +134,14 @@ public class SIPRequestHeaderProvider {
|
|||||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
||||||
|
|
||||||
//Forwards
|
//Forwards
|
||||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||||
|
|
||||||
//ceq
|
//ceq
|
||||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||||
|
|
||||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||||
@ -231,7 +231,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createSubscribeRequest(Device device, String content, SipTransactionInfo sipTransactionInfo, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
// sipuri
|
// sipuri
|
||||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||||
@ -244,11 +244,11 @@ public class SIPRequestHeaderProvider {
|
|||||||
// from
|
// from
|
||||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
|
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, sipTransactionInfo == null ? SipUtils.getNewFromTag() :sipTransactionInfo.getFromTag());
|
||||||
// to
|
// to
|
||||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
|
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, sipTransactionInfo == null ? null :sipTransactionInfo.getToTag());
|
||||||
|
|
||||||
// Forwards
|
// Forwards
|
||||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||||
|
|||||||
@ -1179,7 +1179,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @return true = 命令发送成功
|
* @return true = 命令发送成功
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
public SIPRequest mobilePositionSubscribe(Device device, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
||||||
|
|
||||||
StringBuffer subscribePostitionXml = new StringBuffer(200);
|
StringBuffer subscribePostitionXml = new StringBuffer(200);
|
||||||
String charset = device.getCharset();
|
String charset = device.getCharset();
|
||||||
@ -1197,12 +1197,12 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
CallIdHeader callIdHeader;
|
CallIdHeader callIdHeader;
|
||||||
|
|
||||||
if (requestOld != null) {
|
if (sipTransactionInfo != null) {
|
||||||
callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
|
callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sipTransactionInfo.getCallId());
|
||||||
} else {
|
} else {
|
||||||
callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport());
|
callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport());
|
||||||
}
|
}
|
||||||
SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence",callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
|
SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), sipTransactionInfo, device.getSubscribeCycleForMobilePosition(), "presence",callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
|
||||||
|
|
||||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent);
|
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent);
|
||||||
return request;
|
return request;
|
||||||
@ -1255,7 +1255,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
public SIPRequest catalogSubscribe(Device device, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
||||||
|
|
||||||
StringBuffer cmdXml = new StringBuffer(200);
|
StringBuffer cmdXml = new StringBuffer(200);
|
||||||
String charset = device.getCharset();
|
String charset = device.getCharset();
|
||||||
@ -1268,14 +1268,14 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
CallIdHeader callIdHeader;
|
CallIdHeader callIdHeader;
|
||||||
|
|
||||||
if (requestOld != null) {
|
if (sipTransactionInfo != null) {
|
||||||
callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
|
callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sipTransactionInfo.getCallId());
|
||||||
} else {
|
} else {
|
||||||
callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport());
|
callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 有效时间默认为60秒以上
|
// 有效时间默认为60秒以上
|
||||||
SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog",
|
SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), sipTransactionInfo, device.getSubscribeCycleForCatalog(), "Catalog",
|
||||||
callIdHeader);
|
callIdHeader);
|
||||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent);
|
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent);
|
||||||
return request;
|
return request;
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
|||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
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.GitUtil;
|
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||||
import gov.nist.javax.sip.message.MessageFactoryImpl;
|
import gov.nist.javax.sip.message.MessageFactoryImpl;
|
||||||
@ -121,9 +120,6 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
|||||||
request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform,
|
request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform,
|
||||||
redisCatchStorage.getCSEQ(), fromTag,
|
redisCatchStorage.getCSEQ(), fromTag,
|
||||||
toTag, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
toTag, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
||||||
// 将 callid 写入缓存, 等注册成功可以更新状态
|
|
||||||
String callIdFromHeader = callIdHeader.getCallId();
|
|
||||||
redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister));
|
|
||||||
}else {
|
}else {
|
||||||
request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, fromTag, toTag, www, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, fromTag, toTag, www, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
||||||
}
|
}
|
||||||
@ -132,7 +128,6 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
|||||||
if (event != null) {
|
if (event != null) {
|
||||||
log.info("[国标级联]:{}, 注册失败: {} ", parentPlatform.getServerGBId(), event.msg);
|
log.info("[国标级联]:{}, 注册失败: {} ", parentPlatform.getServerGBId(), event.msg);
|
||||||
}
|
}
|
||||||
redisCatchStorage.delPlatformRegisterInfo(callIdHeader.getCallId());
|
|
||||||
if (errorEvent != null ) {
|
if (errorEvent != null ) {
|
||||||
errorEvent.response(event);
|
errorEvent.response(event);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.CmdType;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
||||||
@ -23,6 +20,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
import javax.sip.RequestEvent;
|
import javax.sip.RequestEvent;
|
||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
|
import javax.sip.header.EventHeader;
|
||||||
import javax.sip.header.ExpiresHeader;
|
import javax.sip.header.ExpiresHeader;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
@ -56,9 +54,9 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
|
|||||||
sipProcessorObserver.addRequestProcessor(method, this);
|
sipProcessorObserver.addRequestProcessor(method, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理SUBSCRIBE请求
|
* 处理SUBSCRIBE请求
|
||||||
*
|
*
|
||||||
* @param evt 事件
|
* @param evt 事件
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@ -106,7 +104,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
|
|||||||
String platformId = SipUtils.getUserIdFromFromHeader(request);
|
String platformId = SipUtils.getUserIdFromFromHeader(request);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||||
Platform platform = platformService.queryPlatformByServerGBId(platformId);
|
Platform platform = platformService.queryPlatformByServerGBId(platformId);
|
||||||
SubscribeInfo subscribeInfo = new SubscribeInfo(request, platformId);
|
|
||||||
if (platform == null) {
|
if (platform == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -122,23 +119,28 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
|
|||||||
.append("<Result>OK</Result>\r\n")
|
.append("<Result>OK</Result>\r\n")
|
||||||
.append("</Response>\r\n");
|
.append("</Response>\r\n");
|
||||||
|
|
||||||
if (subscribeInfo.getExpires() > 0) {
|
|
||||||
// GPS上报时间间隔
|
|
||||||
String interval = XmlUtil.getText(rootElement, "Interval");
|
|
||||||
if (interval == null) {
|
|
||||||
subscribeInfo.setGpsInterval(5);
|
|
||||||
}else {
|
|
||||||
subscribeInfo.setGpsInterval(Integer.parseInt(interval));
|
|
||||||
}
|
|
||||||
subscribeInfo.setSn(sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SIPResponse response = responseXmlAck(request, resultXml.toString(), platform, subscribeInfo.getExpires());
|
int expires = request.getExpires().getExpires();
|
||||||
|
SIPResponse response = responseXmlAck(request, resultXml.toString(), platform, expires);
|
||||||
|
|
||||||
|
SubscribeInfo subscribeInfo = SubscribeInfo.getInstance(response, platformId, expires,
|
||||||
|
(EventHeader)request.getHeader(EventHeader.NAME));
|
||||||
|
if (subscribeInfo.getExpires() > 0) {
|
||||||
|
// GPS上报时间间隔
|
||||||
|
String interval = XmlUtil.getText(rootElement, "Interval");
|
||||||
|
if (interval == null) {
|
||||||
|
subscribeInfo.setGpsInterval(5);
|
||||||
|
}else {
|
||||||
|
subscribeInfo.setGpsInterval(Integer.parseInt(interval));
|
||||||
|
}
|
||||||
|
subscribeInfo.setSn(sn);
|
||||||
|
}
|
||||||
if (subscribeInfo.getExpires() == 0) {
|
if (subscribeInfo.getExpires() == 0) {
|
||||||
subscribeHolder.removeMobilePositionSubscribe(platformId);
|
subscribeHolder.removeMobilePositionSubscribe(platformId);
|
||||||
}else {
|
}else {
|
||||||
subscribeInfo.setResponse(response);
|
subscribeInfo.setTransactionInfo(new SipTransactionInfo(response));
|
||||||
subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo, ()->{
|
subscribeHolder.putMobilePositionSubscribe(platformId, subscribeInfo, ()->{
|
||||||
platformService.sendNotifyMobilePosition(platformId);
|
platformService.sendNotifyMobilePosition(platformId);
|
||||||
});
|
});
|
||||||
@ -163,7 +165,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
|
|||||||
if (platform == null){
|
if (platform == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SubscribeInfo subscribeInfo = new SubscribeInfo(request, platformId);
|
|
||||||
|
|
||||||
String sn = XmlUtil.getText(rootElement, "SN");
|
String sn = XmlUtil.getText(rootElement, "SN");
|
||||||
log.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId);
|
log.info("[回复上级的目录订阅请求]: {}/{}", platformId, deviceId);
|
||||||
@ -176,18 +177,25 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
|
|||||||
.append("<Result>OK</Result>\r\n")
|
.append("<Result>OK</Result>\r\n")
|
||||||
.append("</Response>\r\n");
|
.append("</Response>\r\n");
|
||||||
|
|
||||||
if (subscribeInfo.getExpires() > 0) {
|
|
||||||
subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
|
|
||||||
}else if (subscribeInfo.getExpires() == 0) {
|
|
||||||
subscribeHolder.removeCatalogSubscribe(platformId);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
|
int expires = request.getExpires().getExpires();
|
||||||
Platform parentPlatform = platformService.queryPlatformByServerGBId(platformId);
|
Platform parentPlatform = platformService.queryPlatformByServerGBId(platformId);
|
||||||
SIPResponse response = responseXmlAck(request, resultXml.toString(), parentPlatform, subscribeInfo.getExpires());
|
SIPResponse response = responseXmlAck(request, resultXml.toString(), parentPlatform, expires);
|
||||||
|
|
||||||
|
SubscribeInfo subscribeInfo = SubscribeInfo.getInstance(response, platformId, expires,
|
||||||
|
(EventHeader)request.getHeader(EventHeader.NAME));
|
||||||
|
|
||||||
|
if (subscribeInfo.getExpires() > 0) {
|
||||||
|
subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
|
||||||
|
}else if (subscribeInfo.getExpires() == 0) {
|
||||||
|
subscribeHolder.removeCatalogSubscribe(platformId);
|
||||||
|
}
|
||||||
|
|
||||||
if (subscribeInfo.getExpires() == 0) {
|
if (subscribeInfo.getExpires() == 0) {
|
||||||
subscribeHolder.removeCatalogSubscribe(platformId);
|
subscribeHolder.removeCatalogSubscribe(platformId);
|
||||||
}else {
|
}else {
|
||||||
subscribeInfo.setResponse(response);
|
subscribeInfo.setTransactionInfo(new SipTransactionInfo(response));
|
||||||
subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
|
subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
|
||||||
}
|
}
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||||
|
|||||||
@ -97,10 +97,6 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||||||
}
|
}
|
||||||
Device device = sipMsgInfo.getDevice();
|
Device device = sipMsgInfo.getDevice();
|
||||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||||
// if (!ObjectUtils.isEmpty(device.getKeepaliveTime()) && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L) {
|
|
||||||
// log.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
|
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||||
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
|
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
|
||||||
@ -109,12 +105,6 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||||||
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
|
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
|
||||||
device.setIp(remoteAddressInfo.getIp());
|
device.setIp(remoteAddressInfo.getIp());
|
||||||
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
device.setLocalIp(request.getLocalAddress().getHostAddress());
|
||||||
// 设备地址变化会引起目录订阅任务失效,需要重新添加
|
|
||||||
if (device.getSubscribeCycleForCatalog() > 0) {
|
|
||||||
deviceService.removeCatalogSubscribe(device, result -> {
|
|
||||||
deviceService.addCatalogSubscribe(device);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device.setKeepaliveTime(DateUtil.getNow());
|
device.setKeepaliveTime(DateUtil.getNow());
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatch;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.sip.SipEvent;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
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.gb28181.service.IPlatformService;
|
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
|
|
||||||
import gov.nist.javax.sip.message.SIPResponse;
|
import gov.nist.javax.sip.message.SIPResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -21,10 +21,10 @@ import javax.sip.header.WWWAuthenticateHeader;
|
|||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description:Register响应处理器
|
* @description:Register响应处理器
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午5:32:23
|
* @date: 2020年5月3日 下午5:32:23
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@ -44,6 +44,9 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IPlatformService platformService;
|
private IPlatformService platformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
// 添加消息处理的订阅
|
// 添加消息处理的订阅
|
||||||
@ -59,23 +62,19 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
|
|||||||
public void process(ResponseEvent evt) {
|
public void process(ResponseEvent evt) {
|
||||||
SIPResponse response = (SIPResponse)evt.getResponse();
|
SIPResponse response = (SIPResponse)evt.getResponse();
|
||||||
String callId = response.getCallIdHeader().getCallId();
|
String callId = response.getCallIdHeader().getCallId();
|
||||||
PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId);
|
long seqNumber = response.getCSeqHeader().getSeqNumber();
|
||||||
if (platformRegisterInfo == null) {
|
SipEvent subscribe = sipSubscribe.getSubscribe(callId + seqNumber);
|
||||||
log.info(String.format("[国标级联]未找到callId: %s 的注册/注销平台id", callId ));
|
if (subscribe == null || subscribe.getSipTransactionInfo() == null || subscribe.getSipTransactionInfo().getUser() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformRegisterInfo.getPlatformId());
|
String action = subscribe.getSipTransactionInfo().getExpires() > 0 ? "注册" : "注销";
|
||||||
if (parentPlatformCatch == null) {
|
String platFormServerGbId = subscribe.getSipTransactionInfo().getUser();
|
||||||
log.warn(String.format("[国标级联]收到注册/注销%S请求,平台:%s,但是平台缓存信息未查询到!!!", response.getStatusCode(),platformRegisterInfo.getPlatformId()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String action = platformRegisterInfo.isRegister() ? "注册" : "注销";
|
log.info("[国标级联]{} {}响应 {} ", action, response.getStatusCode(), platFormServerGbId);
|
||||||
log.info(String.format("[国标级联]%s %S响应,%s ", action, response.getStatusCode(), platformRegisterInfo.getPlatformId() ));
|
Platform platform = platformService.queryPlatformByServerGBId(platFormServerGbId);
|
||||||
Platform parentPlatform = parentPlatformCatch.getPlatform();
|
if (platform == null) {
|
||||||
if (parentPlatform == null) {
|
log.warn("[国标级联]收到 来自{}的 {} 回复 {}, 但是平台信息未查询到!!!", platFormServerGbId, action, response.getStatusCode());
|
||||||
log.warn(String.format("[国标级联]收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformRegisterInfo.getPlatformId(), action, response.getStatusCode()));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,21 +82,17 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
|
|||||||
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
|
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
|
||||||
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
|
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
|
||||||
try {
|
try {
|
||||||
sipCommanderForPlatform.register(parentPlatform, sipTransactionInfo, www, null, null, platformRegisterInfo.isRegister());
|
sipCommanderForPlatform.register(platform, sipTransactionInfo, www, null, null, subscribe.getSipTransactionInfo().getExpires() > 0);
|
||||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||||
log.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage());
|
log.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}else if (response.getStatusCode() == Response.OK){
|
}else if (response.getStatusCode() == Response.OK){
|
||||||
|
if (subscribe.getSipTransactionInfo().getExpires() > 0) {
|
||||||
if (platformRegisterInfo.isRegister()) {
|
|
||||||
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
|
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
|
||||||
platformService.online(parentPlatform, sipTransactionInfo);
|
platformService.online(platform, sipTransactionInfo);
|
||||||
}else {
|
}else {
|
||||||
platformService.offline(parentPlatform, true);
|
platformService.offline(platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册/注销成功移除缓存的信息
|
|
||||||
redisCatchStorage.delPlatformRegisterInfo(callId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
|
||||||
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;
|
||||||
@ -55,6 +56,9 @@ public class RedisAlarmMsgListener implements MessageListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IPlatformService platformService;
|
private IPlatformService platformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlatformChannelService platformChannelService;
|
||||||
|
|
||||||
private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
|
private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -129,7 +133,6 @@ public class RedisAlarmMsgListener implements MessageListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// 获取开启了消息推送的设备和平台
|
// 获取开启了消息推送的设备和平台
|
||||||
List<Device> devices = channelService.queryDeviceWithAsMessageChannel();
|
List<Device> devices = channelService.queryDeviceWithAsMessageChannel();
|
||||||
@ -143,24 +146,26 @@ public class RedisAlarmMsgListener implements MessageListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Device device = deviceService.getDeviceByDeviceId(gbId);
|
// 获取该通道ID是属于设备还是对应的上级平台
|
||||||
Platform platform = platformService.queryPlatformByServerGBId(gbId);
|
Device device = deviceService.getDeviceBySourceChannelDeviceId(gbId);
|
||||||
if (device != null && platform == null) {
|
List<Platform> platforms = platformChannelService.queryByPlatformBySharChannelId(gbId);
|
||||||
|
if (device != null && (platforms == null || platforms.isEmpty())) {
|
||||||
try {
|
try {
|
||||||
commander.sendAlarmMessage(device, deviceAlarm);
|
commander.sendAlarmMessage(device, deviceAlarm);
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
log.error("[命令发送失败] 发送报警: {}", e.getMessage());
|
log.error("[命令发送失败] 发送报警: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
} else if (device == null && platform != null) {
|
} else if (device == null && (platforms != null && !platforms.isEmpty())) {
|
||||||
try {
|
for (Platform platform : platforms) {
|
||||||
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
|
try {
|
||||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
|
||||||
log.error("[命令发送失败] 发送报警: {}", e.getMessage());
|
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||||
|
log.error("[命令发送失败] 发送报警: {}", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn("无法确定" + gbId + "是平台还是设备");
|
log.warn("[REDIS的ALARM通知] 未查询到" + gbId + "所属的平台或设备");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -231,6 +231,9 @@ public class RedisRpcServiceImpl implements IRedisRpcService {
|
|||||||
RedisRpcRequest request = buildRequest("platform/update", platform);
|
RedisRpcRequest request = buildRequest("platform/update", platform);
|
||||||
request.setToId(serverId);
|
request.setToId(serverId);
|
||||||
RedisRpcResponse response = redisRpcConfig.request(request, 40, TimeUnit.MILLISECONDS);
|
RedisRpcResponse response = redisRpcConfig.request(request, 40, TimeUnit.MILLISECONDS);
|
||||||
|
if(response == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return Boolean.parseBoolean(response.getBody().toString());
|
return Boolean.parseBoolean(response.getBody().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.media.bean.MediaServer;
|
|||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
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.storager.dao.dto.PlatformRegisterInfo;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -23,18 +22,6 @@ public interface IRedisCatchStorage {
|
|||||||
*/
|
*/
|
||||||
Long getCSEQ();
|
Long getCSEQ();
|
||||||
|
|
||||||
void updatePlatformCatchInfo(PlatformCatch parentPlatformCatch);
|
|
||||||
|
|
||||||
PlatformCatch queryPlatformCatchInfo(String platformGbId);
|
|
||||||
|
|
||||||
void delPlatformCatchInfo(String platformGbId);
|
|
||||||
|
|
||||||
void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo);
|
|
||||||
|
|
||||||
PlatformRegisterInfo queryPlatformRegisterInfo(String callId);
|
|
||||||
|
|
||||||
void delPlatformRegisterInfo(String callId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在redis添加wvp的信息
|
* 在redis添加wvp的信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
|||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
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.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
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.JsonUtil;
|
import com.genersoft.iot.vmp.utils.JsonUtil;
|
||||||
import com.genersoft.iot.vmp.utils.SystemInfoUtils;
|
import com.genersoft.iot.vmp.utils.SystemInfoUtils;
|
||||||
@ -73,41 +72,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
|
|||||||
redisTemplate.opsForValue().set(key, 1);
|
redisTemplate.opsForValue().set(key, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePlatformCatchInfo(PlatformCatch parentPlatformCatch) {
|
|
||||||
String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId();
|
|
||||||
redisTemplate.opsForValue().set(key, parentPlatformCatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlatformCatch queryPlatformCatchInfo(String platformGbId) {
|
|
||||||
return (PlatformCatch)redisTemplate.opsForValue().get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delPlatformCatchInfo(String platformGbId) {
|
|
||||||
redisTemplate.delete(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePlatformRegisterInfo(String callId, PlatformRegisterInfo platformRegisterInfo) {
|
|
||||||
String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId;
|
|
||||||
Duration duration = Duration.ofSeconds(30L);
|
|
||||||
redisTemplate.opsForValue().set(key, platformRegisterInfo, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlatformRegisterInfo queryPlatformRegisterInfo(String callId) {
|
|
||||||
return (PlatformRegisterInfo)redisTemplate.opsForValue().get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delPlatformRegisterInfo(String callId) {
|
|
||||||
redisTemplate.delete(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateWVPInfo(ServerInfo serverInfo, int time) {
|
public void updateWVPInfo(ServerInfo serverInfo, int time) {
|
||||||
|
|||||||
@ -39,7 +39,7 @@ public class StreamPushPlayServiceImpl implements IStreamPushPlayService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserSetting userSetting;
|
private UserSetting userSetting;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DynamicTask dynamicTask;
|
private DynamicTask dynamicTask;
|
||||||
|
|
||||||
@ -57,27 +57,28 @@ public class StreamPushPlayServiceImpl implements IStreamPushPlayService {
|
|||||||
StreamPush streamPush = streamPushMapper.queryOne(id);
|
StreamPush streamPush = streamPushMapper.queryOne(id);
|
||||||
Assert.notNull(streamPush, "推流信息未找到");
|
Assert.notNull(streamPush, "推流信息未找到");
|
||||||
|
|
||||||
if (!userSetting.getServerId().equals(streamPush.getServerId())) {
|
if (streamPush.isPushing() && !userSetting.getServerId().equals(streamPush.getServerId())) {
|
||||||
redisRpcPlayService.playPush(id, callback);
|
redisRpcPlayService.playPush(id, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaServer mediaServer = mediaServerService.getOne(streamPush.getMediaServerId());
|
MediaServer mediaServer = mediaServerService.getOne(streamPush.getMediaServerId());
|
||||||
Assert.notNull(mediaServer, "节点" + streamPush.getMediaServerId() + "未找到");
|
if (mediaServer != null) {
|
||||||
MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServer, streamPush.getApp(), streamPush.getStream());
|
MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServer, streamPush.getApp(), streamPush.getStream());
|
||||||
if (mediaInfo != null) {
|
if (mediaInfo != null) {
|
||||||
String callId = null;
|
String callId = null;
|
||||||
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(streamPush.getApp(), streamPush.getStream());
|
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(streamPush.getApp(), streamPush.getStream());
|
||||||
if (streamAuthorityInfo != null) {
|
if (streamAuthorityInfo != null) {
|
||||||
callId = streamAuthorityInfo.getCallId();
|
callId = streamAuthorityInfo.getCallId();
|
||||||
|
}
|
||||||
|
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), mediaServerService.getStreamInfoByAppAndStream(mediaServer,
|
||||||
|
streamPush.getApp(), streamPush.getStream(), mediaInfo, callId));
|
||||||
|
if (!streamPush.isPushing()) {
|
||||||
|
streamPush.setPushing(true);
|
||||||
|
streamPushMapper.update(streamPush);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), mediaServerService.getStreamInfoByAppAndStream(mediaServer,
|
|
||||||
streamPush.getApp(), streamPush.getStream(), mediaInfo, callId));
|
|
||||||
if (!streamPush.isPushing()) {
|
|
||||||
streamPush.setPushing(true);
|
|
||||||
streamPushMapper.update(streamPush);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
Assert.isTrue(streamPush.isStartOfflinePush(), "通道未推流");
|
Assert.isTrue(streamPush.isStartOfflinePush(), "通道未推流");
|
||||||
// 发送redis消息以使设备上线,流上线后被
|
// 发送redis消息以使设备上线,流上线后被
|
||||||
|
|||||||
@ -195,6 +195,14 @@ public class DateUtil {
|
|||||||
}
|
}
|
||||||
Instant startInstant = Instant.from(formatter.parse(startTime));
|
Instant startInstant = Instant.from(formatter.parse(startTime));
|
||||||
Instant endInstant = Instant.from(formatter.parse(endTime));
|
Instant endInstant = Instant.from(formatter.parse(endTime));
|
||||||
return ChronoUnit.MILLIS.between(endInstant, startInstant);
|
return ChronoUnit.MILLIS.between(startInstant, endInstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
long difference = getDifference("2025-05-21 13:00:00", "2025-05-21 13:30:00")/1000;
|
||||||
|
System.out.println(difference);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user