dialog去除以及异常情况处理优化

This commit is contained in:
648540858 2022-09-23 22:45:23 +08:00
parent a574ff0944
commit cd117ed228
53 changed files with 3106 additions and 3053 deletions

View File

@ -2,6 +2,9 @@ package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.utils.DateUtil; 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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@ -15,6 +18,8 @@ import java.util.regex.Pattern;
@Configuration("mediaConfig") @Configuration("mediaConfig")
public class MediaConfig{ public class MediaConfig{
private final static Logger logger = LoggerFactory.getLogger(MediaConfig.class);
// 修改必须配置不再支持自动获取 // 修改必须配置不再支持自动获取
@Value("${media.id}") @Value("${media.id}")
private String id; private String id;
@ -174,7 +179,7 @@ public class MediaConfig{
try { try {
hostAddress = InetAddress.getByName(sdpIp).getHostAddress(); hostAddress = InetAddress.getByName(sdpIp).getHostAddress();
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
throw new RuntimeException(e); logger.error("[获取SDP IP]: 域名解析失败");
} }
return hostAddress; return hostAddress;
} }

View File

@ -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();
}
}

View File

@ -41,7 +41,7 @@ public class SipLayer{
@Bean("sipStack") @Bean("sipStack")
@DependsOn({"sipFactory"}) @DependsOn({"sipFactory"})
SipStack createSipStack() throws PeerUnavailableException { SipStackImpl createSipStack() throws PeerUnavailableException {
sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false)); sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
return sipStack; return sipStack;
} }
@ -56,7 +56,6 @@ public class SipLayer{
tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint); tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
tcpSipProvider.setDialogErrorsAutomaticallyHandled(); tcpSipProvider.setDialogErrorsAutomaticallyHandled();
tcpSipProvider.addSipListener(sipProcessorObserver); tcpSipProvider.addSipListener(sipProcessorObserver);
// tcpSipProvider.setAutomaticDialogSupportEnabled(false);
logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort()); logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort());
} catch (TransportNotSupportedException e) { } catch (TransportNotSupportedException e) {
e.printStackTrace(); e.printStackTrace();
@ -80,7 +79,6 @@ public class SipLayer{
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP"); udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint); udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
udpSipProvider.addSipListener(sipProcessorObserver); udpSipProvider.addSipListener(sipProcessorObserver);
// udpSipProvider.setAutomaticDialogSupportEnabled(false);
} catch (TransportNotSupportedException e) { } catch (TransportNotSupportedException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

View File

@ -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;
}
}

View File

@ -4,6 +4,9 @@ import javax.sip.Dialog;
import java.util.EventObject; import java.util.EventObject;
public class DeviceNotFoundEvent extends EventObject { public class DeviceNotFoundEvent extends EventObject {
private String callId;
/** /**
* Constructs a prototypical Event. * Constructs a prototypical Event.
* *
@ -14,8 +17,11 @@ public class DeviceNotFoundEvent extends EventObject {
super(dialog); super(dialog);
} }
public String getCallId() {
return callId;
}
public Dialog getDialog() { public void setCallId(String callId) {
return (Dialog)super.getSource(); this.callId = callId;
} }
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.bean; package com.genersoft.iot.vmp.gb28181.bean;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
public class SipTransactionInfo { public class SipTransactionInfo {
@ -9,11 +10,11 @@ public class SipTransactionInfo {
private String toTag; private String toTag;
private String viaBranch; private String viaBranch;
public SipTransactionInfo(SIPRequest request) { public SipTransactionInfo(SIPResponse response) {
this.callId = request.getCallIdHeader().getCallId(); this.callId = response.getCallIdHeader().getCallId();
this.fromTag = request.getFromTag(); this.fromTag = response.getFromTag();
this.toTag = request.getToTag(); this.toTag = response.getToTag();
this.viaBranch = request.getTopmostViaHeader().getBranch(); this.viaBranch = response.getTopmostViaHeader().getBranch();
} }
public SipTransactionInfo() { public SipTransactionInfo() {

View File

@ -8,10 +8,11 @@ public class SsrcTransaction {
private String channelId; private String channelId;
private String callId; private String callId;
private String stream; private String stream;
private byte[] transaction;
private byte[] dialog;
private String mediaServerId; private String mediaServerId;
private String ssrc; private String ssrc;
private SipTransactionInfo sipTransactionInfo;
private VideoStreamSessionManager.SessionType type; private VideoStreamSessionManager.SessionType type;
public String getDeviceId() { public String getDeviceId() {
@ -46,22 +47,6 @@ public class SsrcTransaction {
this.stream = stream; 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() { public String getMediaServerId() {
return mediaServerId; return mediaServerId;
} }
@ -85,4 +70,12 @@ public class SsrcTransaction {
public void setType(VideoStreamSessionManager.SessionType type) { public void setType(VideoStreamSessionManager.SessionType type) {
this.type = type; this.type = type;
} }
public SipTransactionInfo getSipTransactionInfo() {
return sipTransactionInfo;
}
public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
this.sipTransactionInfo = sipTransactionInfo;
}
} }

View File

@ -1,15 +1,10 @@
package com.genersoft.iot.vmp.gb28181.bean; 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.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse; 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.ServerTransaction;
import javax.sip.header.*; import javax.sip.header.*;
import javax.sip.message.Request;
public class SubscribeInfo { public class SubscribeInfo {

View File

@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
import javax.sip.*; import javax.sip.*;
import javax.sip.header.CallIdHeader; import javax.sip.header.CallIdHeader;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException;
import java.time.Instant; import java.time.Instant;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -56,8 +57,7 @@ public class SipSubscribe {
logger.debug("errorSubscribes.size:{}",errorSubscribes.size()); logger.debug("errorSubscribes.size:{}",errorSubscribes.size());
} }
public interface Event { public interface Event { void response(EventResult eventResult) ;
void response(EventResult eventResult);
} }
/** /**
@ -81,18 +81,13 @@ public class SipSubscribe {
public EventResultType type; public EventResultType type;
public String msg; public String msg;
public String callId; public String callId;
public Dialog dialog;
public EventObject event; public EventObject event;
public EventResult() {
}
public EventResult(EventObject event) { public EventResult(EventObject event) {
this.event = event; this.event = event;
if (event instanceof ResponseEvent) { if (event instanceof ResponseEvent) {
ResponseEvent responseEvent = (ResponseEvent)event; ResponseEvent responseEvent = (ResponseEvent)event;
Response response = responseEvent.getResponse(); Response response = responseEvent.getResponse();
this.dialog = responseEvent.getDialog();
this.type = EventResultType.response; this.type = EventResultType.response;
if (response != null) { if (response != null) {
this.msg = response.getReasonPhrase(); this.msg = response.getReasonPhrase();
@ -127,12 +122,10 @@ public class SipSubscribe {
this.statusCode = -1024; this.statusCode = -1024;
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
}else if (event instanceof DeviceNotFoundEvent) { }else if (event instanceof DeviceNotFoundEvent) {
DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
this.type = EventResultType.deviceNotFoundEvent; this.type = EventResultType.deviceNotFoundEvent;
this.msg = "设备未找到"; this.msg = "设备未找到";
this.statusCode = -1024; this.statusCode = -1024;
this.dialog = deviceNotFoundEvent.getDialog(); this.callId = ((DeviceNotFoundEvent) event).getCallId();
this.callId = this.dialog != null ?deviceNotFoundEvent.getDialog().getCallId().getCallId() : null;
} }
} }
} }

View File

@ -36,6 +36,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener<RequestTimeo
} }
deviceService.offline(device.getDeviceId()); deviceService.offline(device.getDeviceId());
} }
} }
} }
} }

View File

@ -18,6 +18,9 @@ import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.*; import java.util.*;
/** /**
@ -96,7 +99,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
} }
if (deviceChannelList.size() > 0) { if (deviceChannelList.size() > 0) {
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null); 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) { }else if (parentPlatformMap.keySet().size() > 0) {
for (String gbId : parentPlatformMap.keySet()) { for (String gbId : parentPlatformMap.keySet()) {
@ -112,7 +120,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
DeviceChannel deviceChannel = new DeviceChannel(); DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setChannelId(gbId); deviceChannel.setChannelId(gbId);
deviceChannelList.add(deviceChannel); deviceChannelList.add(deviceChannel);
sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null); 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) { if (deviceChannelList.size() > 0) {
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null); 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) { }else if (parentPlatformMap.keySet().size() > 0) {
for (String gbId : parentPlatformMap.keySet()) { for (String gbId : parentPlatformMap.keySet()) {
@ -157,7 +175,12 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform); DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform);
deviceChannelList.add(deviceChannelByStream); deviceChannelList.add(deviceChannelByStream);
} }
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null); try {
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null);
} catch (InvalidArgumentException | ParseException | NoSuchFieldException |
SipException | IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
}
} }
} }
} }

View File

@ -8,9 +8,13 @@ import javax.sip.Dialog;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting; 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.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.utils.SerializeUtils; import com.genersoft.iot.vmp.utils.SerializeUtils;
import com.genersoft.iot.vmp.utils.redis.RedisUtil; 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 gov.nist.javax.sip.stack.SIPDialog;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -42,15 +46,14 @@ public class VideoStreamSessionManager {
* @param callId 一次请求的CallID * @param callId 一次请求的CallID
* @param stream 流名称 * @param stream 流名称
* @param mediaServerId 所使用的流媒体ID * @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 ssrcTransaction = new SsrcTransaction();
ssrcTransaction.setDeviceId(deviceId); ssrcTransaction.setDeviceId(deviceId);
ssrcTransaction.setChannelId(channelId); ssrcTransaction.setChannelId(channelId);
ssrcTransaction.setStream(stream); ssrcTransaction.setStream(stream);
byte[] transactionByteArray = SerializeUtils.serialize(transaction); ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
ssrcTransaction.setTransaction(transactionByteArray);
ssrcTransaction.setCallId(callId); ssrcTransaction.setCallId(callId);
ssrcTransaction.setSsrc(ssrc); ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId); ssrcTransaction.setMediaServerId(mediaServerId);
@ -62,53 +65,6 @@ public class VideoStreamSessionManager {
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); + "_" + 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){ public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
if (ObjectUtils.isEmpty(deviceId)) { if (ObjectUtils.isEmpty(deviceId)) {

View File

@ -10,9 +10,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sip.Dialog; import javax.sip.*;
import javax.sip.DialogState;
import javax.sip.ResponseEvent;
import javax.sip.header.ToHeader; import javax.sip.header.ToHeader;
import java.text.ParseException; import java.text.ParseException;
import java.util.Timer; import java.util.Timer;
@ -44,23 +42,29 @@ public class CatalogSubscribeTask implements ISubscribeTask {
if (dynamicTask.get(taskKey) != null) { if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> { SIPRequest sipRequest = null;
ResponseEvent event = (ResponseEvent) eventResult.event; try {
// 成功 sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
logger.info("[目录订阅]成功: {}", device.getDeviceId()); ResponseEvent event = (ResponseEvent) eventResult.event;
ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME); // 成功
try { logger.info("[目录订阅]成功: {}", device.getDeviceId());
this.request.getToHeader().setTag(toHeader.getTag()); ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
} catch (ParseException e) { try {
logger.info("[目录订阅]成功: 但为request设置ToTag失败"); this.request.getToHeader().setTag(toHeader.getTag());
} catch (ParseException e) {
logger.info("[目录订阅]成功: 但为request设置ToTag失败");
this.request = null;
}
},eventResult -> {
this.request = null; this.request = null;
} // 失败
},eventResult -> { logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
this.request = null; dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
// 失败 });
logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); } catch (InvalidArgumentException | SipException | ParseException e) {
dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000); logger.error("[命令发送失败] 目录订阅: {}", e.getMessage());
});
}
if (sipRequest != null) { if (sipRequest != null) {
this.request = sipRequest; this.request = sipRequest;
} }
@ -80,18 +84,22 @@ public class CatalogSubscribeTask implements ISubscribeTask {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
device.setSubscribeCycleForCatalog(0); device.setSubscribeCycleForCatalog(0);
sipCommander.catalogSubscribe(device, request, eventResult -> { try {
ResponseEvent event = (ResponseEvent) eventResult.event; sipCommander.catalogSubscribe(device, request, eventResult -> {
if (event.getResponse().getRawContent() != null) { ResponseEvent event = (ResponseEvent) eventResult.event;
// 成功 if (event.getResponse().getRawContent() != null) {
logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); // 成功
}else { logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
// 成功 }else {
logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId()); // 成功
} logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
},eventResult -> { }
// 失败 },eventResult -> {
logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); // 失败
}); logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 取消目录订阅订阅: {}", e.getMessage());
}
} }
} }

View File

@ -11,9 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import javax.sip.Dialog; import javax.sip.*;
import javax.sip.DialogState;
import javax.sip.ResponseEvent;
import javax.sip.header.ToHeader; import javax.sip.header.ToHeader;
import java.text.ParseException; import java.text.ParseException;
import java.util.Timer; import java.util.Timer;
@ -43,23 +41,28 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
if (dynamicTask.get(taskKey) != null) { if (dynamicTask.get(taskKey) != null) {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> { SIPRequest sipRequest = null;
// 成功 try {
logger.info("[移动位置订阅]成功: {}", device.getDeviceId()); sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
ResponseEvent event = (ResponseEvent) eventResult.event; // 成功
ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME); logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
try { ResponseEvent event = (ResponseEvent) eventResult.event;
this.request.getToHeader().setTag(toHeader.getTag()); ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
} catch (ParseException e) { try {
logger.info("[移动位置订阅]成功: 为request设置ToTag失败"); this.request.getToHeader().setTag(toHeader.getTag());
} catch (ParseException e) {
logger.info("[移动位置订阅]成功: 为request设置ToTag失败");
this.request = null;
}
},eventResult -> {
this.request = null; this.request = null;
} // 失败
},eventResult -> { logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
this.request = null; dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
// 失败 });
logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); } catch (InvalidArgumentException | SipException | ParseException e) {
dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000); logger.error("[命令发送失败] 移动位置订阅: {}", e.getMessage());
}); }
if (sipRequest != null) { if (sipRequest != null) {
this.request = sipRequest; this.request = sipRequest;
} }
@ -79,18 +82,22 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
dynamicTask.stop(taskKey); dynamicTask.stop(taskKey);
} }
device.setSubscribeCycleForMobilePosition(0); device.setSubscribeCycleForMobilePosition(0);
sipCommander.mobilePositionSubscribe(device, request, eventResult -> { try {
ResponseEvent event = (ResponseEvent) eventResult.event; sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
if (event.getResponse().getRawContent() != null) { ResponseEvent event = (ResponseEvent) eventResult.event;
// 成功 if (event.getResponse().getRawContent() != null) {
logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); // 成功
}else { logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
// 成功 }else {
logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId()); // 成功
} logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
},eventResult -> { }
// 失败 },eventResult -> {
logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg); // 失败
}); logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 取消移动位置订阅: {}", e.getMessage());
}
} }
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd; package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
@ -9,6 +10,11 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import javax.sip.Dialog; 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:设备能力接口用于定义设备的控制查询能力 * @description:设备能力接口用于定义设备的控制查询能力
@ -25,7 +31,7 @@ public interface ISIPCommander {
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 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 upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param moveSpeed 镜头移动速度 * @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 channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @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 channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @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 moveSpeed 镜头移动速度
* @param zoomSpeed 镜头缩放速度 * @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指令预置位指令巡航指令扫描指令和辅助开关指令 * 前端控制包括PTZ指令FI指令预置位指令巡航指令扫描指令和辅助开关指令
@ -79,7 +85,7 @@ public interface ISIPCommander {
* @param parameter2 数据2 * @param parameter2 数据2
* @param combineCode2 组合码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 channelId 预览通道
* @param cmdString 前端控制指令串 * @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 device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 请求回放视频流 * 请求回放视频流
@ -104,7 +110,7 @@ public interface ISIPCommander {
* @param startTime 开始时间,格式要求yyyy-MM-dd HH:mm:ss * @param startTime 开始时间,格式要求yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss * @param endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss
*/ */
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, void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 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(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
void streamByeCmd(String deviceId, String channelId, String stream, String callId); 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,23 +157,24 @@ public interface ISIPCommander {
* @param streamInfo * @param streamInfo
* @param content * @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;
/**
/**
* 语音广播 * 语音广播
* *
* @param device 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @param channelId 预览通道
*/ */
boolean audioBroadcastCmd(Device device,String channelId); void audioBroadcastCmd(Device device,String channelId);
/** /**
* 语音广播 * 语音广播
* *
* @param device 视频设备 * @param device 视频设备
*/ */
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent); void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
boolean audioBroadcastCmd(Device device); void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 音视频录像控制 * 音视频录像控制
@ -176,21 +183,21 @@ public interface ISIPCommander {
* @param channelId 预览通道 * @param channelId 预览通道
* @param recordCmdStr 录像命令Record / StopRecord * @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 视频设备 * @param device 视频设备
*/ */
boolean teleBootCmd(Device device); void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 报警布防/撤防命令 * 报警布防/撤防命令
* *
* @param device 视频设备 * @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 alarmMethod 报警方式可选
* @param alarmType 报警类型可选 * @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帧 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
@ -207,7 +214,7 @@ public interface ISIPCommander {
* @param device 视频设备 * @param device 视频设备
* @param channelId 预览通道 * @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 resetTime 自动归位时间间隔开启看守位时使用单位:(s)
* @param presetIndex 调用预置位编号开启看守位时使用取值范围0~255 * @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 视频设备 * @param device 视频设备
*/ */
boolean deviceConfigCmd(Device device); void deviceConfigCmd(Device device);
/** /**
* 设备配置命令basicParam * 设备配置命令basicParam
@ -236,14 +243,14 @@ public interface ISIPCommander {
* @param heartBeatInterval 心跳间隔时间可选 * @param heartBeatInterval 心跳间隔时间可选
* @param heartBeatCount 心跳超时次数可选 * @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 视频设备 * @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 视频设备 * @param device 视频设备
* @return * @return
*/ */
boolean deviceInfoQuery(Device device); void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询目录列表 * 查询目录列表
* *
* @param device 视频设备 * @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 endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss
* @param sn * @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 报警发生终止时间可选 * @param endTime 报警发生终止时间可选
* @return true = 命令发送成功 * @return true = 命令发送成功
*/ */
boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent); String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/** /**
* 查询设备配置 * 查询设备配置
@ -292,21 +299,21 @@ public interface ISIPCommander {
* @param channelId 通道编码可选 * @param channelId 通道编码可选
* @param configType 配置类型 * @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 视频设备 * @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 视频设备 * @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 视频设备 * @param device 视频设备
* @return true = 命令发送成功 * @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 报警发生终止时间可选 * @param endTime 报警发生终止时间可选
* @return true = 命令发送成功 * @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 视频设备 * @param device 视频设备
* @return true = 命令发送成功 * @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 channelId 通道id
* @param cmdString 前端控制指令串 * @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 报警信息信息 * @param deviceAlarm 报警信息信息
* @return * @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;
} }

View File

@ -4,7 +4,10 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.header.WWWAuthenticateHeader; import javax.sip.header.WWWAuthenticateHeader;
import java.text.ParseException;
import java.util.List; import java.util.List;
public interface ISIPCommanderForPlatform { public interface ISIPCommanderForPlatform {
@ -14,15 +17,15 @@ public interface ISIPCommanderForPlatform {
* @param parentPlatform * @param parentPlatform
* @return * @return
*/ */
boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister); void register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException;
/** /**
* 向上级平台注销 * 向上级平台注销
* @param parentPlatform * @param parentPlatform
* @return * @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 * @param parentPlatform
* @return callId(作为接受回复的判定) * @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 * @param size
* @return * @return
*/ */
boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size); void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException;
boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag); void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException;
/** /**
* 向上级回复DeviceInfo查询信息 * 向上级回复DeviceInfo查询信息
@ -52,7 +55,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag * @param fromTag
* @return * @return
*/ */
boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag); void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
/** /**
* 向上级回复DeviceStatus查询信息 * 向上级回复DeviceStatus查询信息
@ -61,7 +64,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag * @param fromTag
* @return * @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 订阅相关的信息 * @param subscribeInfo 订阅相关的信息
* @return * @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 报警信息信息 * @param deviceAlarm 报警信息信息
* @return * @return
*/ */
boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm); void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException;
/** /**
* 回复catalog事件-增加/更新 * 回复catalog事件-增加/更新
* @param parentPlatform * @param parentPlatform
* @param deviceChannels * @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事件-删除 * 回复catalog事件-删除
* @param parentPlatform * @param parentPlatform
* @param deviceChannels * @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 * 回复recordInfo
@ -101,7 +104,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag fromTag * @param fromTag fromTag
* @param recordInfo 录像信息 * @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消息 * 录像播放推送完成时发送MediaStatus消息
@ -109,13 +112,13 @@ public interface ISIPCommanderForPlatform {
* @param sendRtpItem * @param sendRtpItem
* @return * @return
*/ */
boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem); void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
/** /**
* 向发起点播的上级回复bye * 向发起点播的上级回复bye
* @param platform 平台信息 * @param platform 平台信息
* @param callId callId * @param callId callId
*/ */
void streamByeCmd(ParentPlatform platform, String callId); void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException;
void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem); void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
} }

View File

@ -10,6 +10,9 @@ import javax.sip.header.*;
import javax.sip.message.Request; import javax.sip.message.Request;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.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.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 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.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPDialog;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -168,34 +172,37 @@ public class SIPRequestHeaderProvider {
return request; 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; Request request = null;
//请求行 //请求行
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress()); SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
// via // via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); 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); viaHeaders.add(viaHeader);
//from //from
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记否则无法创建会话无法回应ack FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
//to //to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress()); SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress());
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,toTag); ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
//Forwards //Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
//ceq //ceq
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); 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 = sipFactory.createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil)); request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort())); Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
return request; return request;
} }
@ -251,47 +258,72 @@ public class SIPRequestHeaderProvider {
return request; 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 { throws SipException, ParseException, InvalidArgumentException {
if (streamInfo == null) { if (device == null || transactionInfo == null) {
return null; return null;
} }
Request request = null; SIPRequest request = null;
SIPDialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream()); //请求行
if (dialog == null) { SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
return null; // 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());
//Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
//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");
request.setContent(content, contentTypeHeader);
} }
return request;
}
SipStack sipStack = udpSipProvider.getSipStack(); public Request createAckRequest(SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {
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());
ViaHeader viaHeader = (ViaHeader) infoRequest.getHeader(ViaHeader.NAME); // via
viaHeader.setRPort(); ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
// 增加Contact header ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() viaHeaders.add(viaHeader);
.createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort()));
infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
infoRequest.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", //Forwards
"MANSRTSP"); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
infoRequest.setContent(content, contentTypeHeader);
CSeqHeader cSeqHeader = (CSeqHeader)infoRequest.getHeader(CSeqHeader.NAME); //ceq
cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ()); CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
// ceq
infoRequest.addHeader(cSeqHeader); Request request = sipFactory.createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
return infoRequest;
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;
} }
} }

View File

@ -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.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.GitUtil;
import com.genersoft.iot.vmp.utils.SerializeUtils; import com.genersoft.iot.vmp.utils.SerializeUtils;
import gov.nist.javax.sip.SIPConstants;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.MessageFactoryImpl;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPDialog;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -26,17 +27,15 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import javax.sip.*; import javax.sip.*;
import javax.sip.address.SipURI;
import javax.sip.header.*; import javax.sip.header.*;
import javax.sip.message.Request; import javax.sip.message.Request;
import java.lang.reflect.Field;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
@Component @Component
@ -77,19 +76,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
private SubscribeHolder subscribeHolder; private SubscribeHolder subscribeHolder;
@Override @Override
public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
return register(parentPlatform, null, null, errorEvent, okEvent, false, true); register(parentPlatform, null, null, errorEvent, okEvent, false, true);
} }
@Override @Override
public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
return register(parentPlatform, null, null, errorEvent, okEvent, false, false); register(parentPlatform, null, null, errorEvent, okEvent, false, false);
} }
@Override @Override
public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) { SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException {
try {
Request request; Request request;
if (!registerAgain ) { if (!registerAgain ) {
CallIdHeader callIdHeader = null; CallIdHeader callIdHeader = null;
@ -126,23 +124,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
transmitRequest(parentPlatform, request, null, okEvent); 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 @Override
public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
String callId = null;
try {
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
StringBuffer keepaliveXml = new StringBuffer(200); StringBuffer keepaliveXml = new StringBuffer(200);
keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -163,11 +148,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
SipUtils.getNewViaTag(), SipUtils.getNewViaTag(),
callIdHeader); callIdHeader);
transmitRequest(parentPlatform, request, errorEvent, okEvent); transmitRequest(parentPlatform, request, errorEvent, okEvent);
callId = callIdHeader.getCallId(); return callIdHeader.getCallId();
} catch (ParseException | InvalidArgumentException | SipException e) {
e.printStackTrace();
}
return callId;
} }
private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException { private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
@ -206,39 +187,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return * @return
*/ */
@Override @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) { if ( parentPlatform ==null) {
return false; return ;
} }
try { List<DeviceChannel> channels = new ArrayList<>();
List<DeviceChannel> channels = new ArrayList<>(); if (channel != null) {
if (channel != null) { channels.add(channel);
channels.add(channel);
}
String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
// callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
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; String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
// callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} }
@Override @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) { if ( parentPlatform ==null) {
return false; return ;
} }
sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0); sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
return true;
} }
private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) { private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
@ -300,30 +274,30 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return catalogXml.toString(); 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()) { if (index >= channels.size()) {
return; return;
} }
try { List<DeviceChannel> deviceChannels;
List<DeviceChannel> deviceChannels; if (index + parentPlatform.getCatalogGroup() < channels.size()) {
if (index + parentPlatform.getCatalogGroup() < channels.size()) { deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup()); }else {
}else { deviceChannels = channels.subList(index, channels.size());
deviceChannels = channels.subList(index, channels.size());
}
String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
// callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request, null, eventResult -> {
int indexNext = index + parentPlatform.getCatalogGroup();
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
});
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
} }
String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
// callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
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 | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
}
});
} }
/** /**
@ -334,36 +308,29 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return * @return
*/ */
@Override @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) { if (parentPlatform == null) {
return false; return;
} }
try { String characterSet = parentPlatform.getCharacterSet();
String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceInfoXml = new StringBuffer(600);
StringBuffer deviceInfoXml = new StringBuffer(600); deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); deviceInfoXml.append("<Response>\r\n");
deviceInfoXml.append("<Response>\r\n"); deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
deviceInfoXml.append("<SN>" +sn + "</SN>\r\n"); deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n");
deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n"); deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n");
deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n"); deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n");
deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n"); deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n");
deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n"); deviceInfoXml.append("<Result>OK</Result>\r\n");
deviceInfoXml.append("<Result>OK</Result>\r\n"); deviceInfoXml.append("</Response>\r\n");
deviceInfoXml.append("</Response>\r\n");
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
} }
/** /**
@ -374,129 +341,103 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return * @return
*/ */
@Override @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) { if (parentPlatform == null) {
return false; return ;
} }
try { String characterSet = parentPlatform.getCharacterSet();
String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600);
StringBuffer deviceStatusXml = new StringBuffer(600); deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); deviceStatusXml.append("<Response>\r\n");
deviceStatusXml.append("<Response>\r\n"); deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n"); deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
deviceStatusXml.append("<SN>" +sn + "</SN>\r\n"); deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); deviceStatusXml.append("<Result>OK</Result>\r\n");
deviceStatusXml.append("<Result>OK</Result>\r\n"); deviceStatusXml.append("<Online>ONLINE</Online>\r\n");
deviceStatusXml.append("<Online>ONLINE</Online>\r\n"); deviceStatusXml.append("<Status>OK</Status>\r\n");
deviceStatusXml.append("<Status>OK</Status>\r\n"); deviceStatusXml.append("</Response>\r\n");
deviceStatusXml.append("</Response>\r\n");
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
} }
@Override @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) { if (parentPlatform == null) {
return false; return;
} }
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
} }
try { String characterSet = parentPlatform.getCharacterSet();
String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600);
StringBuffer deviceStatusXml = new StringBuffer(600); deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); deviceStatusXml.append("<Notify>\r\n");
deviceStatusXml.append("<Notify>\r\n"); deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n"); deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");
deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n"); deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");
deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n"); deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");
deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n"); deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");
deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n"); deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");
deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n"); deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");
deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n"); deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n"); deviceStatusXml.append("</Notify>\r\n");
deviceStatusXml.append("</Notify>\r\n");
sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> { sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg); logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
}, null); }, 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 @Override
public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) { public void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) { if (parentPlatform == null) {
return false; return;
} }
logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm)); deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
try { String characterSet = parentPlatform.getCharacterSet();
String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600);
StringBuffer deviceStatusXml = new StringBuffer(600); deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); deviceStatusXml.append("<Notify>\r\n");
deviceStatusXml.append("<Notify>\r\n"); deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n"); deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n"); deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n"); deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n"); deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n"); deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n"); deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n"); deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n"); deviceStatusXml.append("<info>\r\n");
deviceStatusXml.append("<info>\r\n"); deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n"); deviceStatusXml.append("</info>\r\n");
deviceStatusXml.append("</info>\r\n"); deviceStatusXml.append("</Notify>\r\n");
deviceStatusXml.append("</Notify>\r\n");
CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId() CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId(); : udpSipProvider.getNewCallId();
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request); transmitRequest(parentPlatform, request);
} catch (SipException | ParseException e) {
e.printStackTrace();
return false;
} catch (InvalidArgumentException e) {
e.printStackTrace();
}
return true;
} }
@Override @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) { if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
return false; return;
} }
if (index == null) { if (index == null) {
index = 0; index = 0;
} }
if (index >= deviceChannels.size()) { if (index >= deviceChannels.size()) {
return true; return;
} }
List<DeviceChannel> channels; List<DeviceChannel> channels;
if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) { if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@ -504,32 +445,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else { }else {
channels = deviceChannels.subList(index, deviceChannels.size()); channels = deviceChannels.subList(index, deviceChannels.size());
} }
try { Integer finalIndex = index;
Integer finalIndex = index; String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels, deviceChannels.size(), type, subscribeInfo);
deviceChannels.size(), type, subscribeInfo); sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> { logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg); }, (eventResult -> {
}, (eventResult -> { try {
sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
finalIndex + parentPlatform.getCatalogGroup()); finalIndex + parentPlatform.getCatalogGroup());
})); } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
} catch (SipException | ParseException e) { IllegalAccessException e) {
e.printStackTrace(); logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
return false; }
} catch (NoSuchFieldException e) { }));
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
}
return true;
} }
private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent, private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent ) SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException { throws SipException, ParseException, InvalidArgumentException {
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
// 设置编码 防止中文乱码 // 设置编码 防止中文乱码
@ -537,50 +471,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo); SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ()); transmitRequest(parentPlatform, notifyRequest);
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;
} }
private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) { private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
@ -639,20 +530,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
@Override @Override
public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, public void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
SubscribeInfo subscribeInfo, Integer index) { SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
if (parentPlatform == null if (parentPlatform == null
|| deviceChannels == null || deviceChannels == null
|| deviceChannels.size() == 0 || deviceChannels.size() == 0
|| subscribeInfo == null) { || subscribeInfo == null) {
return false; logger.warn("[缺少必要参数]");
return;
} }
if (index == null) { if (index == null) {
index = 0; index = 0;
} }
if (index >= deviceChannels.size()) { if (index >= deviceChannels.size()) {
return true; return;
} }
List<DeviceChannel> channels; List<DeviceChannel> channels;
if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) { if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@ -660,28 +552,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else { }else {
channels = deviceChannels.subList(index, deviceChannels.size()); channels = deviceChannels.subList(index, deviceChannels.size());
} }
try { Integer finalIndex = index;
Integer finalIndex = index; String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type); sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> { logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg); }, eventResult -> {
}, (eventResult -> { try {
sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
finalIndex + parentPlatform.getCatalogGroup()); finalIndex + parentPlatform.getCatalogGroup());
})); } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
} catch (SipException e) { IllegalAccessException e) {
e.printStackTrace(); logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
} catch (ParseException e) { }
e.printStackTrace(); });
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
}
return true;
} }
private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) { private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
@ -711,113 +594,81 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return catalogXml.toString(); return catalogXml.toString();
} }
@Override @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) { if ( parentPlatform ==null) {
return false; return ;
} }
try { String characterSet = parentPlatform.getCharacterSet();
String characterSet = parentPlatform.getCharacterSet(); StringBuffer recordXml = new StringBuffer(600);
StringBuffer recordXml = new StringBuffer(600); recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); recordXml.append("<Response>\r\n");
recordXml.append("<Response>\r\n"); recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");
recordXml.append("<CmdType>RecordInfo</CmdType>\r\n"); recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");
recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n"); recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n");
recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n"); recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n"); if (recordInfo.getRecordList() == null ) {
if (recordInfo.getRecordList() == null ) { recordXml.append("<RecordList Num=\"0\">\r\n");
recordXml.append("<RecordList Num=\"0\">\r\n"); }else {
}else { recordXml.append("<RecordList Num=\"" + recordInfo.getRecordList().size()+"\">\r\n");
recordXml.append("<RecordList Num=\"" + recordInfo.getRecordList().size()+"\">\r\n"); if (recordInfo.getRecordList().size() > 0) {
if (recordInfo.getRecordList().size() > 0) { for (RecordItem recordItem : recordInfo.getRecordList()) {
for (RecordItem recordItem : recordInfo.getRecordList()) { recordXml.append("<Item>\r\n");
recordXml.append("<Item>\r\n"); if (deviceChannel != null) {
if (deviceChannel != null) { recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n");
recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n"); recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n");
recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n"); recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n");
recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n"); recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");
recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n"); recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");
recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n"); recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");
recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n"); if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {
if (!ObjectUtils.isEmpty(recordItem.getFileSize())) { recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");
recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n"); }
} if (!ObjectUtils.isEmpty(recordItem.getFilePath())) {
if (!ObjectUtils.isEmpty(recordItem.getFilePath())) { recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");
recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");
}
} }
recordXml.append("</Item>\r\n");
} }
recordXml.append("</Item>\r\n");
} }
} }
recordXml.append("</RecordList>\r\n");
recordXml.append("</Response>\r\n");
// callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
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;
} }
try{ recordXml.append("</RecordList>\r\n");
recordXml.append("</Response>\r\n");
String characterSet = platform.getCharacterSet();
StringBuffer mediaStatusXml = new StringBuffer(200);
mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
mediaStatusXml.append("<Notify>\r\n");
mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");
mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
mediaStatusXml.append("</Notify>\r\n");
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;
// callid
CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} }
@Override @Override
public void streamByeCmd(ParentPlatform platform, String callId) { public void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
if (sendRtpItem == null || platform == null) {
return;
}
String characterSet = platform.getCharacterSet();
StringBuffer mediaStatusXml = new StringBuffer(200);
mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
mediaStatusXml.append("<Notify>\r\n");
mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");
mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
mediaStatusXml.append("</Notify>\r\n");
SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
sendRtpItem);
transmitRequest(platform, messageRequest);
}
@Override
public void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException {
if (platform == null) { if (platform == null) {
return; return;
} }
@ -828,7 +679,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
@Override @Override
public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) { public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
if (sendRtpItem == null ) { if (sendRtpItem == null ) {
logger.info("[向上级发送BYE] sendRtpItem 为NULL"); logger.info("[向上级发送BYE] sendRtpItem 为NULL");
return; return;
@ -844,25 +695,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId()); zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
} }
try { SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
if (byeRequest == null) {
SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem); logger.warn("[向上级发送bye]:无法创建 byeRequest");
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);
} }
} }

View File

@ -7,6 +7,7 @@ import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPServerTransaction; import gov.nist.javax.sip.stack.SIPServerTransaction;
import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
@ -57,7 +58,7 @@ public abstract class SIPRequestProcessorParent {
*/ */
public ServerTransaction getServerTransaction(RequestEvent evt) { public ServerTransaction getServerTransaction(RequestEvent evt) {
Request request = evt.getRequest(); Request request = evt.getRequest();
ServerTransaction serverTransaction = evt.getServerTransaction(); SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
// 判断TCP还是UDP // 判断TCP还是UDP
boolean isTcp = false; boolean isTcp = false;
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
@ -65,28 +66,28 @@ public abstract class SIPRequestProcessorParent {
if (transport.equalsIgnoreCase("TCP")) { if (transport.equalsIgnoreCase("TCP")) {
isTcp = true; isTcp = true;
} }
if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
}
if (serverTransaction == null) { if (serverTransaction == null) {
try { try {
if (isTcp) { if (isTcp) {
SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack(); SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
if (serverTransaction == null) { if (serverTransaction == null) {
serverTransaction = tcpSipProvider.getNewServerTransaction(request); serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
} }
} else { } else {
SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack(); SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
if (serverTransaction == null) { if (serverTransaction == null) {
serverTransaction = udpSipProvider.getNewServerTransaction(request); serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
} }
} }
} catch (TransactionAlreadyExistsException e) { } catch (TransactionAlreadyExistsException e) {
logger.error(e.getMessage()); logger.error(e.getMessage());
} catch (TransactionUnavailableException e) { } catch (TransactionUnavailableException e) {
logger.error(e.getMessage()); logger.error(e.getMessage());
}finally {
} }
} }
return serverTransaction; return serverTransaction;

View File

@ -23,12 +23,15 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.address.SipURI; import javax.sip.address.SipURI;
import javax.sip.header.CallIdHeader; import javax.sip.header.CallIdHeader;
import javax.sip.header.FromHeader; import javax.sip.header.FromHeader;
import javax.sip.header.HeaderAddress; import javax.sip.header.HeaderAddress;
import javax.sip.header.ToHeader; import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.*; import java.util.*;
/** /**
@ -95,8 +98,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
logger.info("收到ACKrtp/{}开始向上级推流, 目标 {}:{}SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); logger.info("收到ACKrtp/{}开始向上级推流, 目标={}:{}SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
Map<String, Object> param = new HashMap<>(); Map<String, Object> param = new HashMap<>(12);
param.put("vhost","__defaultVhost__"); param.put("vhost","__defaultVhost__");
param.put("app",sendRtpItem.getApp()); param.put("app",sendRtpItem.getApp());
param.put("stream",sendRtpItem.getStreamId()); param.put("stream",sendRtpItem.getStreamId());
@ -139,7 +142,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
// TODO 可能是语音对讲 // TODO 可能是语音对讲
}else { }else {
// 向上级平台 // 向上级平台
commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); try {
commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
import com.genersoft.iot.vmp.common.StreamInfo; 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.Device;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 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.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
@ -50,6 +50,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Autowired
private IDeviceService deviceService;
@Autowired @Autowired
private IVideoManagerStorage storager; private IVideoManagerStorage storager;
@ -77,9 +80,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
*/ */
@Override @Override
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
try { try {
responseAck(getServerTransaction(evt), Response.OK); responseAck(getServerTransaction(evt), Response.OK);
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); } 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 platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId()); SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
@ -99,7 +106,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
if (totalReaderCount <= 0) { if (totalReaderCount <= 0) {
logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { 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)) { if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, 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); SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
if (ssrcTransactionForPlay != null){ if (ssrcTransactionForPlay != null){
SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog()); if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){
if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
// 释放ssrc // 释放ssrc
MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
if (mediaServerItem != null) { if (mediaServerItem != null) {
@ -140,12 +156,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
} }
} }
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
} }
} }

View File

@ -341,7 +341,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
logger.info("Ack 等待超时"); logger.info("Ack 等待超时");
mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc); mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc);
// 回复bye // 回复bye
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId()); try {
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
}, 60 * 1000); }, 60 * 1000);
responseSdpAck(serverTransaction, content.toString(), platform); responseSdpAck(serverTransaction, content.toString(), platform);

View File

@ -93,7 +93,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found"); responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
logger.warn("[设备未找到 ] {}", deviceId); logger.warn("[设备未找到 ] {}", deviceId);
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ 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); sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
}; };
}else { }else {

View File

@ -89,8 +89,6 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
try { try {
if (device != null && parentPlatform != null) { if (device != null && parentPlatform != null) {
logger.warn("[重复]平台与设备编号重复:{}", deviceId);
SIPRequest request = (SIPRequest) evt.getRequest(); SIPRequest request = (SIPRequest) evt.getRequest();
String hostAddress = request.getRemoteAddress().getHostAddress(); String hostAddress = request.getRemoteAddress().getHostAddress();
int remotePort = request.getRemotePort(); int remotePort = request.getRemotePort();
@ -105,7 +103,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found"); responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
logger.warn("[设备未找到 ] {}", deviceId); logger.warn("[设备未找到 ] {}", deviceId);
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ 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); sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
}; };
}else { }else {

View File

@ -16,6 +16,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; 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.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -48,6 +50,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
@Autowired @Autowired
private SIPCommanderFroPlatform cmderFroPlatform; private SIPCommanderFroPlatform cmderFroPlatform;
@Qualifier("taskExecutor")
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
controlMessageHandler.addHandler(cmdType, this); controlMessageHandler.addHandler(cmdType, this);
@ -71,34 +77,30 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
if (parentPlatform.getServerGBId().equals(targetGBId)) { if (parentPlatform.getServerGBId().equals(targetGBId)) {
// 远程启动本平台需要在重新启动程序后先对SipStack解绑 // 远程启动本平台需要在重新启动程序后先对SipStack解绑
logger.info("执行远程启动本平台命令"); logger.info("执行远程启动本平台命令");
cmderFroPlatform.unregister(parentPlatform, null, null); try {
cmderFroPlatform.unregister(parentPlatform, null, null);
Thread restartThread = new Thread(new Runnable() { } catch (InvalidArgumentException | ParseException | SipException e) {
@Override logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
public void run() { }
try { taskExecutor.execute(()->{
Thread.sleep(3000); try {
SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); Thread.sleep(3000);
SipStackImpl stack = (SipStackImpl)up.getSipStack(); SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
stack.stop(); SipStackImpl stack = (SipStackImpl)up.getSipStack();
Iterator listener = stack.getListeningPoints(); stack.stop();
while (listener.hasNext()) { Iterator listener = stack.getListeningPoints();
stack.deleteListeningPoint((ListeningPoint) listener.next()); while (listener.hasNext()) {
} stack.deleteListeningPoint((ListeningPoint) listener.next());
Iterator providers = stack.getSipProviders();
while (providers.hasNext()) {
stack.deleteSipProvider((SipProvider) providers.next());
}
VManageBootstrap.restart();
} catch (InterruptedException ignored) {
} catch (ObjectInUseException e) {
e.printStackTrace();
} }
Iterator providers = stack.getSipProviders();
while (providers.hasNext()) {
stack.deleteSipProvider((SipProvider) providers.next());
}
VManageBootstrap.restart();
} catch (InterruptedException | ObjectInUseException e) {
logger.error("[任务执行失败] 服务重启: {}", e.getMessage());
} }
}); });
restartThread.setDaemon(false);
restartThread.start();
} else { } else {
// 远程启动指定设备 // 远程启动指定设备
} }
@ -111,37 +113,29 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
try { try {
responseAck(serverTransaction, Response.NOT_FOUND); responseAck(serverTransaction, Response.NOT_FOUND);
return; return;
} catch (SipException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); logger.error("[命令发送失败] 错误信息: {}", e.getMessage());
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} }
} }
cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> { try {
// 失败的回复 cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
try { // 失败的回复
responseAck(serverTransaction, eventResult.statusCode, eventResult.msg); try {
} catch (SipException e) { responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
e.printStackTrace(); } catch (SipException | InvalidArgumentException | ParseException e) {
} catch (InvalidArgumentException e) { logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
e.printStackTrace(); }
} catch (ParseException e) { }, eventResult -> {
e.printStackTrace(); // 成功的回复
} try {
}, eventResult -> { responseAck(serverTransaction, eventResult.statusCode);
// 成功的回复 } catch (SipException | InvalidArgumentException | ParseException e) {
try { logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
responseAck(serverTransaction, eventResult.statusCode); }
} catch (SipException e) { });
e.printStackTrace(); } catch (InvalidArgumentException | SipException | ParseException e) {
} catch (InvalidArgumentException e) { logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
e.printStackTrace(); }
} catch (ParseException e) {
e.printStackTrace();
}
});
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; 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.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.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 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); SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 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进行上下级绑定 // 如果级联播放需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题需要将点播CallId进行上下级绑定
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null); SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null);
@ -99,7 +105,11 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
logger.warn("[级联消息发送]发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId()); logger.warn("[级联消息发送]发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId());
return; return;
} }
sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem); try {
sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
}
} }
} }
} }

View File

@ -49,14 +49,14 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
try { try {
// 回复200 OK // 回复200 OK
responseAck(getServerTransaction(evt), Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); logger.error("[命令发送失败] DeviceInfo查询回复: {}", e.getMessage());
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} }
String sn = rootElement.element("SN").getText(); String sn = rootElement.element("SN").getText();
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag()); try {
cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage());
}
} }
} }

View File

@ -62,14 +62,14 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
// 回复200 OK // 回复200 OK
try { try {
responseAck(getServerTransaction(evt), Response.OK); responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage());
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} }
String sn = rootElement.element("SN").getText(); String sn = rootElement.element("SN").getText();
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag()); try {
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
}
} }
} }

View File

@ -103,53 +103,45 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId); DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId);
// 接收录像数据 // 接收录像数据
recordEndEventListener.addEndEventHandler(deviceChannel.getDeviceId(), channelId, (recordInfo)->{ recordEndEventListener.addEndEventHandler(deviceChannel.getDeviceId(), channelId, (recordInfo)->{
cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, fromHeader.getTag(), recordInfo); try {
cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, fromHeader.getTag(), recordInfo);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
}
}); });
commander.recordInfoQuery(device, channelId, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime), try {
DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> { commander.recordInfoQuery(device, channelId, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
// 回复200 OK DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
try { // 回复200 OK
responseAck(serverTransaction, Response.OK); try {
} catch (SipException e) { responseAck(serverTransaction, Response.OK);
e.printStackTrace(); } catch (SipException | InvalidArgumentException | ParseException e) {
} catch (InvalidArgumentException e) { logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
e.printStackTrace(); }
} catch (ParseException e) { }),(eventResult -> {
e.printStackTrace(); // 查询失败
} try {
}),(eventResult -> { responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
// 查询失败 } catch (SipException | InvalidArgumentException | ParseException e) {
try { logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
responseAck(serverTransaction, eventResult.statusCode, eventResult.msg); }
} catch (SipException e) { }));
e.printStackTrace(); } catch (InvalidArgumentException | ParseException | SipException e) {
} catch (InvalidArgumentException e) { logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
e.printStackTrace(); }
} catch (ParseException e) {
e.printStackTrace();
}
}));
}else if (channelSources.get(1).getCount() > 0) { // 直播流 }else if (channelSources.get(1).getCount() > 0) { // 直播流
// TODO // TODO
try { try {
responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现 responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
} catch (SipException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} }
}else { // 错误的请求 }else { // 错误的请求
try { try {
responseAck(serverTransaction, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
} catch (SipException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace(); logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} }
} }
} }

View File

@ -87,89 +87,73 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
public void handForDevice(RequestEvent evt, Device device, Element element) { public void handForDevice(RequestEvent evt, Device device, Element element) {
taskQueue.offer(new HandlerCatchData(evt, device, element)); taskQueue.offer(new HandlerCatchData(evt, device, element));
// 回复200 OK // 回复200 OK
ServerTransaction serverTransaction = getServerTransaction(evt);
try { try {
ServerTransaction serverTransaction = getServerTransaction(evt);
responseAck(serverTransaction, Response.OK); responseAck(serverTransaction, Response.OK);
if (!taskQueueHandlerRun) { } catch (SipException | InvalidArgumentException | ParseException e) {
taskQueueHandlerRun = true; logger.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
taskExecutor.execute(()-> { }
while (!taskQueue.isEmpty()) { if (!taskQueueHandlerRun) {
HandlerCatchData take = taskQueue.poll(); taskQueueHandlerRun = true;
try { taskExecutor.execute(() -> {
Element rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset()); while (!taskQueue.isEmpty()) {
if (rootElement == null) { HandlerCatchData take = taskQueue.poll();
logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest()); Element rootElement = null;
continue; try {
} rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
Element deviceListElement = rootElement.element("DeviceList"); } catch (DocumentException e) {
Element sumNumElement = rootElement.element("SumNum"); logger.error("[xml解析] 失败: ", e);
Element snElement = rootElement.element("SN"); continue;
if (snElement == null || sumNumElement == null || deviceListElement == null) {
responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
continue;
}
int sumNum = Integer.parseInt(sumNumElement.getText());
if (sumNum == 0) {
logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
// 数据已经完整接收
storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
}else {
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
if (deviceListIterator != null) {
List<DeviceChannel> channelList = new ArrayList<>();
// 遍历DeviceList
while (deviceListIterator.hasNext()) {
Element itemDevice = deviceListIterator.next();
Element channelDeviceElement = itemDevice.element("DeviceID");
if (channelDeviceElement == null) {
continue;
}
DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
deviceChannel.setDeviceId(take.getDevice().getDeviceId());
channelList.add(deviceChannel);
}
int sn = Integer.parseInt(snElement.getText());
catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
// 数据已经完整接收 此时可能存在某个设备离线变上线的情况但是考虑到性能此处不做处理
// 目前支持设备通道上线通知时和设备上线时向上级通知
boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
if (!resetChannelsResult) {
String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "";
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
}else {
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
}
}
}
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
} finally {
taskQueueHandlerRun = false;
}
} }
}); if (rootElement == null) {
} logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
} catch (SipException e) { continue;
throw new RuntimeException(e); }
} catch (InvalidArgumentException e) { Element deviceListElement = rootElement.element("DeviceList");
throw new RuntimeException(e); Element sumNumElement = rootElement.element("SumNum");
} catch (ParseException e) { Element snElement = rootElement.element("SN");
throw new RuntimeException(e); int sumNum = Integer.parseInt(sumNumElement.getText());
} finally {
taskQueueHandlerRun = false; if (sumNum == 0) {
logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
// 数据已经完整接收
storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
} else {
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
if (deviceListIterator != null) {
List<DeviceChannel> channelList = new ArrayList<>();
// 遍历DeviceList
while (deviceListIterator.hasNext()) {
Element itemDevice = deviceListIterator.next();
Element channelDeviceElement = itemDevice.element("DeviceID");
if (channelDeviceElement == null) {
continue;
}
DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
deviceChannel.setDeviceId(take.getDevice().getDeviceId());
channelList.add(deviceChannel);
}
int sn = Integer.parseInt(snElement.getText());
catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 : catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
// 数据已经完整接收 此时可能存在某个设备离线变上线的情况但是考虑到性能此处不做处理
// 目前支持设备通道上线通知时和设备上线时向上级通知
boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
if (!resetChannelsResult) {
String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "";
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
} else {
catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
}
}
}
}
}
});
} }
} }
@ -182,7 +166,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
public SyncStatus getChannelSyncProgress(String deviceId) { public SyncStatus getChannelSyncProgress(String deviceId) {
if (catalogDataCatch.get(deviceId) == null) { if (catalogDataCatch.get(deviceId) == null) {
return null; return null;
}else { } else {
return catalogDataCatch.getSyncStatus(deviceId); return catalogDataCatch.getSyncStatus(deviceId);
} }
} }
@ -190,7 +174,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
public boolean isSyncRunning(String deviceId) { public boolean isSyncRunning(String deviceId) {
if (catalogDataCatch.get(deviceId) == null) { if (catalogDataCatch.get(deviceId) == null) {
return false; return false;
}else { } else {
return catalogDataCatch.isSyncRunning(deviceId); return catalogDataCatch.isSyncRunning(deviceId);
} }
} }

View File

@ -50,12 +50,12 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
@Override @Override
public void handForDevice(RequestEvent evt, Device device, Element element) { public void handForDevice(RequestEvent evt, Device device, Element element) {
Element rootElement = null;
ServerTransaction serverTransaction = getServerTransaction(evt);
try { try {
Element rootElement = getRootElement(evt, device.getCharset());
ServerTransaction serverTransaction = getServerTransaction(evt);
rootElement = getRootElement(evt, device.getCharset());
if (rootElement == null) { if (rootElement == null) {
logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest()); logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
responseAck(serverTransaction, Response.BAD_REQUEST); responseAck(serverTransaction, Response.BAD_REQUEST);
@ -66,32 +66,29 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
//该字段可能为通道或则设备的id //该字段可能为通道或则设备的id
String deviceId = getText(rootElement, "DeviceID"); String deviceId = getText(rootElement, "DeviceID");
String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId; String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
if (snElement == null || presetListNumElement == null) { if (snElement == null || presetListNumElement == null) {
responseAck(serverTransaction, Response.BAD_REQUEST, "xml error"); responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
return; return;
} }
int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num")); int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>(); List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>();
if (sumNum > 0) { if (sumNum > 0) {
for (Iterator<Element> presetIterator = presetListNumElement.elementIterator();presetIterator.hasNext();){ for (Iterator<Element> presetIterator = presetListNumElement.elementIterator(); presetIterator.hasNext(); ) {
Element itemListElement = presetIterator.next(); Element itemListElement = presetIterator.next();
PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq(); PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq();
for (Iterator<Element> itemListIterator = itemListElement.elementIterator();itemListIterator.hasNext();){ for (Iterator<Element> itemListIterator = itemListElement.elementIterator(); itemListIterator.hasNext(); ) {
// 遍历item // 遍历item
Element itemOne = itemListIterator.next(); Element itemOne = itemListIterator.next();
String name = itemOne.getName(); String name = itemOne.getName();
String textTrim = itemOne.getTextTrim(); String textTrim = itemOne.getTextTrim();
if("PresetID".equalsIgnoreCase(name)){ if ("PresetID".equalsIgnoreCase(name)) {
presetQuerySipReq.setPresetId(textTrim); presetQuerySipReq.setPresetId(textTrim);
}else { } else {
presetQuerySipReq.setPresetName(textTrim); presetQuerySipReq.setPresetName(textTrim);
} }
} }
presetQuerySipReqList.add(presetQuerySipReq); presetQuerySipReqList.add(presetQuerySipReq);
} }
} }
RequestMessage requestMessage = new RequestMessage(); RequestMessage requestMessage = new RequestMessage();
requestMessage.setKey(key); requestMessage.setKey(key);
@ -99,13 +96,9 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
deferredResultHolder.invokeAllResult(requestMessage); deferredResultHolder.invokeAllResult(requestMessage);
responseAck(serverTransaction, Response.OK); responseAck(serverTransaction, Response.OK);
} catch (DocumentException e) { } catch (DocumentException e) {
e.printStackTrace(); logger.error("[解析xml]失败: ", e);
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException | ParseException | SipException e) {
e.printStackTrace(); logger.error("[命令发送失败] 设备预置位查询应答处理: {}", e.getMessage());
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
} }
} }

View File

@ -1,18 +1,27 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
import com.genersoft.iot.vmp.conf.SipConfig; 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.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.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.transmit.event.response.SIPResponseProcessorAbstract;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.utils.GitUtil; import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.ResponseEventExt; import gov.nist.javax.sip.ResponseEventExt;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPClientTransaction; import gov.nist.javax.sip.stack.SIPClientTransaction;
import gov.nist.javax.sip.stack.SIPDialog; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sdp.SdpFactory; import javax.sdp.SdpFactory;
@ -54,6 +63,20 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
@Autowired @Autowired
private GitUtil gitUtil; private GitUtil gitUtil;
@Autowired
private ISIPCommander commander;
@Autowired
private IDeviceService deviceService;
@Autowired
private SIPRequestHeaderProvider headerProvider;
@Autowired
@Qualifier(value="udpSipProvider")
private SipProviderImpl udpSipProvider;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
// 添加消息处理的订阅 // 添加消息处理的订阅
@ -71,7 +94,8 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
@Override @Override
public void process(ResponseEvent evt ){ public void process(ResponseEvent evt ){
try { try {
Response response = evt.getResponse();
SIPResponse response = (SIPResponse)evt.getResponse();
int statusCode = response.getStatusCode(); int statusCode = response.getStatusCode();
// trying不会回复 // trying不会回复
if (statusCode == Response.TRYING) { if (statusCode == Response.TRYING) {
@ -80,10 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
// 下发ack // 下发ack
if (statusCode == Response.OK) { if (statusCode == Response.OK) {
ResponseEventExt event = (ResponseEventExt)evt; 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()); String contentString = new String(response.getRawContent());
// jainSip不支持y=字段 移除以解析 // jainSip不支持y=字段 移除以解析
int ssrcIndex = contentString.indexOf("y="); int ssrcIndex = contentString.indexOf("y=");
@ -96,29 +117,15 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
} else { } else {
sdp = SdpFactory.getInstance().createSessionDescription(contentString); sdp = SdpFactory.getInstance().createSessionDescription(contentString);
} }
requestURI.setUser(sdp.getOrigin().getUsername()); SipURI requestUri = sipFactory.createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
try { Request reqAck = headerProvider.createAckRequest(requestUri, response);
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());
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) { } catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
e.printStackTrace(); logger.info("[点播回复ACK],异常:", e );
} catch (ParseException e) {
throw new RuntimeException(e);
} catch (SdpParseException e) {
throw new RuntimeException(e);
} }
} }

View File

@ -15,10 +15,13 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent; import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.header.CallIdHeader; import javax.sip.header.CallIdHeader;
import javax.sip.header.WWWAuthenticateHeader; import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException;
/** /**
* @description:Register响应处理器 * @description:Register响应处理器
@ -87,7 +90,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
if (response.getStatusCode() == Response.UNAUTHORIZED) { if (response.getStatusCode() == Response.UNAUTHORIZED) {
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister()); 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){ }else if (response.getStatusCode() == Response.OK){
if (platformRegisterInfo.isRegister()) { if (platformRegisterInfo.isRegister()) {

View File

@ -70,4 +70,47 @@ public class SipUtils {
return String.valueOf(System.currentTimeMillis()); 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();
}
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.media.zlm; package com.genersoft.iot.vmp.media.zlm;
import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -7,6 +8,7 @@ import java.util.Map;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@ -31,6 +33,8 @@ import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
/** /**
* @description:针对 ZLMediaServer的hook事件监听 * @description:针对 ZLMediaServer的hook事件监听
@ -58,6 +62,9 @@ public class ZLMHttpHookListener {
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Autowired
private IDeviceService deviceService;
@Autowired @Autowired
private IMediaServerService mediaServerService; private IMediaServerService mediaServerService;
@ -515,7 +522,11 @@ public class ZLMHttpHookListener {
String platformId = sendRtpItem.getPlatformId(); String platformId = sendRtpItem.getPlatformId();
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
commanderFroPlatform.streamByeCmd(platform, sendRtpItem); 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) { if (sendRtpItems.size() > 0) {
for (SendRtpItem sendRtpItem : sendRtpItems) { for (SendRtpItem sendRtpItem : sendRtpItems) {
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); try {
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
sendRtpItem.getCallId(), sendRtpItem.getStreamId()); sendRtpItem.getCallId(), sendRtpItem.getStreamId());
} }
} }
} }
cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(), Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
streamInfoForPlayCatch.getStream(), null); 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); redisCatchStorage.stopPlay(streamInfoForPlayCatch);
storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
}else{ }else{
StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null); StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
if (streamInfoForPlayBackCatch != null) { if (streamInfoForPlayBackCatch != null) {
cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null); 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(), redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null); streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
}else { }else {
@ -689,7 +720,11 @@ public class ZLMHttpHookListener {
if (sendRtpItems.size() > 0) { if (sendRtpItems.size() > 0) {
for (SendRtpItem sendRtpItem : sendRtpItems) { for (SendRtpItem sendRtpItem : sendRtpItems) {
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); try {
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
sendRtpItem.getCallId(), sendRtpItem.getStreamId()); sendRtpItem.getCallId(), sendRtpItem.getStreamId());
} }

View File

@ -68,7 +68,6 @@ public class ZLMMediaListManager {
private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>(); private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
public StreamPushItem addPush(MediaItem mediaItem) { public StreamPushItem addPush(MediaItem mediaItem) {
// 查找此直播流是否存在redis预设gbId
StreamPushItem transform = streamPushService.transform(mediaItem); StreamPushItem transform = streamPushService.transform(mediaItem);
StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream()); StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
transform.setPushIng(mediaItem.isRegist()); transform.setPushIng(mediaItem.isRegist());
@ -82,15 +81,14 @@ public class ZLMMediaListManager {
streamPushMapper.update(transform); streamPushMapper.update(transform);
gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId()); gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId());
} }
if (transform != null) { ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream());
if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) { if ( channelOnlineEventLister != null) {
try { try {
getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId()); channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());;
} catch (ParseException e) { } catch (ParseException e) {
throw new RuntimeException(e); logger.error("addPush: ", e);
}
removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
} }
removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
} }
return transform; return transform;
} }
@ -99,11 +97,12 @@ public class ZLMMediaListManager {
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
// 查看推流状态 // 查看推流状态
if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
if (getChannelOnlineEventLister(app, stream) != null) { ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream);
if (channelOnlineEventLister != null) {
try { try {
getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId); channelOnlineEventLister.run(app, stream, mediaServerId);
} catch (ParseException e) { } catch (ParseException e) {
throw new RuntimeException(e); logger.error("sendStreamEvent: ", e);
} }
removedChannelOnlineEventLister(app, stream); removedChannelOnlineEventLister(app, stream);
} }

View File

@ -26,6 +26,9 @@ import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -95,7 +98,11 @@ public class DeviceServiceImpl implements IDeviceService {
logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId()); logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
deviceMapper.add(device); deviceMapper.add(device);
redisCatchStorage.updateDevice(device); redisCatchStorage.updateDevice(device);
commander.deviceInfoQuery(device); try {
commander.deviceInfoQuery(device);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
}
sync(device); sync(device);
}else { }else {
if(device.getOnline() == 0){ if(device.getOnline() == 0){
@ -104,7 +111,11 @@ public class DeviceServiceImpl implements IDeviceService {
logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId()); logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
deviceMapper.update(device); deviceMapper.update(device);
redisCatchStorage.updateDevice(device); redisCatchStorage.updateDevice(device);
commander.deviceInfoQuery(device); try {
commander.deviceInfoQuery(device);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
}
sync(device); sync(device);
// TODO 如果设备下的通道级联到了其他平台那么需要发送事件或者notify给上级平台 // TODO 如果设备下的通道级联到了其他平台那么需要发送事件或者notify给上级平台
}else { }else {
@ -129,6 +140,7 @@ public class DeviceServiceImpl implements IDeviceService {
@Override @Override
public void offline(String deviceId) { public void offline(String deviceId) {
logger.info("[设备离线] device{}", deviceId);
Device device = deviceMapper.getDeviceByDeviceId(deviceId); Device device = deviceMapper.getDeviceByDeviceId(deviceId);
if (device == null) { if (device == null) {
return; return;
@ -238,15 +250,28 @@ public class DeviceServiceImpl implements IDeviceService {
} }
int sn = (int)((Math.random()*9+1)*100000); int sn = (int)((Math.random()*9+1)*100000);
catalogResponseMessageHandler.setChannelSyncReady(device, sn); catalogResponseMessageHandler.setChannelSyncReady(device, sn);
sipCommander.catalogQuery(device, sn, event -> { try {
String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg); 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); catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
}); }
} }
@Override @Override
public Device queryDevice(String deviceId) { 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 @Override
@ -266,7 +291,11 @@ public class DeviceServiceImpl implements IDeviceService {
if (device == null || device.getOnline() == 0) { if (device == null || device.getOnline() == 0) {
return; return;
} }
sipCommander.deviceStatusQuery(device, null); try {
sipCommander.deviceStatusQuery(device, null);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 设备状态查询: {}", e.getMessage());
}
} }

View File

@ -20,7 +20,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.TimeoutEvent; import javax.sip.TimeoutEvent;
import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -99,9 +102,13 @@ public class PlatformServiceImpl implements IPlatformService {
if (parentPlatform.isEnable()) { if (parentPlatform.isEnable()) {
// 保存时启用就发送注册 // 保存时启用就发送注册
// 注册成功时由程序直接调用了online方法 // 注册成功时由程序直接调用了online方法
commanderForPlatform.register(parentPlatform, eventResult -> { try {
logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId()); commanderForPlatform.register(parentPlatform, eventResult -> {
}, null); logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
}, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联: {}", e.getMessage());
}
} }
return result > 0; return result > 0;
} }
@ -130,46 +137,62 @@ public class PlatformServiceImpl implements IPlatformService {
// 添加注册任务 // 添加注册任务
dynamicTask.startDelay(registerTaskKey, dynamicTask.startDelay(registerTaskKey,
// 注册失败注册成功时由程序直接调用了online方法 // 注册失败注册成功时由程序直接调用了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); (parentPlatform.getExpires() - 10) *1000);
final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
if (!dynamicTask.contains(keepaliveTaskKey)) { if (!dynamicTask.contains(keepaliveTaskKey)) {
// 添加心跳任务 // 添加心跳任务
dynamicTask.startCron(keepaliveTaskKey, dynamicTask.startCron(keepaliveTaskKey,
()-> commanderForPlatform.keepalive(parentPlatform, eventResult -> { ()-> {
// 心跳失败 try {
if (eventResult.type == SipSubscribe.EventResultType.timeout) { commanderForPlatform.keepalive(parentPlatform, eventResult -> {
// 心跳超时 // 心跳失败
ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); if (eventResult.type == SipSubscribe.EventResultType.timeout) {
// 此时是第三次心跳超时 平台离线 // 心跳超时
if (platformCatch.getKeepAliveReply() == 2) { ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
// 设置平台离线并重新注册 // 此时是第三次心跳超时 平台离线
offline(parentPlatform); if (platformCatch.getKeepAliveReply() == 2) {
logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId()); // 设置平台离线并重新注册
commanderForPlatform.register(parentPlatform, eventResult1 -> { offline(parentPlatform);
logger.info("[国标级联] {}三次心跳超时后再次发起注册仍然失败开始定时发起注册间隔为1分钟", parentPlatform.getServerGBId()); logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId());
// 添加注册任务 try {
dynamicTask.startCron(registerTaskKey, commanderForPlatform.register(parentPlatform, eventResult1 -> {
// 注册失败注册成功时由程序直接调用了online方法 logger.info("[国标级联] {}三次心跳超时后再次发起注册仍然失败开始定时发起注册间隔为1分钟", parentPlatform.getServerGBId());
()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()), // 添加注册任务
60*1000); dynamicTask.startCron(registerTaskKey,
}, null); // 注册失败注册成功时由程序直接调用了online方法
} ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
60*1000);
}, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
}
}
}else { }else {
logger.warn("[国标级联]发送心跳收到错误code {}, msg: {}", eventResult.statusCode, eventResult.msg); logger.warn("[国标级联]发送心跳收到错误code {}, msg: {}", eventResult.statusCode, eventResult.msg);
} }
}, eventResult -> { }, eventResult -> {
// 心跳成功 // 心跳成功
// 清空之前的心跳超时计数 // 清空之前的心跳超时计数
ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
if (platformCatch.getKeepAliveReply() > 0) { if (platformCatch.getKeepAliveReply() > 0) {
platformCatch.setKeepAliveReply(0); platformCatch.setKeepAliveReply(0);
redisCatchStorage.updatePlatformCatchInfo(platformCatch); redisCatchStorage.updatePlatformCatchInfo(platformCatch);
}
});
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage());
} }
}), },
(parentPlatform.getKeepTimeout() - 10)*1000); (parentPlatform.getKeepTimeout() - 10)*1000);
} }
} }
@ -225,14 +248,18 @@ public class PlatformServiceImpl implements IPlatformService {
@Override @Override
public void login(ParentPlatform parentPlatform) { public void login(ParentPlatform parentPlatform) {
final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
commanderForPlatform.register(parentPlatform, eventResult1 -> { try {
logger.info("[国标级联] {}开始定时发起注册间隔为1分钟", parentPlatform.getServerGBId()); commanderForPlatform.register(parentPlatform, eventResult1 -> {
// 添加注册任务 logger.info("[国标级联] {}开始定时发起注册间隔为1分钟", parentPlatform.getServerGBId());
dynamicTask.startCron(registerTaskKey, // 添加注册任务
// 注册失败注册成功时由程序直接调用了online方法 dynamicTask.startCron(registerTaskKey,
()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()), // 注册失败注册成功时由程序直接调用了online方法
60*1000); ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
}, null); 60*1000);
}, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联注册: {}", e.getMessage());
}
} }
@Override @Override
@ -259,7 +286,12 @@ public class PlatformServiceImpl implements IPlatformService {
continue; continue;
} }
// 发送GPS消息 // 发送GPS消息
commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe); try {
commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 移动位置通知: {}", e.getMessage());
}
} }
} }
} }

View File

@ -2,11 +2,17 @@ package com.genersoft.iot.vmp.service.impl;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.ParseException;
import java.util.*; import java.util.*;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent; import javax.sip.ResponseEvent;
import javax.sip.SipException;
import com.genersoft.iot.vmp.conf.exception.ControllerException; 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 com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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.common.StreamInfo;
import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.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.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@ -92,6 +91,10 @@ public class PlayServiceImpl implements IPlayService {
@Autowired @Autowired
private VideoStreamSessionManager streamSession; private VideoStreamSessionManager streamSession;
@Autowired
private IDeviceService deviceService;
@Autowired @Autowired
private UserSetting userSetting; private UserSetting userSetting;
@ -261,14 +264,14 @@ public class PlayServiceImpl implements IPlayService {
System.out.println("设置超时任务: " + timeOutTaskKey); System.out.println("设置超时任务: " + timeOutTaskKey);
dynamicTask.startDelay( timeOutTaskKey,()->{ dynamicTask.startDelay( timeOutTaskKey,()->{
SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
if (dialog != null) { timeoutCallback.run(1, "收流超时");
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
timeoutCallback.run(1, "收流超时"); try {
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源 cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null);
cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null); } catch (InvalidArgumentException | ParseException | SipException e) {
}else { logger.error("[点播超时] 发送BYE失败 {}", e.getMessage());
logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); } catch (SsrcTransactionNotFoundException e) {
timeoutCallback.run(0, "点播超时"); timeoutCallback.run(0, "点播超时");
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
@ -282,73 +285,87 @@ public class PlayServiceImpl implements IPlayService {
logger.info("[点播端口分配异常]deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); logger.info("[点播端口分配异常]deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
return; return;
} }
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { try {
logger.info("收到订阅消息: " + response.toJSONString()); cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
System.out.println("停止超时任务: " + timeOutTaskKey); logger.info("收到订阅消息: " + response.toJSONString());
dynamicTask.stop(timeOutTaskKey); System.out.println("停止超时任务: " + timeOutTaskKey);
// hook响应 dynamicTask.stop(timeOutTaskKey);
onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid); // hook响应
hookEvent.response(mediaServerItemInuse, response); onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);
logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); hookEvent.response(mediaServerItemInuse, response);
logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
}, (event) -> { }, (event) -> {
ResponseEvent responseEvent = (ResponseEvent)event.event; ResponseEvent responseEvent = (ResponseEvent)event.event;
String contentString = new String(responseEvent.getResponse().getRawContent()); String contentString = new String(responseEvent.getResponse().getRawContent());
// 获取ssrc // 获取ssrc
int ssrcIndex = contentString.indexOf("y="); int ssrcIndex = contentString.indexOf("y=");
// 检查是否有y字段 // 检查是否有y字段
if (ssrcIndex >= 0) { if (ssrcIndex >= 0) {
//ssrc规定长度为10字节不取余下长度以避免后续还有f=字段 TODO 后续对不规范的非10位ssrc兼容 //ssrc规定长度为10字节不取余下长度以避免后续还有f=字段 TODO 后续对不规范的非10位ssrc兼容
String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
// 查询到ssrc不一致且开启了ssrc校验则需要针对处理 // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
if (ssrc.equals(ssrcInResponse)) { if (ssrc.equals(ssrcInResponse)) {
return;
}
logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
// ssrc 不可用
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
event.msg = "下级自定义了ssrc,但是此ssrc不可用";
event.statusCode = 400;
errorEvent.response(event);
return; return;
} }
logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
// ssrc 不可用
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
event.msg = "下级自定义了ssrc,但是此ssrc不可用";
event.statusCode = 400;
errorEvent.response(event);
return;
}
// 单端口模式streamId也有变化需要重新设置监听
if (!mediaServerItem.isRtpEnable()) {
// 添加订阅
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
subscribe.removeSubscribe(hookSubscribe);
hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString());
dynamicTask.stop(timeOutTaskKey);
// hook响应
onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
hookEvent.response(mediaServerItemInUse, response);
});
}
// 关闭rtp server
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
// 重新开启ssrc server
mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
// 单端口模式streamId也有变化需要重新设置监听
if (!mediaServerItem.isRtpEnable()) {
// 添加订阅
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
subscribe.removeSubscribe(hookSubscribe);
hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString());
dynamicTask.stop(timeOutTaskKey);
// hook响应
onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
hookEvent.response(mediaServerItemInUse, response);
});
} }
// 关闭rtp server
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
// 重新开启ssrc server
mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
} }
} }, (event) -> {
}, (event) -> { dynamicTask.stop(timeOutTaskKey);
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
errorEvent.response(event);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 点播消息: {}", e.getMessage());
dynamicTask.stop(timeOutTaskKey); dynamicTask.stop(timeOutTaskKey);
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
// 释放ssrc // 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
errorEvent.response(event); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
}); eventResult.msg = "命令发送失败";
errorEvent.response(eventResult);
}
} }
@Override @Override
@ -439,17 +456,18 @@ public class PlayServiceImpl implements IPlayService {
playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setCode(ErrorCode.ERROR100.getCode());
playBackResult.setMsg("回放超时"); playBackResult.setMsg("回放超时");
playBackResult.setData(requestMessage); playBackResult.setData(requestMessage);
SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源 try {
if (dialog != null) { cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage());
} catch (SsrcTransactionNotFoundException e) {
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
}else {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
} }
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
// 回复之前所有的点播请求 // 回复之前所有的点播请求
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时")); result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
@ -489,59 +507,67 @@ public class PlayServiceImpl implements IPlayService {
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
}; };
cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, try {
hookEvent, eventResult -> { cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
if (eventResult.type == SipSubscribe.EventResultType.response) { hookEvent, eventResult -> {
ResponseEvent responseEvent = (ResponseEvent)eventResult.event; if (eventResult.type == SipSubscribe.EventResultType.response) {
String contentString = new String(responseEvent.getResponse().getRawContent()); ResponseEvent responseEvent = (ResponseEvent)eventResult.event;
// 获取ssrc String contentString = new String(responseEvent.getResponse().getRawContent());
int ssrcIndex = contentString.indexOf("y="); // 获取ssrc
// 检查是否有y字段 int ssrcIndex = contentString.indexOf("y=");
if (ssrcIndex >= 0) { // 检查是否有y字段
//ssrc规定长度为10字节不取余下长度以避免后续还有f=字段 TODO 后续对不规范的非10位ssrc兼容 if (ssrcIndex >= 0) {
String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); //ssrc规定长度为10字节不取余下长度以避免后续还有f=字段 TODO 后续对不规范的非10位ssrc兼容
// 查询到ssrc不一致且开启了ssrc校验则需要针对处理 String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
return; if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
}
logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
// ssrc 不可用
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
eventResult.statusCode = 400;
errorEvent.response(eventResult);
return; return;
} }
logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
// 单端口模式streamId也有变化需要重新设置监听 if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
if (!mediaServerItem.isRtpEnable()) { // ssrc 不可用
// 添加订阅 // 释放ssrc
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
subscribe.removeSubscribe(hookSubscribe); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{ eventResult.statusCode = 400;
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString()); errorEvent.response(eventResult);
dynamicTask.stop(playBackTimeOutTaskKey); return;
// hook响应 }
onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); // 单端口模式streamId也有变化需要重新设置监听
}); if (!mediaServerItem.isRtpEnable()) {
// 添加订阅
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
subscribe.removeSubscribe(hookSubscribe);
hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString());
dynamicTask.stop(playBackTimeOutTaskKey);
// hook响应
onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
});
}
// 关闭rtp server
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
// 重新开启ssrc server
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
} }
// 关闭rtp server
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
// 重新开启ssrc server
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
} }
} }
}
}, errorEvent); }, 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; return result;
} }
@ -587,46 +613,57 @@ public class PlayServiceImpl implements IPlayService {
downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg("录像下载请求超时"); downloadResult.setMsg("录像下载请求超时");
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
if (dialog != null) { try {
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源 cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null); } catch (InvalidArgumentException | ParseException | SipException e) {
}else { logger.error("[录像流]录像下载请求超时, 发送BYE失败 {}", e.getMessage());
} catch (SsrcTransactionNotFoundException e) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
} }
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
// 回复之前所有的点播请求 // 回复之前所有的点播请求
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
}, userSetting.getPlayTimeout()); }, userSetting.getPlayTimeout());
cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
inviteStreamInfo -> { SipSubscribe.Event errorEvent = event -> {
logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); dynamicTask.stop(downLoadTimeOutTaskKey);
dynamicTask.stop(downLoadTimeOutTaskKey); downloadResult.setCode(ErrorCode.ERROR100.getCode());
StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
streamInfo.setStartTime(startTime); wvpResult.setCode(ErrorCode.ERROR100.getCode());
streamInfo.setEndTime(endTime); wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); downloadResult.setEvent(event);
wvpResult.setCode(ErrorCode.SUCCESS.getCode()); hookCallBack.call(downloadResult);
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
wvpResult.setData(streamInfo); };
downloadResult.setCode(ErrorCode.SUCCESS.getCode());
downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); try {
downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
downloadResult.setResponse(inviteStreamInfo.getResponse()); inviteStreamInfo -> {
hookCallBack.call(downloadResult); logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
}, event -> { dynamicTask.stop(downLoadTimeOutTaskKey);
dynamicTask.stop(downLoadTimeOutTaskKey); StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
downloadResult.setCode(ErrorCode.ERROR100.getCode()); streamInfo.setStartTime(startTime);
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); streamInfo.setEndTime(endTime);
wvpResult.setCode(ErrorCode.ERROR100.getCode()); redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); wvpResult.setCode(ErrorCode.SUCCESS.getCode());
downloadResult.setEvent(event); wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
hookCallBack.call(downloadResult); wvpResult.setData(streamInfo);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); downloadResult.setCode(ErrorCode.SUCCESS.getCode());
}); downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
downloadResult.setResponse(inviteStreamInfo.getResponse());
hookCallBack.call(downloadResult);
}, 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; return result;
} }
@ -705,7 +742,11 @@ public class PlayServiceImpl implements IPlayService {
for (SendRtpItem sendRtpItem : sendRtpItems) { for (SendRtpItem sendRtpItem : sendRtpItems) {
if (sendRtpItem.getMediaServerId().equals(mediaServerId)) { if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId()); try {
sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
} }
} }
} }
@ -714,8 +755,17 @@ public class PlayServiceImpl implements IPlayService {
if (allSsrc.size() > 0) { if (allSsrc.size() > 0) {
for (SsrcTransaction ssrcTransaction : allSsrc) { for (SsrcTransaction ssrcTransaction : allSsrc) {
if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) { if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) {
cmder.streamByeCmd(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), Device device = deviceService.queryDevice(ssrcTransaction.getDeviceId());
ssrcTransaction.getStream(), null); 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());
}
} }
} }
} }

View File

@ -16,7 +16,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import javax.validation.constraints.NotNull; import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
@ -78,16 +80,28 @@ public class RedisAlarmMsgListener implements MessageListener {
List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
if (parentPlatforms.size() > 0) { if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) { for (ParentPlatform parentPlatform : parentPlatforms) {
commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); try {
commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
}
} }
} }
}else { }else {
Device device = storage.queryVideoDevice(gbId); Device device = storage.queryVideoDevice(gbId);
ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
if (device != null && platform == null) { if (device != null && platform == null) {
commander.sendAlarmMessage(device, deviceAlarm); try {
commander.sendAlarmMessage(device, deviceAlarm);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
}
}else if (device == null && platform != null){ }else if (device == null && platform != null){
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); try {
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
}
}else { }else {
logger.warn("无法确定" + gbId + "是平台还是设备"); logger.warn("无法确定" + gbId + "是平台还是设备");
} }

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition; package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
import java.text.ParseException;
import java.util.List; import java.util.List;
import java.util.UUID; 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.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
/** /**
* 位置信息管理 * 位置信息管理
*/ */
@ -105,13 +109,18 @@ public class MobilePositionController {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId; String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
cmder.mobilePostitionQuery(device, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.mobilePostitionQuery(device, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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); DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L);
result.onTimeout(()->{ result.onTimeout(()->{
logger.warn(String.format("获取移动位置信息超时")); logger.warn(String.format("获取移动位置信息超时"));

View File

@ -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.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener;
import com.genersoft.iot.vmp.service.IDeviceAlarmService; import com.genersoft.iot.vmp.service.IDeviceAlarmService;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
@ -16,6 +17,8 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag; 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.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -23,6 +26,9 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -33,6 +39,8 @@ import java.util.List;
@RequestMapping("/api/alarm") @RequestMapping("/api/alarm")
public class AlarmController { public class AlarmController {
private final static Logger logger = LoggerFactory.getLogger(AlarmController.class);
@Autowired @Autowired
private IDeviceAlarmService deviceAlarmService; private IDeviceAlarmService deviceAlarmService;
@ -108,9 +116,19 @@ public class AlarmController {
deviceAlarm.setLatitude(39.33333); deviceAlarm.setLatitude(39.33333);
if (device != null && platform == null) { if (device != null && platform == null) {
commander.sendAlarmMessage(device, deviceAlarm);
try {
commander.sendAlarmMessage(device, deviceAlarm);
} catch (InvalidArgumentException | SipException | ParseException e) {
}
}else if (device == null && platform != null){ }else if (device == null && platform != null){
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); try {
commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}else { }else {
throw new ControllerException(ErrorCode.ERROR100.getCode(),"无法确定" + deviceId + "是平台还是设备"); throw new ControllerException(ErrorCode.ERROR100.getCode(),"无法确定" + deviceId + "是平台还是设备");
} }

View File

@ -8,12 +8,14 @@
package com.genersoft.iot.vmp.vmanager.gb28181.device; package com.genersoft.iot.vmp.vmanager.gb28181.device;
import com.alibaba.fastjson.JSONObject; 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.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -26,6 +28,9 @@ import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID; import java.util.UUID;
@Tag(name = "国标设备配置") @Tag(name = "国标设备配置")
@ -75,14 +80,19 @@ public class DeviceConfig {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId; String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg));
}); resultHolder.invokeResult(msg);
DeferredResult<String> result = new DeferredResult<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<String>(3 * 1000L);
result.onTimeout(() -> { result.onTimeout(() -> {
logger.warn(String.format("设备配置操作超时, 设备未返回应答指令")); logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
// 释放rtpserver // 释放rtpserver
@ -121,14 +131,19 @@ public class DeviceConfig {
String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId); String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
cmder.deviceConfigQuery(device, channelId, configType, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.deviceConfigQuery(device, channelId, configType, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg));
}); resultHolder.invokeResult(msg);
DeferredResult<String> result = new DeferredResult<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<String > (3 * 1000L);
result.onTimeout(()->{ result.onTimeout(()->{
logger.warn(String.format("获取设备配置超时")); logger.warn(String.format("获取设备配置超时"));
// 释放rtpserver // 释放rtpserver

View File

@ -29,6 +29,9 @@ import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID; import java.util.UUID;
@Tag(name = "国标设备控制") @Tag(name = "国标设备控制")
@ -61,10 +64,12 @@ public class DeviceControl {
logger.debug("设备远程启动API调用"); logger.debug("设备远程启动API调用");
} }
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (!cmder.teleBootCmd(device)) { try {
logger.warn("设备远程启动API调用失败"); cmder.teleBootCmd(device);
throw new ControllerException(ErrorCode.ERROR100); } catch (InvalidArgumentException | SipException | ParseException e) {
} logger.error("[命令发送失败] 远程启动: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
} }
/** /**
@ -101,13 +106,18 @@ public class DeviceControl {
return result; return result;
} }
resultHolder.put(key, uuid, result); resultHolder.put(key, uuid, result);
cmder.recordCmd(device, channelId, recordCmdStr, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.recordCmd(device, channelId, recordCmdStr, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeAllResult(msg); 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; return result;
} }
@ -123,21 +133,26 @@ public class DeviceControl {
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "guardCmdStr", description = "命令, 可选值SetGuard布防ResetGuard撤防", required = true) @Parameter(name = "guardCmdStr", description = "命令, 可选值SetGuard布防ResetGuard撤防", required = true)
@GetMapping("/guard/{deviceId}/{guardCmdStr}") @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()) { if (logger.isDebugEnabled()) {
logger.debug("布防/撤防API调用"); logger.debug("布防/撤防API调用");
} }
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
String uuid =UUID.randomUUID().toString(); String uuid =UUID.randomUUID().toString();
cmder.guardCmd(device, guardCmdStr, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.guardCmd(device, guardCmdStr, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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); resultHolder.put(key, uuid, result);
result.onTimeout(() -> { result.onTimeout(() -> {
logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令")); logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
@ -174,14 +189,19 @@ public class DeviceControl {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
cmder.alarmCmd(device, alarmMethod, alarmType, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
result.onTimeout(() -> { result.onTimeout(() -> {
logger.warn(String.format("报警复位操作超时, 设备未返回应答指令")); logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
// 释放rtpserver // 释放rtpserver
@ -205,23 +225,23 @@ public class DeviceControl {
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号") @Parameter(name = "channelId", description = "通道国标编号")
@GetMapping("/i_frame/{deviceId}") @GetMapping("/i_frame/{deviceId}")
public ResponseEntity<String> iFrame(@PathVariable String deviceId, public JSONObject iFrame(@PathVariable String deviceId,
@RequestParam(required = false) String channelId) { @RequestParam(required = false) String channelId) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("强制关键帧API调用"); logger.debug("强制关键帧API调用");
} }
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
boolean sucsess = cmder.iFrameCmd(device, channelId); try {
if (sucsess) { cmder.iFrameCmd(device, channelId);
JSONObject json = new JSONObject(); } catch (InvalidArgumentException | SipException | ParseException e) {
json.put("DeviceID", deviceId); logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
json.put("ChannelID", channelId); throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
json.put("Result", "OK");
return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
} else {
logger.warn("强制关键帧API调用失败");
return new ResponseEntity<String>("强制关键帧API调用失败", HttpStatus.INTERNAL_SERVER_ERROR);
} }
JSONObject json = new JSONObject();
json.put("DeviceID", deviceId);
json.put("ChannelID", channelId);
json.put("Result", "OK");
return json;
} }
/** /**
@ -240,7 +260,7 @@ public class DeviceControl {
@Parameter(name = "presetIndex", description = "调用预置位编号") @Parameter(name = "presetIndex", description = "调用预置位编号")
@Parameter(name = "resetTime", description = "自动归位时间间隔") @Parameter(name = "resetTime", description = "自动归位时间间隔")
@GetMapping("/home_position/{deviceId}/{enabled}") @GetMapping("/home_position/{deviceId}/{enabled}")
public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId, public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
@PathVariable String enabled, @PathVariable String enabled,
@RequestParam(required = false) String resetTime, @RequestParam(required = false) String resetTime,
@RequestParam(required = false) String presetIndex, @RequestParam(required = false) String presetIndex,
@ -251,14 +271,19 @@ public class DeviceControl {
String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId); String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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(() -> { result.onTimeout(() -> {
logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令")); logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
// 释放rtpserver // 释放rtpserver
@ -297,14 +322,14 @@ public class DeviceControl {
@Parameter(name = "lengthx", description = "拉框长度像素值", required = true) @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
@Parameter(name = "lengthy", description = "lengthy", required = true) @Parameter(name = "lengthy", description = "lengthy", required = true)
@GetMapping("drag_zoom/zoom_in") @GetMapping("drag_zoom/zoom_in")
public ResponseEntity<String> dragZoomIn(@RequestParam String deviceId, public void dragZoomIn(@RequestParam String deviceId,
@RequestParam(required = false) String channelId, @RequestParam(required = false) String channelId,
@RequestParam int length, @RequestParam int length,
@RequestParam int width, @RequestParam int width,
@RequestParam int midpointx, @RequestParam int midpointx,
@RequestParam int midpointy, @RequestParam int midpointy,
@RequestParam int lengthx, @RequestParam int lengthx,
@RequestParam int lengthy){ @RequestParam int lengthy) throws RuntimeException {
if (logger.isDebugEnabled()) { 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)); 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("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n"); cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomIn>\r\n"); cmdXml.append("</DragZoomIn>\r\n");
cmder.dragZoomCmd(device, channelId, cmdXml.toString()); try {
return new ResponseEntity<String>("success", HttpStatus.OK); cmder.dragZoomCmd(device, channelId, cmdXml.toString());
} 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 = "lengthx", description = "拉框长度像素值", required = true)
@Parameter(name = "lengthy", description = "拉框宽度像素值", required = true) @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
@GetMapping("/drag_zoom/zoom_out") @GetMapping("/drag_zoom/zoom_out")
public ResponseEntity<String> dragZoomOut(@RequestParam String deviceId, public void dragZoomOut(@RequestParam String deviceId,
@RequestParam(required = false) String channelId, @RequestParam(required = false) String channelId,
@RequestParam int length, @RequestParam int length,
@RequestParam int width, @RequestParam int width,
@ -366,7 +395,11 @@ public class DeviceControl {
cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n"); cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n"); cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
cmdXml.append("</DragZoomOut>\r\n"); cmdXml.append("</DragZoomOut>\r\n");
cmder.dragZoomCmd(device, channelId, cmdXml.toString()); try {
return new ResponseEntity<String>("success",HttpStatus.OK); cmder.dragZoomCmd(device, channelId, cmdXml.toString());
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 拉框缩小: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
} }
} }

View File

@ -39,8 +39,11 @@ import org.springframework.web.context.request.async.DeferredResult;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.sip.DialogState; import javax.sip.DialogState;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;
import java.text.ParseException;
import java.util.*; import java.util.*;
@Tag(name = "国标设备查询", description = "国标设备查询") @Tag(name = "国标设备查询", description = "国标设备查询")
@ -315,13 +318,18 @@ public class DeviceQuery {
result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK)); result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK));
return result; return result;
} }
cmder.deviceStatusQuery(device, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.deviceStatusQuery(device, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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(()->{ result.onTimeout(()->{
logger.warn(String.format("获取设备状态超时")); logger.warn(String.format("获取设备状态超时"));
// 释放rtpserver // 释放rtpserver
@ -368,14 +376,19 @@ public class DeviceQuery {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId; String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId;
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("设备报警查询失败,错误码: %s, %s",event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
result.onTimeout(()->{ result.onTimeout(()->{
logger.warn(String.format("设备报警查询超时")); logger.warn(String.format("设备报警查询超时"));
// 释放rtpserver // 释放rtpserver

View File

@ -29,6 +29,9 @@ import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.List; import java.util.List;
/** /**
@ -212,20 +215,37 @@ public class PlatformController {
// 保存时启用就发送注册 // 保存时启用就发送注册
if (parentPlatform.isEnable()) { if (parentPlatform.isEnable()) {
if (parentPlatformOld != null && parentPlatformOld.isStatus()) { if (parentPlatformOld != null && parentPlatformOld.isStatus()) {
commanderForPlatform.unregister(parentPlatformOld, null, null); try {
commanderForPlatform.unregister(parentPlatformOld, null, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
}
try { try {
Thread.sleep(500); Thread.sleep(500);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); logger.error("[线程休眠失败] : {}", e.getMessage());
} }
// 只要保存就发送注册 // 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null); try {
commanderForPlatform.register(parentPlatform, null, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
}
} else { } else {
// 只要保存就发送注册 // 只要保存就发送注册
commanderForPlatform.register(parentPlatform, null, null); try {
commanderForPlatform.register(parentPlatform, null, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
}
} }
} else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
commanderForPlatform.unregister(parentPlatformOld, null, null); try {
commanderForPlatform.unregister(parentPlatformOld, null, null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
}
// 停止订阅相关的定时任务 // 停止订阅相关的定时任务
subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
} }
@ -258,17 +278,21 @@ public class PlatformController {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在");
} }
// 发送离线消息,无论是否成功都删除缓存 // 发送离线消息,无论是否成功都删除缓存
commanderForPlatform.unregister(parentPlatform, (event -> { try {
// 清空redis缓存 commanderForPlatform.unregister(parentPlatform, (event -> {
redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId()); // 清空redis缓存
redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId()); redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId()); redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
}), (event -> { redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
// 清空redis缓存 }), (event -> {
redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId()); // 清空redis缓存
redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId()); redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId()); redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
})); redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
}));
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
}
boolean deleteResult = storager.deleteParentPlatform(parentPlatform); boolean deleteResult = storager.deleteParentPlatform(parentPlatform);
storager.delCatalogByPlatformId(parentPlatform.getServerGBId()); storager.delCatalogByPlatformId(parentPlatform.getServerGBId());

View File

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException; 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.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.bean.Device; 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 com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.web.context.request.async.DeferredResult; 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.List;
import java.util.UUID; import java.util.UUID;
@ -102,12 +106,23 @@ public class PlayController {
throw new ControllerException(ErrorCode.ERROR400); 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); StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
if (streamInfo == null) { if (streamInfo == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到"); 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); redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
@ -221,18 +236,23 @@ public class PlayController {
resultHolder.invokeResult(msg); resultHolder.invokeResult(msg);
return result; return result;
} }
cmder.audioBroadcastCmd(device, (event) -> { try {
RequestMessage msg = new RequestMessage(); cmder.audioBroadcastCmd(device, (event) -> {
msg.setKey(key); RequestMessage msg = new RequestMessage();
msg.setId(uuid); msg.setKey(key);
JSONObject json = new JSONObject(); msg.setId(uuid);
json.put("DeviceID", deviceId); JSONObject json = new JSONObject();
json.put("CmdType", "Broadcast"); json.put("DeviceID", deviceId);
json.put("Result", "Failed"); json.put("CmdType", "Broadcast");
json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", event.statusCode, event.msg)); json.put("Result", "Failed");
msg.setData(json); json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg); 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(() -> { result.onTimeout(() -> {
logger.warn("语音广播操作超时, 设备未返回应答指令"); logger.warn("语音广播操作超时, 设备未返回应答指令");

View File

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException; 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.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 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.RequestMapping;
import org.springframework.web.bind.annotation.RestController; 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.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
/** /**
* @author lin * @author lin
*/ */
@ -92,7 +96,15 @@ public class PlaybackController {
if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) { if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
throw new ControllerException(ErrorCode.ERROR400); 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不存在"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
} }
Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
cmder.playPauseCmd(device, streamInfo); 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不存在"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
} }
Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
cmder.playResumeCmd(device, streamInfo); 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不存在"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
} }
Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
cmder.playSeekCmd(device, streamInfo, seekTime); try {
cmder.playSeekCmd(device, streamInfo, seekTime);
} catch (InvalidArgumentException | ParseException | SipException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
} }
@Operation(summary = "回放倍速播放") @Operation(summary = "回放倍速播放")
@ -157,6 +181,10 @@ public class PlaybackController {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed0.25 0.5 1、2、4"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed0.25 0.5 1、2、4");
} }
Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
cmder.playSpeedCmd(device, streamInfo, speed); try {
cmder.playSpeedCmd(device, streamInfo, speed);
} catch (InvalidArgumentException | ParseException | SipException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
} }
} }

View File

@ -1,6 +1,8 @@
package com.genersoft.iot.vmp.vmanager.gb28181.ptz; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -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.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID; import java.util.UUID;
@Tag(name = "云台控制") @Tag(name = "云台控制")
@ -98,7 +103,12 @@ public class PtzController {
default: default:
break; break;
} }
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed); 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); Device device = storager.queryVideoDevice(deviceId);
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2); 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,13 +161,18 @@ public class PtzController {
return result; return result;
} }
resultHolder.put(key, uuid, result); resultHolder.put(key, uuid, result);
cmder.presetQuery(device, channelId, event -> { try {
RequestMessage msg = new RequestMessage(); cmder.presetQuery(device, channelId, event -> {
msg.setId(uuid); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setId(uuid);
msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg)); msg.setKey(key);
resultHolder.invokeResult(msg); 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; return result;
} }
} }

View File

@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException; 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.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.utils.DateUtil; 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.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 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.time.LocalDate;
import java.util.UUID; import java.util.UUID;
@ -54,6 +59,12 @@ public class GBRecordController {
@Autowired @Autowired
private IPlayService playService; private IPlayService playService;
@Autowired
private IDeviceService deviceService;
@Operation(summary = "录像查询") @Operation(summary = "录像查询")
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@ -81,13 +92,18 @@ public class GBRecordController {
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
msg.setId(uuid); msg.setId(uuid);
msg.setKey(key); msg.setKey(key);
cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> { try {
WVPResult<RecordInfo> wvpResult = new WVPResult<>(); cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
wvpResult.setCode(ErrorCode.ERROR100.getCode()); WVPResult<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg); wvpResult.setCode(ErrorCode.ERROR100.getCode());
msg.setData(wvpResult); wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg);
resultHolder.invokeResult(msg); 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查询 // 录像查询以channelId作为deviceId查询
resultHolder.put(key, uuid, result); resultHolder.put(key, uuid, result);
@ -131,14 +147,24 @@ public class GBRecordController {
@GetMapping("/download/stop/{deviceId}/{channelId}/{stream}") @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
cmder.streamByeCmd(deviceId, channelId, stream, null);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId)); logger.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId));
} }
if (deviceId == null || channelId == null) { 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());
} }
} }

View File

@ -1,14 +1,20 @@
package com.genersoft.iot.vmp.web.gb28181; package com.genersoft.iot.vmp.web.gb28181;
import com.alibaba.fastjson.JSONObject; 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.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
/** /**
* API兼容设备控制 * API兼容设备控制
*/ */
@ -35,7 +41,7 @@ public class ApiControlController {
* @return * @return
*/ */
@RequestMapping(value = "/ptz") @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)Integer channel,
@RequestParam(required = false)String code, @RequestParam(required = false)String code,
@RequestParam(required = false)Integer speed){ @RequestParam(required = false)Integer speed){
@ -48,9 +54,7 @@ public class ApiControlController {
if (speed == null) {speed = 0;} if (speed == null) {speed = 0;}
Device device = storager.queryVideoDevice(serial); Device device = storager.queryVideoDevice(serial);
if (device == null) { if (device == null) {
JSONObject result = new JSONObject(); throw new ControllerException(ErrorCode.ERROR100.getCode(), "device[ " + serial + " ]未找到");
result.put("error","device[ " + serial + " ]未找到");
return result;
} }
int cmdCode = 0; int cmdCode = 0;
switch (command){ switch (command){
@ -91,7 +95,11 @@ public class ApiControlController {
break; break;
} }
// 默认值 50 // 默认值 50
cmder.frontEndCmd(device, code, cmdCode, speed, speed, speed); try {
return null; cmder.frontEndCmd(device, code, cmdCode, speed, speed, speed);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
} }
} }

View File

@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.web.gb28181;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 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.service.IPlayService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@ -17,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
/** /**
* API兼容实时直播 * API兼容实时直播
*/ */
@ -40,6 +46,9 @@ public class ApiStreamController {
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@Autowired
private IDeviceService deviceService;
@Autowired @Autowired
private IPlayService playService; private IPlayService playService;
@ -177,7 +186,19 @@ public class ApiStreamController {
result.put("error","未找到流信息"); result.put("error","未找到流信息");
return result; 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); redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
return null; return null;