dialog去除以及异常情况处理优化
This commit is contained in:
parent
70c20364af
commit
b79a49fa76
@ -2,6 +2,9 @@ package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.device.DeviceQuery;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@ -15,6 +18,8 @@ import java.util.regex.Pattern;
|
||||
@Configuration("mediaConfig")
|
||||
public class MediaConfig{
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(MediaConfig.class);
|
||||
|
||||
// 修改必须配置,不再支持自动获取
|
||||
@Value("${media.id}")
|
||||
private String id;
|
||||
@ -174,7 +179,7 @@ public class MediaConfig{
|
||||
try {
|
||||
hostAddress = InetAddress.getByName(sdpIp).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
logger.error("[获取SDP IP]: 域名解析失败");
|
||||
}
|
||||
return hostAddress;
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package com.genersoft.iot.vmp.conf.exception;
|
||||
|
||||
import com.sun.javafx.binding.StringFormatter;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
public class SsrcTransactionNotFoundException extends Exception{
|
||||
private String deviceId;
|
||||
private String channelId;
|
||||
private String callId;
|
||||
private String stream;
|
||||
|
||||
|
||||
|
||||
public SsrcTransactionNotFoundException(String deviceId, String channelId, String callId, String stream) {
|
||||
this.deviceId = deviceId;
|
||||
this.channelId = channelId;
|
||||
this.callId = callId;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public String getCallId() {
|
||||
return callId;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
StringBuffer msg = new StringBuffer();
|
||||
msg.append(StringFormatter.format("缓存事务信息未找到,device:%s channel: %s ", deviceId, channelId));
|
||||
if (callId != null) {
|
||||
msg.append("callId: " + callId);
|
||||
}
|
||||
if (stream != null) {
|
||||
msg.append("stream: " + stream);
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ public class SipLayer{
|
||||
|
||||
@Bean("sipStack")
|
||||
@DependsOn({"sipFactory"})
|
||||
SipStack createSipStack() throws PeerUnavailableException {
|
||||
SipStackImpl createSipStack() throws PeerUnavailableException {
|
||||
sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
|
||||
return sipStack;
|
||||
}
|
||||
@ -56,7 +56,6 @@ public class SipLayer{
|
||||
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||
tcpSipProvider.setDialogErrorsAutomaticallyHandled();
|
||||
tcpSipProvider.addSipListener(sipProcessorObserver);
|
||||
// tcpSipProvider.setAutomaticDialogSupportEnabled(false);
|
||||
logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort());
|
||||
} catch (TransportNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
@ -80,7 +79,6 @@ public class SipLayer{
|
||||
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
|
||||
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||
// udpSipProvider.setAutomaticDialogSupportEnabled(false);
|
||||
} catch (TransportNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
|
@ -0,0 +1,27 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import javax.sip.Dialog;
|
||||
import java.util.EventObject;
|
||||
|
||||
public class CmdSendFailEvent extends EventObject {
|
||||
|
||||
private String callId;
|
||||
|
||||
/**
|
||||
* Constructs a prototypical Event.
|
||||
*
|
||||
* @param dialog
|
||||
* @throws IllegalArgumentException if source is null.
|
||||
*/
|
||||
public CmdSendFailEvent(Dialog dialog) {
|
||||
super(dialog);
|
||||
}
|
||||
|
||||
public String getCallId() {
|
||||
return callId;
|
||||
}
|
||||
|
||||
public void setCallId(String callId) {
|
||||
this.callId = callId;
|
||||
}
|
||||
}
|
@ -4,6 +4,9 @@ import javax.sip.Dialog;
|
||||
import java.util.EventObject;
|
||||
|
||||
public class DeviceNotFoundEvent extends EventObject {
|
||||
|
||||
private String callId;
|
||||
|
||||
/**
|
||||
* Constructs a prototypical Event.
|
||||
*
|
||||
@ -14,8 +17,11 @@ public class DeviceNotFoundEvent extends EventObject {
|
||||
super(dialog);
|
||||
}
|
||||
|
||||
public String getCallId() {
|
||||
return callId;
|
||||
}
|
||||
|
||||
public Dialog getDialog() {
|
||||
return (Dialog)super.getSource();
|
||||
public void setCallId(String callId) {
|
||||
this.callId = callId;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
|
||||
public class SipTransactionInfo {
|
||||
|
||||
@ -9,11 +10,11 @@ public class SipTransactionInfo {
|
||||
private String toTag;
|
||||
private String viaBranch;
|
||||
|
||||
public SipTransactionInfo(SIPRequest request) {
|
||||
this.callId = request.getCallIdHeader().getCallId();
|
||||
this.fromTag = request.getFromTag();
|
||||
this.toTag = request.getToTag();
|
||||
this.viaBranch = request.getTopmostViaHeader().getBranch();
|
||||
public SipTransactionInfo(SIPResponse response) {
|
||||
this.callId = response.getCallIdHeader().getCallId();
|
||||
this.fromTag = response.getFromTag();
|
||||
this.toTag = response.getToTag();
|
||||
this.viaBranch = response.getTopmostViaHeader().getBranch();
|
||||
}
|
||||
|
||||
public SipTransactionInfo() {
|
||||
|
@ -8,10 +8,11 @@ public class SsrcTransaction {
|
||||
private String channelId;
|
||||
private String callId;
|
||||
private String stream;
|
||||
private byte[] transaction;
|
||||
private byte[] dialog;
|
||||
private String mediaServerId;
|
||||
private String ssrc;
|
||||
|
||||
private SipTransactionInfo sipTransactionInfo;
|
||||
|
||||
private VideoStreamSessionManager.SessionType type;
|
||||
|
||||
public String getDeviceId() {
|
||||
@ -46,22 +47,6 @@ public class SsrcTransaction {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public byte[] getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public void setTransaction(byte[] transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public byte[] getDialog() {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public void setDialog(byte[] dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
public String getMediaServerId() {
|
||||
return mediaServerId;
|
||||
}
|
||||
@ -85,4 +70,12 @@ public class SsrcTransaction {
|
||||
public void setType(VideoStreamSessionManager.SessionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public SipTransactionInfo getSipTransactionInfo() {
|
||||
return sipTransactionInfo;
|
||||
}
|
||||
|
||||
public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
|
||||
this.sipTransactionInfo = sipTransactionInfo;
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,10 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.utils.SerializeUtils;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
|
||||
import javax.sip.ClientTransaction;
|
||||
import javax.sip.Dialog;
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.ServerTransaction;
|
||||
import javax.sip.header.*;
|
||||
import javax.sip.message.Request;
|
||||
|
||||
public class SubscribeInfo {
|
||||
|
||||
|
@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
|
||||
import javax.sip.*;
|
||||
import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -56,8 +57,7 @@ public class SipSubscribe {
|
||||
logger.debug("errorSubscribes.size:{}",errorSubscribes.size());
|
||||
}
|
||||
|
||||
public interface Event {
|
||||
void response(EventResult eventResult);
|
||||
public interface Event { void response(EventResult eventResult) ;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,18 +81,13 @@ public class SipSubscribe {
|
||||
public EventResultType type;
|
||||
public String msg;
|
||||
public String callId;
|
||||
public Dialog dialog;
|
||||
public EventObject event;
|
||||
|
||||
public EventResult() {
|
||||
}
|
||||
|
||||
public EventResult(EventObject event) {
|
||||
this.event = event;
|
||||
if (event instanceof ResponseEvent) {
|
||||
ResponseEvent responseEvent = (ResponseEvent)event;
|
||||
Response response = responseEvent.getResponse();
|
||||
this.dialog = responseEvent.getDialog();
|
||||
this.type = EventResultType.response;
|
||||
if (response != null) {
|
||||
this.msg = response.getReasonPhrase();
|
||||
@ -127,12 +122,10 @@ public class SipSubscribe {
|
||||
this.statusCode = -1024;
|
||||
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
|
||||
}else if (event instanceof DeviceNotFoundEvent) {
|
||||
DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
|
||||
this.type = EventResultType.deviceNotFoundEvent;
|
||||
this.msg = "设备未找到";
|
||||
this.statusCode = -1024;
|
||||
this.dialog = deviceNotFoundEvent.getDialog();
|
||||
this.callId = this.dialog != null ?deviceNotFoundEvent.getDialog().getCallId().getCallId() : null;
|
||||
this.callId = ((DeviceNotFoundEvent) event).getCallId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener<RequestTimeo
|
||||
}
|
||||
deviceService.offline(device.getDeviceId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -96,7 +99,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
}
|
||||
if (deviceChannelList.size() > 0) {
|
||||
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
|
||||
try {
|
||||
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}else if (parentPlatformMap.keySet().size() > 0) {
|
||||
for (String gbId : parentPlatformMap.keySet()) {
|
||||
@ -112,7 +120,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
DeviceChannel deviceChannel = new DeviceChannel();
|
||||
deviceChannel.setChannelId(gbId);
|
||||
deviceChannelList.add(deviceChannel);
|
||||
try {
|
||||
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,7 +150,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
}
|
||||
if (deviceChannelList.size() > 0) {
|
||||
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
|
||||
try {
|
||||
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}else if (parentPlatformMap.keySet().size() > 0) {
|
||||
for (String gbId : parentPlatformMap.keySet()) {
|
||||
@ -157,7 +175,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform);
|
||||
deviceChannelList.add(deviceChannelByStream);
|
||||
}
|
||||
try {
|
||||
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null);
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException |
|
||||
SipException | IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,13 @@ import javax.sip.Dialog;
|
||||
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipMsgInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.utils.SerializeUtils;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -42,15 +46,14 @@ public class VideoStreamSessionManager {
|
||||
* @param callId 一次请求的CallID
|
||||
* @param stream 流名称
|
||||
* @param mediaServerId 所使用的流媒体ID
|
||||
* @param transaction 事务
|
||||
* @param response 回复
|
||||
*/
|
||||
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction, SessionType type){
|
||||
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, SessionType type){
|
||||
SsrcTransaction ssrcTransaction = new SsrcTransaction();
|
||||
ssrcTransaction.setDeviceId(deviceId);
|
||||
ssrcTransaction.setChannelId(channelId);
|
||||
ssrcTransaction.setStream(stream);
|
||||
byte[] transactionByteArray = SerializeUtils.serialize(transaction);
|
||||
ssrcTransaction.setTransaction(transactionByteArray);
|
||||
ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
|
||||
ssrcTransaction.setCallId(callId);
|
||||
ssrcTransaction.setSsrc(ssrc);
|
||||
ssrcTransaction.setMediaServerId(mediaServerId);
|
||||
@ -62,53 +65,6 @@ public class VideoStreamSessionManager {
|
||||
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
|
||||
}
|
||||
|
||||
public void put(String deviceId, String channelId, String callId, Dialog dialog){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
|
||||
if (ssrcTransaction != null) {
|
||||
byte[] dialogByteArray = SerializeUtils.serialize(dialog);
|
||||
ssrcTransaction.setDialog(dialogByteArray);
|
||||
}
|
||||
RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
|
||||
+ "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
|
||||
+ ssrcTransaction.getStream(), ssrcTransaction);
|
||||
}
|
||||
|
||||
|
||||
public ClientTransaction getTransaction(String deviceId, String channelId, String stream, String callId){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] transactionByteArray = ssrcTransaction.getTransaction();
|
||||
ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
|
||||
return clientTransaction;
|
||||
}
|
||||
|
||||
public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] dialogByteArray = ssrcTransaction.getDialog();
|
||||
if (dialogByteArray == null) {
|
||||
return null;
|
||||
}
|
||||
SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public SIPDialog getDialogByCallId(String deviceId, String channelId, String callId){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] dialogByteArray = ssrcTransaction.getDialog();
|
||||
if (dialogByteArray == null) {
|
||||
return null;
|
||||
}
|
||||
return (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
|
||||
}
|
||||
|
||||
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
|
||||
|
||||
if (ObjectUtils.isEmpty(deviceId)) {
|
||||
|
@ -10,9 +10,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import javax.sip.Dialog;
|
||||
import javax.sip.DialogState;
|
||||
import javax.sip.ResponseEvent;
|
||||
import javax.sip.*;
|
||||
import javax.sip.header.ToHeader;
|
||||
import java.text.ParseException;
|
||||
import java.util.Timer;
|
||||
@ -44,7 +42,9 @@ public class CatalogSubscribeTask implements ISubscribeTask {
|
||||
if (dynamicTask.get(taskKey) != null) {
|
||||
dynamicTask.stop(taskKey);
|
||||
}
|
||||
SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
|
||||
SIPRequest sipRequest = null;
|
||||
try {
|
||||
sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
|
||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||
// 成功
|
||||
logger.info("[目录订阅]成功: {}", device.getDeviceId());
|
||||
@ -61,6 +61,10 @@ public class CatalogSubscribeTask implements ISubscribeTask {
|
||||
logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||
dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 目录订阅: {}", e.getMessage());
|
||||
|
||||
}
|
||||
if (sipRequest != null) {
|
||||
this.request = sipRequest;
|
||||
}
|
||||
@ -80,6 +84,7 @@ public class CatalogSubscribeTask implements ISubscribeTask {
|
||||
dynamicTask.stop(taskKey);
|
||||
}
|
||||
device.setSubscribeCycleForCatalog(0);
|
||||
try {
|
||||
sipCommander.catalogSubscribe(device, request, eventResult -> {
|
||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||
if (event.getResponse().getRawContent() != null) {
|
||||
@ -93,5 +98,8 @@ public class CatalogSubscribeTask implements ISubscribeTask {
|
||||
// 失败
|
||||
logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 取消目录订阅订阅: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import javax.sip.Dialog;
|
||||
import javax.sip.DialogState;
|
||||
import javax.sip.ResponseEvent;
|
||||
import javax.sip.*;
|
||||
import javax.sip.header.ToHeader;
|
||||
import java.text.ParseException;
|
||||
import java.util.Timer;
|
||||
@ -43,7 +41,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
|
||||
if (dynamicTask.get(taskKey) != null) {
|
||||
dynamicTask.stop(taskKey);
|
||||
}
|
||||
SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
|
||||
SIPRequest sipRequest = null;
|
||||
try {
|
||||
sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
|
||||
// 成功
|
||||
logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
|
||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||
@ -60,6 +60,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
|
||||
logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||
dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 移动位置订阅: {}", e.getMessage());
|
||||
}
|
||||
if (sipRequest != null) {
|
||||
this.request = sipRequest;
|
||||
}
|
||||
@ -79,6 +82,7 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
|
||||
dynamicTask.stop(taskKey);
|
||||
}
|
||||
device.setSubscribeCycleForMobilePosition(0);
|
||||
try {
|
||||
sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
|
||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||
if (event.getResponse().getRawContent() != null) {
|
||||
@ -92,5 +96,8 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
|
||||
// 失败
|
||||
logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 取消移动位置订阅: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
@ -9,6 +10,11 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
|
||||
import javax.sip.Dialog;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.PeerUnavailableException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.message.Request;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||
@ -25,7 +31,7 @@ public interface ISIPCommander {
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
*/
|
||||
boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown);
|
||||
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台方向放控制
|
||||
@ -36,7 +42,7 @@ public interface ISIPCommander {
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
* @param moveSpeed 镜头移动速度
|
||||
*/
|
||||
boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed);
|
||||
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台缩放控制,使用配置文件中的默认镜头缩放速度
|
||||
@ -45,7 +51,7 @@ public interface ISIPCommander {
|
||||
* @param channelId 预览通道
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
*/
|
||||
boolean ptzZoomCmd(Device device,String channelId,int inOut);
|
||||
void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台缩放控制
|
||||
@ -54,7 +60,7 @@ public interface ISIPCommander {
|
||||
* @param channelId 预览通道
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
*/
|
||||
boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed);
|
||||
void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台控制,支持方向与缩放控制
|
||||
@ -67,7 +73,7 @@ public interface ISIPCommander {
|
||||
* @param moveSpeed 镜头移动速度
|
||||
* @param zoomSpeed 镜头缩放速度
|
||||
*/
|
||||
boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
|
||||
void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
|
||||
@ -79,7 +85,7 @@ public interface ISIPCommander {
|
||||
* @param parameter2 数据2
|
||||
* @param combineCode2 组合码2
|
||||
*/
|
||||
boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2);
|
||||
void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 前端控制指令(用于转发上级指令)
|
||||
@ -87,14 +93,14 @@ public interface ISIPCommander {
|
||||
* @param channelId 预览通道
|
||||
* @param cmdString 前端控制指令串
|
||||
*/
|
||||
boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
|
||||
void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求预览视频流
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
|
||||
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求回放视频流
|
||||
@ -104,7 +110,7 @@ public interface ISIPCommander {
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
|
||||
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求历史媒体下载
|
||||
@ -117,33 +123,33 @@ public interface ISIPCommander {
|
||||
*/
|
||||
void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
|
||||
SipSubscribe.Event errorEvent);
|
||||
SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 视频流停止
|
||||
*/
|
||||
void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent);
|
||||
void streamByeCmd(String deviceId, String channelId, String stream, String callId);
|
||||
void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
|
||||
void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
|
||||
|
||||
/**
|
||||
* 回放暂停
|
||||
*/
|
||||
void playPauseCmd(Device device, StreamInfo streamInfo);
|
||||
void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放恢复
|
||||
*/
|
||||
void playResumeCmd(Device device, StreamInfo streamInfo);
|
||||
void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放拖动播放
|
||||
*/
|
||||
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime);
|
||||
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放倍速播放
|
||||
*/
|
||||
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed);
|
||||
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放控制
|
||||
@ -151,7 +157,8 @@ public interface ISIPCommander {
|
||||
* @param streamInfo
|
||||
* @param content
|
||||
*/
|
||||
void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
|
||||
void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
@ -159,15 +166,15 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
boolean audioBroadcastCmd(Device device,String channelId);
|
||||
void audioBroadcastCmd(Device device,String channelId);
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent);
|
||||
boolean audioBroadcastCmd(Device device);
|
||||
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 音视频录像控制
|
||||
@ -176,21 +183,21 @@ public interface ISIPCommander {
|
||||
* @param channelId 预览通道
|
||||
* @param recordCmdStr 录像命令:Record / StopRecord
|
||||
*/
|
||||
boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent);
|
||||
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 远程启动控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean teleBootCmd(Device device);
|
||||
void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 报警布防/撤防命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent);
|
||||
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 报警复位命令
|
||||
@ -199,7 +206,7 @@ public interface ISIPCommander {
|
||||
* @param alarmMethod 报警方式(可选)
|
||||
* @param alarmType 报警类型(可选)
|
||||
*/
|
||||
boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent);
|
||||
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
||||
@ -207,7 +214,7 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
boolean iFrameCmd(Device device, String channelId);
|
||||
void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 看守位控制命令
|
||||
@ -217,14 +224,14 @@ public interface ISIPCommander {
|
||||
* @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
||||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent);
|
||||
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 设备配置命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean deviceConfigCmd(Device device);
|
||||
void deviceConfigCmd(Device device);
|
||||
|
||||
/**
|
||||
* 设备配置命令:basicParam
|
||||
@ -236,14 +243,14 @@ public interface ISIPCommander {
|
||||
* @param heartBeatInterval 心跳间隔时间(可选)
|
||||
* @param heartBeatCount 心跳超时次数(可选)
|
||||
*/
|
||||
boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent);
|
||||
void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备状态
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent);
|
||||
void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备信息
|
||||
@ -251,14 +258,14 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @return
|
||||
*/
|
||||
boolean deviceInfoQuery(Device device);
|
||||
void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询目录列表
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent);
|
||||
void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询录像信息
|
||||
@ -268,7 +275,7 @@ public interface ISIPCommander {
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param sn
|
||||
*/
|
||||
boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
|
||||
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;
|
||||
|
||||
/**
|
||||
* 查询报警信息
|
||||
@ -282,8 +289,8 @@ public interface ISIPCommander {
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
||||
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent);
|
||||
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
||||
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备配置
|
||||
@ -292,21 +299,21 @@ public interface ISIPCommander {
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param configType 配置类型:
|
||||
*/
|
||||
boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent);
|
||||
void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备预置位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent);
|
||||
void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询移动设备位置数据
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent);
|
||||
void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅移动位置
|
||||
@ -314,7 +321,7 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
|
||||
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅报警信息
|
||||
@ -327,14 +334,14 @@ public interface ISIPCommander {
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
||||
void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅目录信息
|
||||
* @param device 视频设备
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
|
||||
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 拉框控制命令
|
||||
@ -343,7 +350,7 @@ public interface ISIPCommander {
|
||||
* @param channelId 通道id
|
||||
* @param cmdString 前端控制指令串
|
||||
*/
|
||||
boolean dragZoomCmd(Device device, String channelId, String cmdString);
|
||||
void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
@ -352,5 +359,11 @@ public interface ISIPCommander {
|
||||
* @param deviceAlarm 报警信息信息
|
||||
* @return
|
||||
*/
|
||||
boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm);
|
||||
void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
void transmitRequest(String transport, Request request) throws SipException, ParseException ;
|
||||
|
||||
void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException;
|
||||
|
||||
void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, ParseException;
|
||||
}
|
||||
|
@ -4,7 +4,10 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.header.WWWAuthenticateHeader;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
public interface ISIPCommanderForPlatform {
|
||||
@ -14,15 +17,15 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param parentPlatform
|
||||
* @return
|
||||
*/
|
||||
boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
|
||||
boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister);
|
||||
void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
|
||||
void register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 向上级平台注销
|
||||
* @param parentPlatform
|
||||
* @return
|
||||
*/
|
||||
boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
|
||||
void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
|
||||
/**
|
||||
@ -30,7 +33,7 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param parentPlatform
|
||||
* @return callId(作为接受回复的判定)
|
||||
*/
|
||||
String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
|
||||
String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
@ -42,8 +45,8 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size);
|
||||
boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag);
|
||||
void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException;
|
||||
void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 向上级回复DeviceInfo查询信息
|
||||
@ -52,7 +55,7 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param fromTag
|
||||
* @return
|
||||
*/
|
||||
boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag);
|
||||
void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 向上级回复DeviceStatus查询信息
|
||||
@ -61,7 +64,7 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param fromTag
|
||||
* @return
|
||||
*/
|
||||
boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag);
|
||||
void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 向上级回复移动位置订阅消息
|
||||
@ -70,7 +73,7 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param subscribeInfo 订阅相关的信息
|
||||
* @return
|
||||
*/
|
||||
boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo);
|
||||
void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* 向上级回复报警消息
|
||||
@ -78,21 +81,21 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param deviceAlarm 报警信息信息
|
||||
* @return
|
||||
*/
|
||||
boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm);
|
||||
void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 回复catalog事件-增加/更新
|
||||
* @param parentPlatform
|
||||
* @param deviceChannels
|
||||
*/
|
||||
boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
|
||||
void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* 回复catalog事件-删除
|
||||
* @param parentPlatform
|
||||
* @param deviceChannels
|
||||
*/
|
||||
boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
|
||||
void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* 回复recordInfo
|
||||
@ -101,7 +104,7 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param fromTag fromTag
|
||||
* @param recordInfo 录像信息
|
||||
*/
|
||||
boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo);
|
||||
void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 录像播放推送完成时发送MediaStatus消息
|
||||
@ -109,13 +112,13 @@ public interface ISIPCommanderForPlatform {
|
||||
* @param sendRtpItem
|
||||
* @return
|
||||
*/
|
||||
boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem);
|
||||
void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 向发起点播的上级回复bye
|
||||
* @param platform 平台信息
|
||||
* @param callId callId
|
||||
*/
|
||||
void streamByeCmd(ParentPlatform platform, String callId);
|
||||
void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem);
|
||||
void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException;
|
||||
void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ import javax.sip.header.*;
|
||||
import javax.sip.message.Request;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipMsgInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
@ -17,6 +20,7 @@ import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
import gov.nist.javax.sip.SipStackImpl;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@ -168,34 +172,37 @@ public class SIPRequestHeaderProvider {
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createByteRequest(Device device, String channelId, String viaTag, String fromTag, String toTag, String callId) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,toTag);
|
||||
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
|
||||
CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(callId);
|
||||
CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
|
||||
request = sipFactory.createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
|
||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
|
||||
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
@ -251,47 +258,72 @@ public class SIPRequestHeaderProvider {
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createInfoRequest(Device device, StreamInfo streamInfo, String content)
|
||||
public SIPRequest createInfoRequest(Device device, String channelId, String content, SipTransactionInfo transactionInfo)
|
||||
throws SipException, ParseException, InvalidArgumentException {
|
||||
if (streamInfo == null) {
|
||||
return null;
|
||||
}
|
||||
Request request = null;
|
||||
SIPDialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
|
||||
if (dialog == null) {
|
||||
if (device == null || transactionInfo == null) {
|
||||
return null;
|
||||
}
|
||||
SIPRequest request = null;
|
||||
//请求行
|
||||
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
SipStack sipStack = udpSipProvider.getSipStack();
|
||||
SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
|
||||
if (dialog != sipDialog) {
|
||||
dialog = sipDialog;
|
||||
}else {
|
||||
dialog.setSipProvider(udpSipProvider);
|
||||
}
|
||||
streamSession.put(streamInfo.getDeviceID(), streamInfo.getChannelId(), dialog.getCallId().getCallId(), dialog);
|
||||
Request infoRequest = dialog.createRequest(Request.INFO);
|
||||
SipURI sipURI = (SipURI) infoRequest.getRequestURI();
|
||||
sipURI.setHost(device.getIp());
|
||||
sipURI.setPort(device.getPort());
|
||||
sipURI.setUser(streamInfo.getChannelId());
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
ViaHeader viaHeader = (ViaHeader) infoRequest.getHeader(ViaHeader.NAME);
|
||||
viaHeader.setRPort();
|
||||
// 增加Contact header
|
||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
|
||||
.createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort()));
|
||||
infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||
infoRequest.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO);
|
||||
CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
|
||||
request = (SIPRequest)sipFactory.createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
|
||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
|
||||
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
|
||||
if (content != null) {
|
||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application",
|
||||
"MANSRTSP");
|
||||
infoRequest.setContent(content, contentTypeHeader);
|
||||
request.setContent(content, contentTypeHeader);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createAckRequest(SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
CSeqHeader cSeqHeader = (CSeqHeader)infoRequest.getHeader(CSeqHeader.NAME);
|
||||
cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
|
||||
//ceq
|
||||
infoRequest.addHeader(cSeqHeader);
|
||||
return infoRequest;
|
||||
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
|
||||
|
||||
Request request = sipFactory.createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
|
||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
|
||||
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,13 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import com.genersoft.iot.vmp.utils.SerializeUtils;
|
||||
import gov.nist.javax.sip.SIPConstants;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
import gov.nist.javax.sip.SipStackImpl;
|
||||
import gov.nist.javax.sip.message.MessageFactoryImpl;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -26,17 +27,15 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.*;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.*;
|
||||
import javax.sip.message.Request;
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ -77,19 +76,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
private SubscribeHolder subscribeHolder;
|
||||
|
||||
@Override
|
||||
public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
|
||||
return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
|
||||
public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
|
||||
register(parentPlatform, null, null, errorEvent, okEvent, false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
|
||||
return register(parentPlatform, null, null, errorEvent, okEvent, false, false);
|
||||
public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
|
||||
register(parentPlatform, null, null, errorEvent, okEvent, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
|
||||
SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) {
|
||||
try {
|
||||
public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
|
||||
SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException {
|
||||
Request request;
|
||||
if (!registerAgain ) {
|
||||
CallIdHeader callIdHeader = null;
|
||||
@ -126,23 +124,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}
|
||||
|
||||
transmitRequest(parentPlatform, request, null, okEvent);
|
||||
return true;
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (PeerUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
|
||||
String callId = null;
|
||||
try {
|
||||
public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer keepaliveXml = new StringBuffer(200);
|
||||
keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
@ -163,11 +148,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
SipUtils.getNewViaTag(),
|
||||
callIdHeader);
|
||||
transmitRequest(parentPlatform, request, errorEvent, okEvent);
|
||||
callId = callIdHeader.getCallId();
|
||||
} catch (ParseException | InvalidArgumentException | SipException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return callId;
|
||||
return callIdHeader.getCallId();
|
||||
}
|
||||
|
||||
private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
|
||||
@ -206,12 +187,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) {
|
||||
public void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException {
|
||||
|
||||
if ( parentPlatform ==null) {
|
||||
return false;
|
||||
return ;
|
||||
}
|
||||
try {
|
||||
List<DeviceChannel> channels = new ArrayList<>();
|
||||
if (channel != null) {
|
||||
channels.add(channel);
|
||||
@ -225,20 +205,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
transmitRequest(parentPlatform, request);
|
||||
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) {
|
||||
public void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException {
|
||||
if ( parentPlatform ==null) {
|
||||
return false;
|
||||
return ;
|
||||
}
|
||||
sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
|
||||
return true;
|
||||
}
|
||||
private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
@ -300,11 +274,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
return catalogXml.toString();
|
||||
}
|
||||
|
||||
private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) {
|
||||
private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (index >= channels.size()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<DeviceChannel> deviceChannels;
|
||||
if (index + parentPlatform.getCatalogGroup() < channels.size()) {
|
||||
deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
|
||||
@ -319,11 +292,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
transmitRequest(parentPlatform, request, null, eventResult -> {
|
||||
int indexNext = index + parentPlatform.getCatalogGroup();
|
||||
try {
|
||||
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
|
||||
});
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -334,11 +308,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
|
||||
public void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (parentPlatform == null) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer deviceInfoXml = new StringBuffer(600);
|
||||
deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
@ -358,12 +331,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
transmitRequest(parentPlatform, request);
|
||||
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -374,11 +341,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
|
||||
public void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (parentPlatform == null) {
|
||||
return false;
|
||||
return ;
|
||||
}
|
||||
try {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer deviceStatusXml = new StringBuffer(600);
|
||||
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
@ -397,23 +363,17 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
transmitRequest(parentPlatform, request);
|
||||
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) {
|
||||
public void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
|
||||
if (parentPlatform == null) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
|
||||
}
|
||||
|
||||
try {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer deviceStatusXml = new StringBuffer(600);
|
||||
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
@ -433,27 +393,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, null);
|
||||
|
||||
} catch (SipException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) {
|
||||
public void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (parentPlatform == null) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
|
||||
deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
|
||||
try {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer deviceStatusXml = new StringBuffer(600);
|
||||
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
@ -478,25 +426,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
|
||||
transmitRequest(parentPlatform, request);
|
||||
|
||||
} catch (SipException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
|
||||
public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
|
||||
if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
if (index == null) {
|
||||
index = 0;
|
||||
}
|
||||
if (index >= deviceChannels.size()) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
List<DeviceChannel> channels;
|
||||
if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
|
||||
@ -504,32 +445,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}else {
|
||||
channels = deviceChannels.subList(index, deviceChannels.size());
|
||||
}
|
||||
try {
|
||||
Integer finalIndex = index;
|
||||
String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
|
||||
deviceChannels.size(), type, subscribeInfo);
|
||||
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, (eventResult -> {
|
||||
try {
|
||||
sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
|
||||
finalIndex + parentPlatform.getCatalogGroup());
|
||||
}));
|
||||
} catch (SipException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
|
||||
private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
|
||||
SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
|
||||
throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException {
|
||||
throws SipException, ParseException, InvalidArgumentException {
|
||||
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
// 设置编码, 防止中文乱码
|
||||
@ -537,50 +471,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
|
||||
|
||||
notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());
|
||||
|
||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
||||
notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
|
||||
|
||||
SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
|
||||
.createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
|
||||
notifyRequest.addHeader(subscriptionState);
|
||||
|
||||
EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
|
||||
if (subscribeInfo.getEventId() != null) {
|
||||
event.setEventId(subscribeInfo.getEventId());
|
||||
}
|
||||
notifyRequest.addHeader(event);
|
||||
SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
|
||||
sipURI.setHost(parentPlatform.getServerIP());
|
||||
sipURI.setPort(parentPlatform.getServerPort());
|
||||
|
||||
// ClientTransaction transaction = subscribeInfo.getClientTransaction();
|
||||
// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {
|
||||
// if ("TCP".equals(parentPlatform.getTransport())) {
|
||||
// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
|
||||
// } else if ("UDP".equals(parentPlatform.getTransport())) {
|
||||
// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
|
||||
// }
|
||||
// }
|
||||
|
||||
ClientTransaction transaction = null;
|
||||
if ("TCP".equals(parentPlatform.getTransport())) {
|
||||
transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
|
||||
} else if ("UDP".equals(parentPlatform.getTransport())) {
|
||||
transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
|
||||
}
|
||||
|
||||
// 添加错误订阅
|
||||
if (errorEvent != null) {
|
||||
sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);
|
||||
}
|
||||
// 添加订阅
|
||||
if (okEvent != null) {
|
||||
sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);
|
||||
}
|
||||
transaction.sendRequest();
|
||||
return transaction;
|
||||
transmitRequest(parentPlatform, notifyRequest);
|
||||
}
|
||||
|
||||
private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
|
||||
@ -639,20 +530,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
|
||||
SubscribeInfo subscribeInfo, Integer index) {
|
||||
public void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
|
||||
SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
|
||||
if (parentPlatform == null
|
||||
|| deviceChannels == null
|
||||
|| deviceChannels.size() == 0
|
||||
|| subscribeInfo == null) {
|
||||
return false;
|
||||
logger.warn("[缺少必要参数]");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == null) {
|
||||
index = 0;
|
||||
}
|
||||
if (index >= deviceChannels.size()) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
List<DeviceChannel> channels;
|
||||
if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
|
||||
@ -660,28 +552,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}else {
|
||||
channels = deviceChannels.subList(index, deviceChannels.size());
|
||||
}
|
||||
try {
|
||||
Integer finalIndex = index;
|
||||
String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
|
||||
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, (eventResult -> {
|
||||
}, eventResult -> {
|
||||
try {
|
||||
sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
|
||||
finalIndex + parentPlatform.getCatalogGroup());
|
||||
}));
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
|
||||
@ -711,11 +594,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
return catalogXml.toString();
|
||||
}
|
||||
@Override
|
||||
public boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) {
|
||||
public void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException {
|
||||
if ( parentPlatform ==null) {
|
||||
return false;
|
||||
return ;
|
||||
}
|
||||
try {
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer recordXml = new StringBuffer(600);
|
||||
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
|
||||
@ -759,23 +641,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
transmitRequest(parentPlatform, request);
|
||||
|
||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) {
|
||||
if (sendRtpItem == null) {
|
||||
return false;
|
||||
}
|
||||
if (platform == null) {
|
||||
return false;
|
||||
public void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (sendRtpItem == null || platform == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
|
||||
String characterSet = platform.getCharacterSet();
|
||||
StringBuffer mediaStatusXml = new StringBuffer(200);
|
||||
@ -790,34 +663,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
|
||||
sendRtpItem);
|
||||
|
||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
||||
messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);
|
||||
SipURI sipURI = (SipURI) messageRequest.getRequestURI();
|
||||
sipURI.setHost(platform.getServerIP());
|
||||
sipURI.setPort(platform.getServerPort());
|
||||
ClientTransaction clientTransaction;
|
||||
if ("TCP".equals(platform.getTransport())) {
|
||||
clientTransaction = tcpSipProvider.getNewClientTransaction(messageRequest);
|
||||
}else {
|
||||
clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
|
||||
}
|
||||
clientTransaction.sendRequest();
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (InvalidArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return true;
|
||||
|
||||
transmitRequest(platform, messageRequest);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamByeCmd(ParentPlatform platform, String callId) {
|
||||
public void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (platform == null) {
|
||||
return;
|
||||
}
|
||||
@ -828,7 +679,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) {
|
||||
public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (sendRtpItem == null ) {
|
||||
logger.info("[向上级发送BYE], sendRtpItem 为NULL");
|
||||
return;
|
||||
@ -844,25 +695,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
|
||||
zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
|
||||
}
|
||||
try {
|
||||
|
||||
SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
|
||||
if (byeRequest == null) {
|
||||
logger.warn("[向上级发送bye]:无法创建 byeRequest");
|
||||
}
|
||||
ClientTransaction clientTransaction;
|
||||
if ("TCP".equals(platform.getTransport())) {
|
||||
clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
|
||||
} else {
|
||||
clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
|
||||
}
|
||||
clientTransaction.sendRequest();
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
transmitRequest(platform,byeRequest);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import gov.nist.javax.sip.SipStackImpl;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import gov.nist.javax.sip.stack.SIPServerTransaction;
|
||||
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
@ -57,7 +58,7 @@ public abstract class SIPRequestProcessorParent {
|
||||
*/
|
||||
public ServerTransaction getServerTransaction(RequestEvent evt) {
|
||||
Request request = evt.getRequest();
|
||||
ServerTransaction serverTransaction = evt.getServerTransaction();
|
||||
SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
|
||||
// 判断TCP还是UDP
|
||||
boolean isTcp = false;
|
||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||
@ -65,28 +66,28 @@ public abstract class SIPRequestProcessorParent {
|
||||
if (transport.equalsIgnoreCase("TCP")) {
|
||||
isTcp = true;
|
||||
}
|
||||
|
||||
if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
|
||||
serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
|
||||
}
|
||||
if (serverTransaction == null) {
|
||||
try {
|
||||
if (isTcp) {
|
||||
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
|
||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
||||
serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
|
||||
if (serverTransaction == null) {
|
||||
serverTransaction = tcpSipProvider.getNewServerTransaction(request);
|
||||
serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
|
||||
}
|
||||
} else {
|
||||
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
|
||||
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
|
||||
serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
|
||||
if (serverTransaction == null) {
|
||||
serverTransaction = udpSipProvider.getNewServerTransaction(request);
|
||||
serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
|
||||
}
|
||||
}
|
||||
} catch (TransactionAlreadyExistsException e) {
|
||||
logger.error(e.getMessage());
|
||||
} catch (TransactionUnavailableException e) {
|
||||
logger.error(e.getMessage());
|
||||
}finally {
|
||||
|
||||
}
|
||||
}
|
||||
return serverTransaction;
|
||||
|
@ -23,12 +23,15 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.header.FromHeader;
|
||||
import javax.sip.header.HeaderAddress;
|
||||
import javax.sip.header.ToHeader;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -95,8 +98,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
|
||||
String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
|
||||
Map<String, Object> param = new HashMap<>(12);
|
||||
param.put("vhost","__defaultVhost__");
|
||||
param.put("app",sendRtpItem.getApp());
|
||||
param.put("stream",sendRtpItem.getStreamId());
|
||||
@ -139,7 +142,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
// TODO 可能是语音对讲
|
||||
}else {
|
||||
// 向上级平台
|
||||
try {
|
||||
commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
@ -12,12 +13,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.SerializeUtils;
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@ -50,6 +50,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorage storager;
|
||||
|
||||
@ -77,8 +80,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
*/
|
||||
@Override
|
||||
public void process(RequestEvent evt) {
|
||||
|
||||
try {
|
||||
responseAck(getServerTransaction(evt), Response.OK);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[回复BYE信息失败],{}", e.getMessage());
|
||||
}
|
||||
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
|
||||
String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
||||
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
||||
@ -99,7 +106,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
if (totalReaderCount <= 0) {
|
||||
logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
|
||||
if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
|
||||
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null);
|
||||
Device device = deviceService.queryDevice(sendRtpItem.getDeviceId());
|
||||
if (device == null) {
|
||||
logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
|
||||
}
|
||||
try {
|
||||
logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), channelId);
|
||||
cmder.streamByeCmd(device, channelId, streamId, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException |
|
||||
SsrcTransactionNotFoundException e) {
|
||||
logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
|
||||
}
|
||||
}
|
||||
if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
|
||||
MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
|
||||
@ -120,8 +137,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
}
|
||||
SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
|
||||
if (ssrcTransactionForPlay != null){
|
||||
SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
|
||||
if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
|
||||
if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){
|
||||
// 释放ssrc
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
|
||||
if (mediaServerItem != null) {
|
||||
@ -140,12 +156,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
|
||||
}
|
||||
}
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +341,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
logger.info("Ack 等待超时");
|
||||
mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc);
|
||||
// 回复bye
|
||||
try {
|
||||
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}, 60 * 1000);
|
||||
responseSdpAck(serverTransaction, content.toString(), platform);
|
||||
|
||||
|
@ -93,7 +93,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
|
||||
responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
|
||||
logger.warn("[设备未找到 ]: {}", deviceId);
|
||||
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
|
||||
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
|
||||
deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
|
||||
sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
|
||||
};
|
||||
}else {
|
||||
|
@ -89,8 +89,6 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
|
||||
ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
|
||||
try {
|
||||
if (device != null && parentPlatform != null) {
|
||||
|
||||
logger.warn("[重复]平台与设备编号重复:{}", deviceId);
|
||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||
String hostAddress = request.getRemoteAddress().getHostAddress();
|
||||
int remotePort = request.getRemotePort();
|
||||
@ -105,7 +103,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
|
||||
responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
|
||||
logger.warn("[设备未找到 ]: {}", deviceId);
|
||||
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
|
||||
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
|
||||
deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
|
||||
sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
|
||||
};
|
||||
}else {
|
||||
|
@ -16,6 +16,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -48,6 +50,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
||||
@Autowired
|
||||
private SIPCommanderFroPlatform cmderFroPlatform;
|
||||
|
||||
@Qualifier("taskExecutor")
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
controlMessageHandler.addHandler(cmdType, this);
|
||||
@ -71,11 +77,12 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
||||
if (parentPlatform.getServerGBId().equals(targetGBId)) {
|
||||
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
|
||||
logger.info("执行远程启动本平台命令");
|
||||
try {
|
||||
cmderFroPlatform.unregister(parentPlatform, null, null);
|
||||
|
||||
Thread restartThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
||||
}
|
||||
taskExecutor.execute(()->{
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
|
||||
@ -90,15 +97,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
||||
stack.deleteSipProvider((SipProvider) providers.next());
|
||||
}
|
||||
VManageBootstrap.restart();
|
||||
} catch (InterruptedException ignored) {
|
||||
} catch (ObjectInUseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (InterruptedException | ObjectInUseException e) {
|
||||
logger.error("[任务执行失败] 服务重启: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
restartThread.setDaemon(false);
|
||||
restartThread.start();
|
||||
} else {
|
||||
// 远程启动指定设备
|
||||
}
|
||||
@ -111,37 +113,29 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
||||
try {
|
||||
responseAck(serverTransaction, Response.NOT_FOUND);
|
||||
return;
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 错误信息: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
try {
|
||||
cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
|
||||
// 失败的回复
|
||||
try {
|
||||
responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
|
||||
}
|
||||
}, eventResult -> {
|
||||
// 成功的回复
|
||||
try {
|
||||
responseAck(serverTransaction, eventResult.statusCode);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
@ -89,7 +90,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
|
||||
// 先从会话内查找
|
||||
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
|
||||
if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
|
||||
cmder.streamByeCmd(device.getDeviceId(), ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
|
||||
|
||||
try {
|
||||
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
|
||||
} catch (InvalidArgumentException | ParseException | SsrcTransactionNotFoundException | SipException e) {
|
||||
logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage());
|
||||
}
|
||||
|
||||
// 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定
|
||||
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null);
|
||||
@ -99,7 +105,11 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
|
||||
logger.warn("[级联消息发送]:发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,14 +49,14 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
|
||||
try {
|
||||
// 回复200 OK
|
||||
responseAck(getServerTransaction(evt), Response.OK);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] DeviceInfo查询回复: {}", e.getMessage());
|
||||
}
|
||||
String sn = rootElement.element("SN").getText();
|
||||
try {
|
||||
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,14 +62,14 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
|
||||
// 回复200 OK
|
||||
try {
|
||||
responseAck(getServerTransaction(evt), Response.OK);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage());
|
||||
}
|
||||
String sn = rootElement.element("SN").getText();
|
||||
try {
|
||||
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,53 +103,45 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
|
||||
DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId);
|
||||
// 接收录像数据
|
||||
recordEndEventListener.addEndEventHandler(deviceChannel.getDeviceId(), channelId, (recordInfo)->{
|
||||
try {
|
||||
cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, fromHeader.getTag(), recordInfo);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
try {
|
||||
commander.recordInfoQuery(device, channelId, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
|
||||
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
|
||||
// 回复200 OK
|
||||
try {
|
||||
responseAck(serverTransaction, Response.OK);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
|
||||
}
|
||||
}),(eventResult -> {
|
||||
// 查询失败
|
||||
try {
|
||||
responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
|
||||
}
|
||||
}));
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
|
||||
}
|
||||
|
||||
}else if (channelSources.get(1).getCount() > 0) { // 直播流
|
||||
// TODO
|
||||
try {
|
||||
responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
|
||||
}
|
||||
}else { // 错误的请求
|
||||
try {
|
||||
responseAck(serverTransaction, Response.BAD_REQUEST);
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,16 +87,24 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
|
||||
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||
taskQueue.offer(new HandlerCatchData(evt, device, element));
|
||||
// 回复200 OK
|
||||
try {
|
||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
||||
try {
|
||||
responseAck(serverTransaction, Response.OK);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
|
||||
}
|
||||
if (!taskQueueHandlerRun) {
|
||||
taskQueueHandlerRun = true;
|
||||
taskExecutor.execute(() -> {
|
||||
while (!taskQueue.isEmpty()) {
|
||||
HandlerCatchData take = taskQueue.poll();
|
||||
Element rootElement = null;
|
||||
try {
|
||||
Element rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
|
||||
rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
|
||||
} catch (DocumentException e) {
|
||||
logger.error("[xml解析] 失败: ", e);
|
||||
continue;
|
||||
}
|
||||
if (rootElement == null) {
|
||||
logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
|
||||
continue;
|
||||
@ -104,10 +112,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
|
||||
Element deviceListElement = rootElement.element("DeviceList");
|
||||
Element sumNumElement = rootElement.element("SumNum");
|
||||
Element snElement = rootElement.element("SN");
|
||||
if (snElement == null || sumNumElement == null || deviceListElement == null) {
|
||||
responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
|
||||
continue;
|
||||
}
|
||||
int sumNum = Integer.parseInt(sumNumElement.getText());
|
||||
|
||||
if (sumNum == 0) {
|
||||
@ -148,29 +152,9 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
|
||||
}
|
||||
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
taskQueueHandlerRun = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (SipException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvalidArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
taskQueueHandlerRun = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -50,12 +50,12 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
|
||||
|
||||
@Override
|
||||
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||
Element rootElement = null;
|
||||
try {
|
||||
|
||||
ServerTransaction serverTransaction = getServerTransaction(evt);
|
||||
|
||||
rootElement = getRootElement(evt, device.getCharset());
|
||||
try {
|
||||
Element rootElement = getRootElement(evt, device.getCharset());
|
||||
|
||||
if (rootElement == null) {
|
||||
logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
|
||||
responseAck(serverTransaction, Response.BAD_REQUEST);
|
||||
@ -88,10 +88,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
|
||||
}
|
||||
}
|
||||
presetQuerySipReqList.add(presetQuerySipReq);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
RequestMessage requestMessage = new RequestMessage();
|
||||
requestMessage.setKey(key);
|
||||
@ -99,13 +96,9 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
|
||||
deferredResultHolder.invokeAllResult(requestMessage);
|
||||
responseAck(serverTransaction, Response.OK);
|
||||
} catch (DocumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SipException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("[解析xml]失败: ", e);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 设备预置位查询应答处理: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,27 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import gov.nist.javax.sip.ResponseEventExt;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import gov.nist.javax.sip.stack.SIPClientTransaction;
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import gov.nist.javax.sip.stack.SIPTransaction;
|
||||
import gov.nist.javax.sip.stack.SIPTransactionImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sdp.SdpFactory;
|
||||
@ -54,6 +63,20 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||
@Autowired
|
||||
private GitUtil gitUtil;
|
||||
|
||||
@Autowired
|
||||
private ISIPCommander commander;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private SIPRequestHeaderProvider headerProvider;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="udpSipProvider")
|
||||
private SipProviderImpl udpSipProvider;
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// 添加消息处理的订阅
|
||||
@ -71,7 +94,8 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||
@Override
|
||||
public void process(ResponseEvent evt ){
|
||||
try {
|
||||
Response response = evt.getResponse();
|
||||
|
||||
SIPResponse response = (SIPResponse)evt.getResponse();
|
||||
int statusCode = response.getStatusCode();
|
||||
// trying不会回复
|
||||
if (statusCode == Response.TRYING) {
|
||||
@ -80,10 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||
// 下发ack
|
||||
if (statusCode == Response.OK) {
|
||||
ResponseEventExt event = (ResponseEventExt)evt;
|
||||
SIPDialog dialog = new SIPDialog((SIPClientTransaction) event.getClientTransaction(), (SIPResponse) event.getResponse());
|
||||
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
||||
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
||||
|
||||
String contentString = new String(response.getRawContent());
|
||||
// jainSip不支持y=字段, 移除以解析。
|
||||
int ssrcIndex = contentString.indexOf("y=");
|
||||
@ -96,29 +117,15 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||
} else {
|
||||
sdp = SdpFactory.getInstance().createSessionDescription(contentString);
|
||||
}
|
||||
requestURI.setUser(sdp.getOrigin().getUsername());
|
||||
try {
|
||||
requestURI.setHost(event.getRemoteIpAddress());
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
requestURI.setPort(event.getRemotePort());
|
||||
reqAck.setRequestURI(requestURI);
|
||||
UserAgentHeader userAgentHeader = SipUtils.createUserAgentHeader(sipFactory, gitUtil);
|
||||
reqAck.addHeader(userAgentHeader);
|
||||
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
|
||||
reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||
logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
|
||||
SipURI requestUri = sipFactory.createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
|
||||
Request reqAck = headerProvider.createAckRequest(requestUri, response);
|
||||
|
||||
dialog.sendAck(reqAck);
|
||||
logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());
|
||||
commander.transmitRequest(response.getTopmostViaHeader().getTransport(), reqAck, null, null);
|
||||
|
||||
}
|
||||
} catch (InvalidArgumentException | SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (SdpParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
|
||||
logger.info("[点播回复ACK],异常:", e );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,13 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.ResponseEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.header.WWWAuthenticateHeader;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* @description:Register响应处理器
|
||||
@ -87,7 +90,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
|
||||
|
||||
if (response.getStatusCode() == Response.UNAUTHORIZED) {
|
||||
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
|
||||
try {
|
||||
sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage());
|
||||
}
|
||||
}else if (response.getStatusCode() == Response.OK){
|
||||
|
||||
if (platformRegisterInfo.isRegister()) {
|
||||
|
@ -70,4 +70,47 @@ public class SipUtils {
|
||||
return String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 云台指令码计算
|
||||
*
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
* @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
|
||||
* @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
|
||||
*/
|
||||
public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) {
|
||||
int cmdCode = 0;
|
||||
if (leftRight == 2) {
|
||||
cmdCode|=0x01; // 右移
|
||||
} else if(leftRight == 1) {
|
||||
cmdCode|=0x02; // 左移
|
||||
}
|
||||
if (upDown == 2) {
|
||||
cmdCode|=0x04; // 下移
|
||||
} else if(upDown == 1) {
|
||||
cmdCode|=0x08; // 上移
|
||||
}
|
||||
if (inOut == 2) {
|
||||
cmdCode |= 0x10; // 放大
|
||||
} else if(inOut == 1) {
|
||||
cmdCode |= 0x20; // 缩小
|
||||
}
|
||||
StringBuilder builder = new StringBuilder("A50F01");
|
||||
String strTmp;
|
||||
strTmp = String.format("%02X", cmdCode);
|
||||
builder.append(strTmp, 0, 2);
|
||||
strTmp = String.format("%02X", moveSpeed);
|
||||
builder.append(strTmp, 0, 2);
|
||||
builder.append(strTmp, 0, 2);
|
||||
strTmp = String.format("%X", zoomSpeed);
|
||||
builder.append(strTmp, 0, 1).append("0");
|
||||
//计算校验码
|
||||
int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100;
|
||||
strTmp = String.format("%02X", checkCode);
|
||||
builder.append(strTmp, 0, 2);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.media.zlm;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -7,6 +8,7 @@ import java.util.Map;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
@ -31,6 +33,8 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
|
||||
/**
|
||||
* @description:针对 ZLMediaServer的hook事件监听
|
||||
@ -58,6 +62,9 @@ public class ZLMHttpHookListener {
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@ -515,7 +522,11 @@ public class ZLMHttpHookListener {
|
||||
String platformId = sendRtpItem.getPlatformId();
|
||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
|
||||
|
||||
try {
|
||||
commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -552,21 +563,41 @@ public class ZLMHttpHookListener {
|
||||
if (sendRtpItems.size() > 0) {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
|
||||
try {
|
||||
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
|
||||
sendRtpItem.getCallId(), sendRtpItem.getStreamId());
|
||||
}
|
||||
}
|
||||
}
|
||||
cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
|
||||
Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
|
||||
if (device != null) {
|
||||
try {
|
||||
cmder.streamByeCmd(device, streamInfoForPlayCatch.getChannelId(),
|
||||
streamInfoForPlayCatch.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
|
||||
logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
redisCatchStorage.stopPlay(streamInfoForPlayCatch);
|
||||
storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
|
||||
}else{
|
||||
StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
|
||||
if (streamInfoForPlayBackCatch != null) {
|
||||
cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(),
|
||||
streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
|
||||
Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
|
||||
if (device != null) {
|
||||
try {
|
||||
cmder.streamByeCmd(device,streamInfoForPlayBackCatch.getChannelId(),
|
||||
streamInfoForPlayBackCatch.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException |
|
||||
SsrcTransactionNotFoundException e) {
|
||||
logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
|
||||
streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
|
||||
}else {
|
||||
@ -689,7 +720,11 @@ public class ZLMHttpHookListener {
|
||||
if (sendRtpItems.size() > 0) {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
|
||||
try {
|
||||
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
|
||||
sendRtpItem.getCallId(), sendRtpItem.getStreamId());
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ public class ZLMMediaListManager {
|
||||
private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
|
||||
|
||||
public StreamPushItem addPush(MediaItem mediaItem) {
|
||||
// 查找此直播流是否存在redis预设gbId
|
||||
StreamPushItem transform = streamPushService.transform(mediaItem);
|
||||
StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
|
||||
transform.setPushIng(mediaItem.isRegist());
|
||||
@ -82,16 +81,15 @@ public class ZLMMediaListManager {
|
||||
streamPushMapper.update(transform);
|
||||
gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId());
|
||||
}
|
||||
if (transform != null) {
|
||||
if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) {
|
||||
ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream());
|
||||
if ( channelOnlineEventLister != null) {
|
||||
try {
|
||||
getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
|
||||
channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());;
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
logger.error("addPush: ", e);
|
||||
}
|
||||
removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
|
||||
}
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
@ -99,11 +97,12 @@ public class ZLMMediaListManager {
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
// 查看推流状态
|
||||
if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
|
||||
if (getChannelOnlineEventLister(app, stream) != null) {
|
||||
ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream);
|
||||
if (channelOnlineEventLister != null) {
|
||||
try {
|
||||
getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
|
||||
channelOnlineEventLister.run(app, stream, mediaServerId);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
logger.error("sendStreamEvent: ", e);
|
||||
}
|
||||
removedChannelOnlineEventLister(app, stream);
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -95,7 +98,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
|
||||
deviceMapper.add(device);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
try {
|
||||
commander.deviceInfoQuery(device);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
|
||||
}
|
||||
sync(device);
|
||||
}else {
|
||||
if(device.getOnline() == 0){
|
||||
@ -104,7 +111,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
|
||||
deviceMapper.update(device);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
try {
|
||||
commander.deviceInfoQuery(device);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
|
||||
}
|
||||
sync(device);
|
||||
// TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
|
||||
}else {
|
||||
@ -129,6 +140,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
@Override
|
||||
public void offline(String deviceId) {
|
||||
logger.info("[设备离线], device:{}", deviceId);
|
||||
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
|
||||
if (device == null) {
|
||||
return;
|
||||
@ -238,15 +250,28 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
int sn = (int)((Math.random()*9+1)*100000);
|
||||
catalogResponseMessageHandler.setChannelSyncReady(device, sn);
|
||||
try {
|
||||
sipCommander.catalogQuery(device, sn, event -> {
|
||||
String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg);
|
||||
catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
|
||||
});
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[同步通道], 信令发送失败:{}", e.getMessage() );
|
||||
String errorMsg = String.format("同步通道失败,信令发送失败: %s", e.getMessage());
|
||||
catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Device queryDevice(String deviceId) {
|
||||
return deviceMapper.getDeviceByDeviceId(deviceId);
|
||||
Device device = redisCatchStorage.getDevice(deviceId);
|
||||
if (device == null) {
|
||||
device = deviceMapper.getDeviceByDeviceId(deviceId);
|
||||
if (device != null) {
|
||||
redisCatchStorage.updateDevice(device);
|
||||
}
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -266,7 +291,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
if (device == null || device.getOnline() == 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sipCommander.deviceStatusQuery(device, null);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 设备状态查询: {}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,10 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.TimeoutEvent;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -99,9 +102,13 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
if (parentPlatform.isEnable()) {
|
||||
// 保存时启用就发送注册
|
||||
// 注册成功时由程序直接调用了online方法
|
||||
try {
|
||||
commanderForPlatform.register(parentPlatform, eventResult -> {
|
||||
logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
|
||||
}, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
return result > 0;
|
||||
}
|
||||
@ -130,14 +137,22 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
// 添加注册任务
|
||||
dynamicTask.startDelay(registerTaskKey,
|
||||
// 注册失败(注册成功时由程序直接调用了online方法)
|
||||
()->commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null),
|
||||
()-> {
|
||||
try {
|
||||
commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
|
||||
}
|
||||
},
|
||||
(parentPlatform.getExpires() - 10) *1000);
|
||||
|
||||
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
|
||||
if (!dynamicTask.contains(keepaliveTaskKey)) {
|
||||
// 添加心跳任务
|
||||
dynamicTask.startCron(keepaliveTaskKey,
|
||||
()-> commanderForPlatform.keepalive(parentPlatform, eventResult -> {
|
||||
()-> {
|
||||
try {
|
||||
commanderForPlatform.keepalive(parentPlatform, eventResult -> {
|
||||
// 心跳失败
|
||||
if (eventResult.type == SipSubscribe.EventResultType.timeout) {
|
||||
// 心跳超时
|
||||
@ -147,6 +162,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
// 设置平台离线,并重新注册
|
||||
offline(parentPlatform);
|
||||
logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId());
|
||||
try {
|
||||
commanderForPlatform.register(parentPlatform, eventResult1 -> {
|
||||
logger.info("[国标级联] {},三次心跳超时后再次发起注册仍然失败,开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
|
||||
// 添加注册任务
|
||||
@ -155,6 +171,9 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
|
||||
60*1000);
|
||||
}, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}else {
|
||||
@ -169,7 +188,11 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
platformCatch.setKeepAliveReply(0);
|
||||
redisCatchStorage.updatePlatformCatchInfo(platformCatch);
|
||||
}
|
||||
}),
|
||||
});
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage());
|
||||
}
|
||||
},
|
||||
(parentPlatform.getKeepTimeout() - 10)*1000);
|
||||
}
|
||||
}
|
||||
@ -225,6 +248,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
@Override
|
||||
public void login(ParentPlatform parentPlatform) {
|
||||
final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
|
||||
try {
|
||||
commanderForPlatform.register(parentPlatform, eventResult1 -> {
|
||||
logger.info("[国标级联] {},开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
|
||||
// 添加注册任务
|
||||
@ -233,6 +257,9 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
|
||||
60*1000);
|
||||
}, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联注册: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -259,7 +286,12 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
continue;
|
||||
}
|
||||
// 发送GPS消息
|
||||
try {
|
||||
commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
logger.error("[命令发送失败] 国标级联 移动位置通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,17 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.ResponseEvent;
|
||||
import javax.sip.SipException;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -22,13 +28,6 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
@ -92,6 +91,10 @@ public class PlayServiceImpl implements IPlayService {
|
||||
@Autowired
|
||||
private VideoStreamSessionManager streamSession;
|
||||
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@ -258,14 +261,14 @@ public class PlayServiceImpl implements IPlayService {
|
||||
System.out.println("设置超时任务: " + timeOutTaskKey);
|
||||
dynamicTask.startDelay( timeOutTaskKey,()->{
|
||||
|
||||
SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
|
||||
if (dialog != null) {
|
||||
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
|
||||
timeoutCallback.run(1, "收流超时");
|
||||
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
|
||||
cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null);
|
||||
}else {
|
||||
logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
|
||||
try {
|
||||
cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[点播超时], 发送BYE失败 {}", e.getMessage());
|
||||
} catch (SsrcTransactionNotFoundException e) {
|
||||
timeoutCallback.run(0, "点播超时");
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
|
||||
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
|
||||
@ -279,6 +282,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
|
||||
logger.info("收到订阅消息: " + response.toJSONString());
|
||||
System.out.println("停止超时任务: " + timeOutTaskKey);
|
||||
@ -346,6 +350,19 @@ public class PlayServiceImpl implements IPlayService {
|
||||
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
|
||||
errorEvent.response(event);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
|
||||
logger.error("[命令发送失败] 点播消息: {}", e.getMessage());
|
||||
dynamicTask.stop(timeOutTaskKey);
|
||||
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
|
||||
// 释放ssrc
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
|
||||
|
||||
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
|
||||
eventResult.msg = "命令发送失败";
|
||||
errorEvent.response(eventResult);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -436,17 +453,18 @@ public class PlayServiceImpl implements IPlayService {
|
||||
playBackResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
playBackResult.setMsg("回放超时");
|
||||
playBackResult.setData(requestMessage);
|
||||
SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
|
||||
|
||||
try {
|
||||
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage());
|
||||
} catch (SsrcTransactionNotFoundException e) {
|
||||
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
|
||||
if (dialog != null) {
|
||||
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
|
||||
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
|
||||
}else {
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
|
||||
streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
|
||||
}
|
||||
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
|
||||
|
||||
// 回复之前所有的点播请求
|
||||
playBackCallback.call(playBackResult);
|
||||
result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
|
||||
@ -486,6 +504,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
playBackCallback.call(playBackResult);
|
||||
};
|
||||
|
||||
try {
|
||||
cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
|
||||
hookEvent, eventResult -> {
|
||||
if (eventResult.type == SipSubscribe.EventResultType.response) {
|
||||
@ -539,6 +558,13 @@ public class PlayServiceImpl implements IPlayService {
|
||||
}
|
||||
|
||||
}, errorEvent);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 回放: {}", e.getMessage());
|
||||
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
|
||||
eventResult.msg = "命令发送失败";
|
||||
errorEvent.response(eventResult);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -584,20 +610,33 @@ public class PlayServiceImpl implements IPlayService {
|
||||
downloadResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
downloadResult.setMsg("录像下载请求超时");
|
||||
hookCallBack.call(downloadResult);
|
||||
SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
|
||||
|
||||
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
|
||||
if (dialog != null) {
|
||||
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
|
||||
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
|
||||
}else {
|
||||
try {
|
||||
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[录像流]录像下载请求超时, 发送BYE失败 {}", e.getMessage());
|
||||
} catch (SsrcTransactionNotFoundException e) {
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
|
||||
streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
|
||||
}
|
||||
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
|
||||
// 回复之前所有的点播请求
|
||||
hookCallBack.call(downloadResult);
|
||||
}, userSetting.getPlayTimeout());
|
||||
|
||||
SipSubscribe.Event errorEvent = event -> {
|
||||
dynamicTask.stop(downLoadTimeOutTaskKey);
|
||||
downloadResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
|
||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
|
||||
downloadResult.setEvent(event);
|
||||
hookCallBack.call(downloadResult);
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
};
|
||||
|
||||
try {
|
||||
cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
|
||||
inviteStreamInfo -> {
|
||||
logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
|
||||
@ -614,16 +653,14 @@ public class PlayServiceImpl implements IPlayService {
|
||||
downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
|
||||
downloadResult.setResponse(inviteStreamInfo.getResponse());
|
||||
hookCallBack.call(downloadResult);
|
||||
}, event -> {
|
||||
dynamicTask.stop(downLoadTimeOutTaskKey);
|
||||
downloadResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
|
||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
|
||||
downloadResult.setEvent(event);
|
||||
hookCallBack.call(downloadResult);
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
});
|
||||
}, errorEvent);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
|
||||
|
||||
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
|
||||
eventResult.msg = "命令发送失败";
|
||||
errorEvent.response(eventResult);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -702,7 +739,11 @@ public class PlayServiceImpl implements IPlayService {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
|
||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
|
||||
try {
|
||||
sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -711,8 +752,17 @@ public class PlayServiceImpl implements IPlayService {
|
||||
if (allSsrc.size() > 0) {
|
||||
for (SsrcTransaction ssrcTransaction : allSsrc) {
|
||||
if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) {
|
||||
cmder.streamByeCmd(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(),
|
||||
Device device = deviceService.queryDevice(ssrcTransaction.getDeviceId());
|
||||
if (device == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(),
|
||||
ssrcTransaction.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException |
|
||||
SsrcTransactionNotFoundException e) {
|
||||
logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
@ -76,16 +79,28 @@ public class RedisAlarmMsgListener implements MessageListener {
|
||||
List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
|
||||
if (parentPlatforms.size() > 0) {
|
||||
for (ParentPlatform parentPlatform : parentPlatforms) {
|
||||
try {
|
||||
commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
Device device = storage.queryVideoDevice(gbId);
|
||||
ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
|
||||
if (device != null && platform == null) {
|
||||
try {
|
||||
commander.sendAlarmMessage(device, deviceAlarm);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
|
||||
}
|
||||
}else if (device == null && platform != null){
|
||||
try {
|
||||
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
|
||||
}
|
||||
}else {
|
||||
logger.warn("无法确定" + gbId + "是平台还是设备");
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -31,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
|
||||
/**
|
||||
* 位置信息管理
|
||||
*/
|
||||
@ -105,6 +109,7 @@ public class MobilePositionController {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
|
||||
try {
|
||||
cmder.mobilePostitionQuery(device, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -112,6 +117,10 @@ public class MobilePositionController {
|
||||
msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 获取移动位置信息: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取移动位置信息超时"));
|
||||
|
@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener;
|
||||
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
@ -16,6 +17,8 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -23,6 +26,9 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -33,6 +39,8 @@ import java.util.List;
|
||||
@RequestMapping("/api/alarm")
|
||||
public class AlarmController {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AlarmController.class);
|
||||
|
||||
@Autowired
|
||||
private IDeviceAlarmService deviceAlarmService;
|
||||
|
||||
@ -108,9 +116,19 @@ public class AlarmController {
|
||||
deviceAlarm.setLatitude(39.33333);
|
||||
|
||||
if (device != null && platform == null) {
|
||||
|
||||
try {
|
||||
commander.sendAlarmMessage(device, deviceAlarm);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
|
||||
}
|
||||
}else if (device == null && platform != null){
|
||||
try {
|
||||
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}else {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(),"无法确定" + deviceId + "是平台还是设备");
|
||||
}
|
||||
|
@ -8,12 +8,14 @@
|
||||
package com.genersoft.iot.vmp.vmanager.gb28181.device;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
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.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -26,6 +28,9 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Tag(name = "国标设备配置")
|
||||
@ -75,6 +80,7 @@ public class DeviceConfig {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
|
||||
try {
|
||||
cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -82,6 +88,10 @@ public class DeviceConfig {
|
||||
msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 设备配置: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<String> result = new DeferredResult<String>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
|
||||
@ -121,6 +131,7 @@ public class DeviceConfig {
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
try {
|
||||
cmder.deviceConfigQuery(device, channelId, configType, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -128,6 +139,10 @@ public class DeviceConfig {
|
||||
msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<String> result = new DeferredResult<String > (3 * 1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取设备配置超时"));
|
||||
|
@ -29,6 +29,9 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Tag(name = "国标设备控制")
|
||||
@ -61,9 +64,11 @@ public class DeviceControl {
|
||||
logger.debug("设备远程启动API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (!cmder.teleBootCmd(device)) {
|
||||
logger.warn("设备远程启动API调用失败!");
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
try {
|
||||
cmder.teleBootCmd(device);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 远程启动: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,6 +106,7 @@ public class DeviceControl {
|
||||
return result;
|
||||
}
|
||||
resultHolder.put(key, uuid, result);
|
||||
try {
|
||||
cmder.recordCmd(device, channelId, recordCmdStr, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -108,6 +114,10 @@ public class DeviceControl {
|
||||
msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeAllResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -123,13 +133,14 @@ public class DeviceControl {
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
|
||||
@GetMapping("/guard/{deviceId}/{guardCmdStr}")
|
||||
public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
|
||||
public DeferredResult<String> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("布防/撤防API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
|
||||
String uuid =UUID.randomUUID().toString();
|
||||
try {
|
||||
cmder.guardCmd(device, guardCmdStr, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -137,7 +148,11 @@ public class DeviceControl {
|
||||
msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<String> result = new DeferredResult<>(3 * 1000L);
|
||||
resultHolder.put(key, uuid, result);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
|
||||
@ -174,6 +189,7 @@ public class DeviceControl {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
|
||||
try {
|
||||
cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -181,6 +197,10 @@ public class DeviceControl {
|
||||
msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 报警复位: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
|
||||
@ -205,23 +225,23 @@ public class DeviceControl {
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号")
|
||||
@GetMapping("/i_frame/{deviceId}")
|
||||
public ResponseEntity<String> iFrame(@PathVariable String deviceId,
|
||||
public JSONObject iFrame(@PathVariable String deviceId,
|
||||
@RequestParam(required = false) String channelId) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("强制关键帧API调用");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
boolean sucsess = cmder.iFrameCmd(device, channelId);
|
||||
if (sucsess) {
|
||||
try {
|
||||
cmder.iFrameCmd(device, channelId);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("DeviceID", deviceId);
|
||||
json.put("ChannelID", channelId);
|
||||
json.put("Result", "OK");
|
||||
return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
|
||||
} else {
|
||||
logger.warn("强制关键帧API调用失败!");
|
||||
return new ResponseEntity<String>("强制关键帧API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,7 +260,7 @@ public class DeviceControl {
|
||||
@Parameter(name = "presetIndex", description = "调用预置位编号")
|
||||
@Parameter(name = "resetTime", description = "自动归位时间间隔")
|
||||
@GetMapping("/home_position/{deviceId}/{enabled}")
|
||||
public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
|
||||
public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
|
||||
@PathVariable String enabled,
|
||||
@RequestParam(required = false) String resetTime,
|
||||
@RequestParam(required = false) String presetIndex,
|
||||
@ -251,6 +271,7 @@ public class DeviceControl {
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
try {
|
||||
cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -258,7 +279,11 @@ public class DeviceControl {
|
||||
msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 看守位控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<String> result = new DeferredResult<>(3 * 1000L);
|
||||
result.onTimeout(() -> {
|
||||
logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
|
||||
// 释放rtpserver
|
||||
@ -297,14 +322,14 @@ public class DeviceControl {
|
||||
@Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
|
||||
@Parameter(name = "lengthy", description = "lengthy", required = true)
|
||||
@GetMapping("drag_zoom/zoom_in")
|
||||
public ResponseEntity<String> dragZoomIn(@RequestParam String deviceId,
|
||||
public void dragZoomIn(@RequestParam String deviceId,
|
||||
@RequestParam(required = false) String channelId,
|
||||
@RequestParam int length,
|
||||
@RequestParam int width,
|
||||
@RequestParam int midpointx,
|
||||
@RequestParam int midpointy,
|
||||
@RequestParam int lengthx,
|
||||
@RequestParam int lengthy){
|
||||
@RequestParam int lengthy) throws RuntimeException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("设备拉框放大 API调用,deviceId:%s ,channelId:%s ,length:%d ,width:%d ,midpointx:%d ,midpointy:%d ,lengthx:%d ,lengthy:%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy));
|
||||
}
|
||||
@ -318,8 +343,12 @@ public class DeviceControl {
|
||||
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
|
||||
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
|
||||
cmdXml.append("</DragZoomIn>\r\n");
|
||||
try {
|
||||
cmder.dragZoomCmd(device, channelId, cmdXml.toString());
|
||||
return new ResponseEntity<String>("success", HttpStatus.OK);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 拉框放大: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,7 +373,7 @@ public class DeviceControl {
|
||||
@Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
|
||||
@Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
|
||||
@GetMapping("/drag_zoom/zoom_out")
|
||||
public ResponseEntity<String> dragZoomOut(@RequestParam String deviceId,
|
||||
public void dragZoomOut(@RequestParam String deviceId,
|
||||
@RequestParam(required = false) String channelId,
|
||||
@RequestParam int length,
|
||||
@RequestParam int width,
|
||||
@ -366,7 +395,11 @@ public class DeviceControl {
|
||||
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
|
||||
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
|
||||
cmdXml.append("</DragZoomOut>\r\n");
|
||||
try {
|
||||
cmder.dragZoomCmd(device, channelId, cmdXml.toString());
|
||||
return new ResponseEntity<String>("success",HttpStatus.OK);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 拉框缩小: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,11 @@ import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.sip.DialogState;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
@Tag(name = "国标设备查询", description = "国标设备查询")
|
||||
@ -315,6 +318,7 @@ public class DeviceQuery {
|
||||
result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK));
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
cmder.deviceStatusQuery(device, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -322,6 +326,10 @@ public class DeviceQuery {
|
||||
msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("获取设备状态超时"));
|
||||
// 释放rtpserver
|
||||
@ -368,6 +376,7 @@ public class DeviceQuery {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId;
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
try {
|
||||
cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -375,6 +384,10 @@ public class DeviceQuery {
|
||||
msg.setData(String.format("设备报警查询失败,错误码: %s, %s",event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 设备报警查询: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
|
||||
result.onTimeout(()->{
|
||||
logger.warn(String.format("设备报警查询超时"));
|
||||
|
@ -29,6 +29,9 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -212,20 +215,37 @@ public class PlatformController {
|
||||
// 保存时启用就发送注册
|
||||
if (parentPlatform.isEnable()) {
|
||||
if (parentPlatformOld != null && parentPlatformOld.isStatus()) {
|
||||
try {
|
||||
commanderForPlatform.unregister(parentPlatformOld, null, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
||||
}
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("[线程休眠失败] : {}", e.getMessage());
|
||||
}
|
||||
// 只要保存就发送注册
|
||||
try {
|
||||
commanderForPlatform.register(parentPlatform, null, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
|
||||
}
|
||||
|
||||
} else {
|
||||
// 只要保存就发送注册
|
||||
try {
|
||||
commanderForPlatform.register(parentPlatform, null, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
|
||||
try {
|
||||
commanderForPlatform.unregister(parentPlatformOld, null, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
||||
}
|
||||
// 停止订阅相关的定时任务
|
||||
subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
|
||||
}
|
||||
@ -258,6 +278,7 @@ public class PlatformController {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在");
|
||||
}
|
||||
// 发送离线消息,无论是否成功都删除缓存
|
||||
try {
|
||||
commanderForPlatform.unregister(parentPlatform, (event -> {
|
||||
// 清空redis缓存
|
||||
redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
|
||||
@ -269,6 +290,9 @@ public class PlatformController {
|
||||
redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
|
||||
redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
|
||||
}));
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
||||
}
|
||||
|
||||
boolean deleteResult = storager.deleteParentPlatform(parentPlatform);
|
||||
storager.delCatalogByPlatformId(parentPlatform.getServerGBId());
|
||||
|
@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
@ -36,6 +37,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -102,12 +106,23 @@ public class PlayController {
|
||||
throw new ControllerException(ErrorCode.ERROR400);
|
||||
}
|
||||
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在");
|
||||
}
|
||||
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
if (streamInfo == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到");
|
||||
}
|
||||
|
||||
cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, null);
|
||||
try {
|
||||
logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
|
||||
cmder.streamByeCmd(device, channelId, streamInfo.getStream(), null, null);
|
||||
} catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
|
||||
logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
redisCatchStorage.stopPlay(streamInfo);
|
||||
|
||||
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||
@ -221,6 +236,7 @@ public class PlayController {
|
||||
resultHolder.invokeResult(msg);
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
cmder.audioBroadcastCmd(device, (event) -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setKey(key);
|
||||
@ -233,6 +249,10 @@ public class PlayController {
|
||||
msg.setData(json);
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 语音广播: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
result.onTimeout(() -> {
|
||||
logger.warn("语音广播操作超时, 设备未返回应答指令");
|
||||
|
@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
@ -21,12 +22,15 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@ -92,7 +96,15 @@ public class PlaybackController {
|
||||
if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
|
||||
throw new ControllerException(ErrorCode.ERROR400);
|
||||
}
|
||||
cmder.streamByeCmd(deviceId, channelId, stream, null);
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + " 未找到");
|
||||
}
|
||||
try {
|
||||
cmder.streamByeCmd(device, channelId, stream, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "发送bye失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -107,7 +119,11 @@ public class PlaybackController {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
|
||||
try {
|
||||
cmder.playPauseCmd(device, streamInfo);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -122,7 +138,11 @@ public class PlaybackController {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
|
||||
try {
|
||||
cmder.playResumeCmd(device, streamInfo);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -138,7 +158,11 @@ public class PlaybackController {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
|
||||
try {
|
||||
cmder.playSeekCmd(device, streamInfo, seekTime);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "回放倍速播放")
|
||||
@ -157,6 +181,10 @@ public class PlaybackController {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)");
|
||||
}
|
||||
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
|
||||
try {
|
||||
cmder.playSpeedCmd(device, streamInfo, speed);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.genersoft.iot.vmp.vmanager.gb28181.ptz;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -18,6 +20,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Tag(name = "云台控制")
|
||||
@ -98,7 +103,12 @@ public class PtzController {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -117,7 +127,12 @@ public class PtzController {
|
||||
}
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 前端控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -146,6 +161,7 @@ public class PtzController {
|
||||
return result;
|
||||
}
|
||||
resultHolder.put(key, uuid, result);
|
||||
try {
|
||||
cmder.presetQuery(device, channelId, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
@ -153,6 +169,10 @@ public class PtzController {
|
||||
msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
|
||||
resultHolder.invokeResult(msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 获取设备预置位: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
@ -31,6 +33,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -54,6 +59,12 @@ public class GBRecordController {
|
||||
@Autowired
|
||||
private IPlayService playService;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
|
||||
|
||||
|
||||
@Operation(summary = "录像查询")
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@ -81,6 +92,7 @@ public class GBRecordController {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
msg.setKey(key);
|
||||
try {
|
||||
cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
|
||||
WVPResult<RecordInfo> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
@ -88,6 +100,10 @@ public class GBRecordController {
|
||||
msg.setData(wvpResult);
|
||||
resultHolder.invokeResult(msg);
|
||||
}));
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 查询录像: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 录像查询以channelId作为deviceId查询
|
||||
resultHolder.put(key, uuid, result);
|
||||
@ -131,14 +147,24 @@ public class GBRecordController {
|
||||
@GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
|
||||
public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
|
||||
|
||||
cmder.streamByeCmd(deviceId, channelId, stream, null);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId));
|
||||
}
|
||||
|
||||
if (deviceId == null || channelId == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
throw new ControllerException(ErrorCode.ERROR400);
|
||||
}
|
||||
|
||||
Device device = deviceService.queryDevice(deviceId);
|
||||
if (device == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "未找到");
|
||||
}
|
||||
|
||||
try {
|
||||
cmder.streamByeCmd(device, channelId, stream, null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
|
||||
logger.error("[停止历史媒体下载]停止历史媒体下载,发送BYE失败 {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,20 @@
|
||||
package com.genersoft.iot.vmp.web.gb28181;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* API兼容:设备控制
|
||||
*/
|
||||
@ -35,7 +41,7 @@ public class ApiControlController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/ptz")
|
||||
private JSONObject list(String serial,String command,
|
||||
private void list(String serial,String command,
|
||||
@RequestParam(required = false)Integer channel,
|
||||
@RequestParam(required = false)String code,
|
||||
@RequestParam(required = false)Integer speed){
|
||||
@ -48,9 +54,7 @@ public class ApiControlController {
|
||||
if (speed == null) {speed = 0;}
|
||||
Device device = storager.queryVideoDevice(serial);
|
||||
if (device == null) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","device[ " + serial + " ]未找到");
|
||||
return result;
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "device[ " + serial + " ]未找到");
|
||||
}
|
||||
int cmdCode = 0;
|
||||
switch (command){
|
||||
@ -91,7 +95,11 @@ public class ApiControlController {
|
||||
break;
|
||||
}
|
||||
// 默认值 50
|
||||
try {
|
||||
cmder.frontEndCmd(device, code, cmdCode, speed, speed, speed);
|
||||
return null;
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.web.gb28181;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
@ -17,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* API兼容:实时直播
|
||||
*/
|
||||
@ -40,6 +46,9 @@ public class ApiStreamController {
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private IPlayService playService;
|
||||
|
||||
@ -177,7 +186,19 @@ public class ApiStreamController {
|
||||
result.put("error","未找到流信息");
|
||||
return result;
|
||||
}
|
||||
cmder.streamByeCmd(serial, code, streamInfo.getStream(), null);
|
||||
Device device = deviceService.queryDevice(serial);
|
||||
if (device == null) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","未找到设备");
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
cmder.streamByeCmd(device, code, streamInfo.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","发送BYE失败:" + e.getMessage());
|
||||
return result;
|
||||
}
|
||||
redisCatchStorage.stopPlay(streamInfo);
|
||||
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||
return null;
|
||||
|
Loading…
Reference in New Issue
Block a user