Merge pull request #625 from 648540858/wvp-dialog

强化对与不通设备的兼容能力
This commit is contained in:
648540858 2022-09-23 23:17:39 +08:00 committed by GitHub
commit d7355a671b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 3145 additions and 3400 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.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.gb28181.device.DeviceQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils;
@ -15,6 +18,8 @@ import java.util.regex.Pattern;
@Configuration("mediaConfig")
public class MediaConfig{
private final static Logger logger = LoggerFactory.getLogger(MediaConfig.class);
// 修改必须配置不再支持自动获取
@Value("${media.id}")
private String id;
@ -174,7 +179,7 @@ public class MediaConfig{
try {
hostAddress = InetAddress.getByName(sdpIp).getHostAddress();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
logger.error("[获取SDP IP]: 域名解析失败");
}
return hostAddress;
}

View File

@ -1,7 +1,10 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd.AlarmQueryMessageHandler;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.SystemInfoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@ -14,6 +17,8 @@ import java.util.Map;
@Component
public class SystemInfoTimerTask {
private Logger logger = LoggerFactory.getLogger(SystemInfoTimerTask.class);
@Autowired
private IRedisCatchStorage redisCatchStorage;
@ -27,7 +32,7 @@ public class SystemInfoTimerTask {
Map<String, String> networkInterfaces = SystemInfoUtils.getNetworkInterfaces();
redisCatchStorage.addNetInfo(networkInterfaces);
} catch (InterruptedException e) {
e.printStackTrace();
logger.error("[获取系统信息失败] {}", e.getMessage());
}
}

View File

@ -2,35 +2,23 @@ package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.common.VersionPo;
import com.genersoft.iot.vmp.utils.GitUtil;
import com.genersoft.iot.vmp.utils.JarFileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class VersionInfo {
@Autowired
VersionConfig config;
@Autowired
GitUtil gitUtil;
@Autowired
JarFileUtils jarFileUtils;
public VersionPo getVersion() {
VersionPo versionPo = new VersionPo();
Map<String,String> map=jarFileUtils.readJarFile();
versionPo.setGIT_Revision(gitUtil.getGitCommitId());
versionPo.setCreate_By(map.get("Created-By"));
versionPo.setGIT_BRANCH(gitUtil.getBranch());
versionPo.setGIT_URL(gitUtil.getGitUrl());
versionPo.setBUILD_DATE(gitUtil.getBuildDate());
versionPo.setArtifactId(config.getArtifactId());
versionPo.setGIT_Revision_SHORT(gitUtil.getCommitIdShort());
versionPo.setVersion(config.getVersion());
versionPo.setProject(config.getDescription());
versionPo.setBuild_Jdk(map.get("Build-Jdk"));
versionPo.setVersion(gitUtil.getBuildVersion());
return versionPo;
}

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

View File

@ -1,44 +0,0 @@
package com.genersoft.iot.vmp.gb28181.auth;
import com.genersoft.iot.vmp.storager.impl.VideoManagerStorageImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
/**
* @description:注册逻辑处理当设备注册后触发逻辑
* @author: swwheihei
* @date: 2020年5月8日 下午9:41:46
*/
@Component
public class RegisterLogicHandler {
private Logger logger = LoggerFactory.getLogger(RegisterLogicHandler.class);
@Autowired
private SIPCommander cmder;
@Autowired
private VideoManagerStorageImpl storager;
public void onRegister(Device device) {
// 只有第一次注册时调用查询设备信息如需更新调用更新API接口
// // TODO 此处错误无法获取到通道
// Device device1 = storager.queryVideoDevice(device.getDeviceId());
// if (device.isFirsRegister()) {
// logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());
// try {
// Thread.sleep(100);
// cmder.deviceInfoQuery(device);
// Thread.sleep(100);
// cmder.catalogQuery(device, null);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
}

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;
public class DeviceNotFoundEvent extends EventObject {
private String callId;
/**
* Constructs a prototypical Event.
*
@ -14,8 +17,11 @@ public class DeviceNotFoundEvent extends EventObject {
super(dialog);
}
public String getCallId() {
return callId;
}
public Dialog getDialog() {
return (Dialog)super.getSource();
public void setCallId(String callId) {
this.callId = callId;
}
}

View File

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

View File

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

View File

@ -1,15 +1,10 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.utils.SerializeUtils;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.header.*;
import javax.sip.message.Request;
public class SubscribeInfo {

View File

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

View File

@ -51,7 +51,6 @@ public class AlarmEventListener implements ApplicationListener<AlarmEvent> {
}
// 移除已关闭的连接
it.remove();
// e.printStackTrace();
}
}
}

View File

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

View File

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

View File

@ -3,19 +3,15 @@ package com.genersoft.iot.vmp.gb28181.session;
import java.util.ArrayList;
import java.util.List;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.utils.SerializeUtils;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import gov.nist.javax.sip.stack.SIPDialog;
import gov.nist.javax.sip.message.SIPResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* @description:视频流session管理器管理视频预览预览回放的通信句柄
@ -42,15 +38,14 @@ public class VideoStreamSessionManager {
* @param callId 一次请求的CallID
* @param stream 流名称
* @param mediaServerId 所使用的流媒体ID
* @param transaction 事务
* @param response 回复
*/
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction, SessionType type){
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, SessionType type){
SsrcTransaction ssrcTransaction = new SsrcTransaction();
ssrcTransaction.setDeviceId(deviceId);
ssrcTransaction.setChannelId(channelId);
ssrcTransaction.setStream(stream);
byte[] transactionByteArray = SerializeUtils.serialize(transaction);
ssrcTransaction.setTransaction(transactionByteArray);
ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
ssrcTransaction.setCallId(callId);
ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId);
@ -62,53 +57,6 @@ public class VideoStreamSessionManager {
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
}
public void put(String deviceId, String channelId, String callId, Dialog dialog){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
if (ssrcTransaction != null) {
byte[] dialogByteArray = SerializeUtils.serialize(dialog);
ssrcTransaction.setDialog(dialogByteArray);
}
RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
+ "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
+ ssrcTransaction.getStream(), ssrcTransaction);
}
public ClientTransaction getTransaction(String deviceId, String channelId, String stream, String callId){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, stream);
if (ssrcTransaction == null) {
return null;
}
byte[] transactionByteArray = ssrcTransaction.getTransaction();
ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
return clientTransaction;
}
public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) {
return null;
}
byte[] dialogByteArray = ssrcTransaction.getDialog();
if (dialogByteArray == null) {
return null;
}
SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
return dialog;
}
public SIPDialog getDialogByCallId(String deviceId, String channelId, String callId){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
if (ssrcTransaction == null) {
return null;
}
byte[] dialogByteArray = ssrcTransaction.getDialog();
if (dialogByteArray == null) {
return null;
}
return (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
}
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
if (ObjectUtils.isEmpty(deviceId)) {

View File

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

View File

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

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
@ -9,6 +10,11 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import gov.nist.javax.sip.message.SIPRequest;
import javax.sip.Dialog;
import javax.sip.InvalidArgumentException;
import javax.sip.PeerUnavailableException;
import javax.sip.SipException;
import javax.sip.message.Request;
import java.text.ParseException;
/**
* @description:设备能力接口用于定义设备的控制查询能力
@ -25,7 +31,7 @@ public interface ISIPCommander {
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
*/
boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown);
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException;
/**
* 云台方向放控制
@ -36,7 +42,7 @@ public interface ISIPCommander {
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param moveSpeed 镜头移动速度
*/
boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed);
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
/**
* 云台缩放控制使用配置文件中的默认镜头缩放速度
@ -45,7 +51,7 @@ public interface ISIPCommander {
* @param channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
*/
boolean ptzZoomCmd(Device device,String channelId,int inOut);
void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException;
/**
* 云台缩放控制
@ -54,7 +60,7 @@ public interface ISIPCommander {
* @param channelId 预览通道
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
*/
boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed);
void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
/**
* 云台控制支持方向与缩放控制
@ -67,7 +73,7 @@ public interface ISIPCommander {
* @param moveSpeed 镜头移动速度
* @param zoomSpeed 镜头缩放速度
*/
boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
/**
* 前端控制包括PTZ指令FI指令预置位指令巡航指令扫描指令和辅助开关指令
@ -79,7 +85,7 @@ public interface ISIPCommander {
* @param parameter2 数据2
* @param combineCode2 组合码2
*/
boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2);
void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
/**
* 前端控制指令用于转发上级指令
@ -87,14 +93,14 @@ public interface ISIPCommander {
* @param channelId 预览通道
* @param cmdString 前端控制指令串
*/
boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 请求预览视频流
* @param device 视频设备
* @param channelId 预览通道
*/
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 请求回放视频流
@ -104,7 +110,7 @@ public interface ISIPCommander {
* @param startTime 开始时间,格式要求yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss
*/
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 请求历史媒体下载
@ -117,33 +123,33 @@ public interface ISIPCommander {
*/
void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
SipSubscribe.Event errorEvent);
SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 视频流停止
*/
void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent);
void streamByeCmd(String deviceId, String channelId, String stream, String callId);
void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
/**
* 回放暂停
*/
void playPauseCmd(Device device, StreamInfo streamInfo);
void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
/**
* 回放恢复
*/
void playResumeCmd(Device device, StreamInfo streamInfo);
void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
/**
* 回放拖动播放
*/
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime);
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException;
/**
* 回放倍速播放
*/
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed);
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
/**
* 回放控制
@ -151,7 +157,8 @@ public interface ISIPCommander {
* @param streamInfo
* @param content
*/
void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
/**
* 语音广播
@ -159,15 +166,15 @@ public interface ISIPCommander {
* @param device 视频设备
* @param channelId 预览通道
*/
boolean audioBroadcastCmd(Device device,String channelId);
void audioBroadcastCmd(Device device,String channelId);
/**
* 语音广播
*
* @param device 视频设备
*/
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent);
boolean audioBroadcastCmd(Device device);
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
/**
* 音视频录像控制
@ -176,21 +183,21 @@ public interface ISIPCommander {
* @param channelId 预览通道
* @param recordCmdStr 录像命令Record / StopRecord
*/
boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent);
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 远程启动控制命令
*
* @param device 视频设备
*/
boolean teleBootCmd(Device device);
void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
/**
* 报警布防/撤防命令
*
* @param device 视频设备
*/
boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent);
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 报警复位命令
@ -199,7 +206,7 @@ public interface ISIPCommander {
* @param alarmMethod 报警方式可选
* @param alarmType 报警类型可选
*/
boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent);
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
@ -207,7 +214,7 @@ public interface ISIPCommander {
* @param device 视频设备
* @param channelId 预览通道
*/
boolean iFrameCmd(Device device, String channelId);
void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
/**
* 看守位控制命令
@ -217,14 +224,14 @@ public interface ISIPCommander {
* @param resetTime 自动归位时间间隔开启看守位时使用单位:(s)
* @param presetIndex 调用预置位编号开启看守位时使用取值范围0~255
*/
boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent);
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 设备配置命令
*
* @param device 视频设备
*/
boolean deviceConfigCmd(Device device);
void deviceConfigCmd(Device device);
/**
* 设备配置命令basicParam
@ -236,14 +243,14 @@ public interface ISIPCommander {
* @param heartBeatInterval 心跳间隔时间可选
* @param heartBeatCount 心跳超时次数可选
*/
boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent);
void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备状态
*
* @param device 视频设备
*/
boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent);
void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备信息
@ -251,14 +258,14 @@ public interface ISIPCommander {
* @param device 视频设备
* @return
*/
boolean deviceInfoQuery(Device device);
void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询目录列表
*
* @param device 视频设备
*/
boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent);
void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
/**
* 查询录像信息
@ -268,7 +275,7 @@ public interface ISIPCommander {
* @param endTime 结束时间,格式要求yyyy-MM-dd HH:mm:ss
* @param sn
*/
boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询报警信息
@ -282,8 +289,8 @@ public interface ISIPCommander {
* @param endTime 报警发生终止时间可选
* @return true = 命令发送成功
*/
boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent);
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备配置
@ -292,21 +299,21 @@ public interface ISIPCommander {
* @param channelId 通道编码可选
* @param configType 配置类型
*/
boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent);
void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询设备预置位置
*
* @param device 视频设备
*/
boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent);
void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 查询移动设备位置数据
*
* @param device 视频设备
*/
boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent);
void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 订阅取消订阅移动位置
@ -314,7 +321,7 @@ public interface ISIPCommander {
* @param device 视频设备
* @return true = 命令发送成功
*/
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 订阅取消订阅报警信息
@ -327,14 +334,14 @@ public interface ISIPCommander {
* @param endTime 报警发生终止时间可选
* @return true = 命令发送成功
*/
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException;
/**
* 订阅取消订阅目录信息
* @param device 视频设备
* @return true = 命令发送成功
*/
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
/**
* 拉框控制命令
@ -343,7 +350,7 @@ public interface ISIPCommander {
* @param channelId 通道id
* @param cmdString 前端控制指令串
*/
boolean dragZoomCmd(Device device, String channelId, String cmdString);
void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
/**
@ -352,5 +359,11 @@ public interface ISIPCommander {
* @param deviceAlarm 报警信息信息
* @return
*/
boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm);
void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
void transmitRequest(String transport, Request request) throws SipException, ParseException ;
void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException;
void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, ParseException;
}

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.service.bean.GPSMsgInfo;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.header.WWWAuthenticateHeader;
import java.text.ParseException;
import java.util.List;
public interface ISIPCommanderForPlatform {
@ -14,15 +17,15 @@ public interface ISIPCommanderForPlatform {
* @param parentPlatform
* @return
*/
boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister);
void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
void register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException;
/**
* 向上级平台注销
* @param parentPlatform
* @return
*/
boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
/**
@ -30,7 +33,7 @@ public interface ISIPCommanderForPlatform {
* @param parentPlatform
* @return callId(作为接受回复的判定)
*/
String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
/**
@ -42,8 +45,8 @@ public interface ISIPCommanderForPlatform {
* @param size
* @return
*/
boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size);
boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag);
void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException;
void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException;
/**
* 向上级回复DeviceInfo查询信息
@ -52,7 +55,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag
* @return
*/
boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag);
void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
/**
* 向上级回复DeviceStatus查询信息
@ -61,7 +64,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag
* @return
*/
boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag);
void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
/**
* 向上级回复移动位置订阅消息
@ -70,7 +73,7 @@ public interface ISIPCommanderForPlatform {
* @param subscribeInfo 订阅相关的信息
* @return
*/
boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo);
void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
/**
* 向上级回复报警消息
@ -78,21 +81,21 @@ public interface ISIPCommanderForPlatform {
* @param deviceAlarm 报警信息信息
* @return
*/
boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm);
void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException;
/**
* 回复catalog事件-增加/更新
* @param parentPlatform
* @param deviceChannels
*/
boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
/**
* 回复catalog事件-删除
* @param parentPlatform
* @param deviceChannels
*/
boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
/**
* 回复recordInfo
@ -101,7 +104,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag fromTag
* @param recordInfo 录像信息
*/
boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo);
void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException;
/**
* 录像播放推送完成时发送MediaStatus消息
@ -109,13 +112,13 @@ public interface ISIPCommanderForPlatform {
* @param sendRtpItem
* @return
*/
boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem);
void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
/**
* 向发起点播的上级回复bye
* @param platform 平台信息
* @param callId callId
*/
void streamByeCmd(ParentPlatform platform, String callId);
void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem);
void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException;
void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
}

View File

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

View File

@ -13,12 +13,9 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.SerializeUtils;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.MessageFactoryImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -30,13 +27,10 @@ import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.sip.*;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@Component
@ -77,19 +71,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
private SubscribeHolder subscribeHolder;
@Override
public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
register(parentPlatform, null, null, errorEvent, okEvent, false, true);
}
@Override
public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
return register(parentPlatform, null, null, errorEvent, okEvent, false, false);
public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
register(parentPlatform, null, null, errorEvent, okEvent, false, false);
}
@Override
public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) {
try {
public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException {
Request request;
if (!registerAgain ) {
CallIdHeader callIdHeader = null;
@ -126,23 +119,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}
transmitRequest(parentPlatform, request, null, okEvent);
return true;
} catch (ParseException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (PeerUnavailableException e) {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
}
return false;
}
@Override
public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
String callId = null;
try {
public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer keepaliveXml = new StringBuffer(200);
keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -163,11 +143,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
SipUtils.getNewViaTag(),
callIdHeader);
transmitRequest(parentPlatform, request, errorEvent, okEvent);
callId = callIdHeader.getCallId();
} catch (ParseException | InvalidArgumentException | SipException e) {
e.printStackTrace();
}
return callId;
return callIdHeader.getCallId();
}
private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
@ -206,12 +182,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return
*/
@Override
public boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) {
public void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException {
if ( parentPlatform ==null) {
return false;
return ;
}
try {
List<DeviceChannel> channels = new ArrayList<>();
if (channel != null) {
channels.add(channel);
@ -225,20 +200,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) {
public void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException {
if ( parentPlatform ==null) {
return false;
return ;
}
sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
return true;
}
private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
String characterSet = parentPlatform.getCharacterSet();
@ -300,11 +269,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return catalogXml.toString();
}
private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) {
private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) throws SipException, InvalidArgumentException, ParseException {
if (index >= channels.size()) {
return;
}
try {
List<DeviceChannel> deviceChannels;
if (index + parentPlatform.getCatalogGroup() < channels.size()) {
deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
@ -319,11 +287,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request, null, eventResult -> {
int indexNext = index + parentPlatform.getCatalogGroup();
try {
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
});
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
}
});
}
/**
@ -334,11 +303,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return
*/
@Override
public boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
public void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) {
return false;
return;
}
try {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceInfoXml = new StringBuffer(600);
deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -358,12 +326,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
@ -374,11 +336,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return
*/
@Override
public boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
public void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) {
return false;
return ;
}
try {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -397,23 +358,17 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) {
public void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
if (parentPlatform == null) {
return false;
return;
}
if (logger.isDebugEnabled()) {
logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
}
try {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -433,27 +388,15 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
}, null);
} catch (SipException | ParseException e) {
e.printStackTrace();
return false;
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) {
public void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) {
return false;
return;
}
logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
try {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -478,25 +421,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} catch (SipException | ParseException e) {
e.printStackTrace();
return false;
} catch (InvalidArgumentException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
return false;
return;
}
if (index == null) {
index = 0;
}
if (index >= deviceChannels.size()) {
return true;
return;
}
List<DeviceChannel> channels;
if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@ -504,32 +440,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else {
channels = deviceChannels.subList(index, deviceChannels.size());
}
try {
Integer finalIndex = index;
String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
deviceChannels.size(), type, subscribeInfo);
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
}, (eventResult -> {
try {
sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
finalIndex + parentPlatform.getCatalogGroup());
}));
} catch (SipException | ParseException e) {
e.printStackTrace();
return false;
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
}
return true;
}));
}
private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException {
throws SipException, ParseException, InvalidArgumentException {
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
String characterSet = parentPlatform.getCharacterSet();
// 设置编码 防止中文乱码
@ -537,50 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
.createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
notifyRequest.addHeader(subscriptionState);
EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
if (subscribeInfo.getEventId() != null) {
event.setEventId(subscribeInfo.getEventId());
}
notifyRequest.addHeader(event);
SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
sipURI.setHost(parentPlatform.getServerIP());
sipURI.setPort(parentPlatform.getServerPort());
// ClientTransaction transaction = subscribeInfo.getClientTransaction();
// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {
// if ("TCP".equals(parentPlatform.getTransport())) {
// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
// } else if ("UDP".equals(parentPlatform.getTransport())) {
// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
// }
// }
ClientTransaction transaction = null;
if ("TCP".equals(parentPlatform.getTransport())) {
transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
} else if ("UDP".equals(parentPlatform.getTransport())) {
transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
}
// 添加错误订阅
if (errorEvent != null) {
sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);
}
// 添加订阅
if (okEvent != null) {
sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);
}
transaction.sendRequest();
return transaction;
transmitRequest(parentPlatform, notifyRequest);
}
private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
@ -639,20 +525,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}
@Override
public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
SubscribeInfo subscribeInfo, Integer index) {
public void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
if (parentPlatform == null
|| deviceChannels == null
|| deviceChannels.size() == 0
|| subscribeInfo == null) {
return false;
logger.warn("[缺少必要参数]");
return;
}
if (index == null) {
index = 0;
}
if (index >= deviceChannels.size()) {
return true;
return;
}
List<DeviceChannel> channels;
if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
@ -660,28 +547,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}else {
channels = deviceChannels.subList(index, deviceChannels.size());
}
try {
Integer finalIndex = index;
String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
logger.error("发送NOTIFY通知消息失败。错误{} {}", eventResult.statusCode, eventResult.msg);
}, (eventResult -> {
}, eventResult -> {
try {
sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
finalIndex + parentPlatform.getCatalogGroup());
}));
} catch (SipException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
IllegalAccessException e) {
logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
}
return true;
});
}
private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
@ -711,11 +589,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
return catalogXml.toString();
}
@Override
public boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) {
public void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException {
if ( parentPlatform ==null) {
return false;
return ;
}
try {
String characterSet = parentPlatform.getCharacterSet();
StringBuffer recordXml = new StringBuffer(600);
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
@ -759,23 +636,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) {
if (sendRtpItem == null) {
return false;
}
if (platform == null) {
return false;
public void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
if (sendRtpItem == null || platform == null) {
return;
}
try{
String characterSet = platform.getCharacterSet();
StringBuffer mediaStatusXml = new StringBuffer(200);
@ -790,34 +658,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
sendRtpItem);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);
SipURI sipURI = (SipURI) messageRequest.getRequestURI();
sipURI.setHost(platform.getServerIP());
sipURI.setPort(platform.getServerPort());
ClientTransaction clientTransaction;
if ("TCP".equals(platform.getTransport())) {
clientTransaction = tcpSipProvider.getNewClientTransaction(messageRequest);
}else {
clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
}
clientTransaction.sendRequest();
} catch (SipException e) {
e.printStackTrace();
return false;
} catch (ParseException e) {
e.printStackTrace();
return false;
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
}
return true;
transmitRequest(platform, messageRequest);
}
@Override
public void streamByeCmd(ParentPlatform platform, String callId) {
public void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException {
if (platform == null) {
return;
}
@ -828,7 +674,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
}
@Override
public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) {
public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
if (sendRtpItem == null ) {
logger.info("[向上级发送BYE] sendRtpItem 为NULL");
return;
@ -844,25 +690,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
}
try {
SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
if (byeRequest == null) {
logger.warn("[向上级发送bye]:无法创建 byeRequest");
}
ClientTransaction clientTransaction;
if ("TCP".equals(platform.getTransport())) {
clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
} else {
clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
}
clientTransaction.sendRequest();
} catch (SipException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
}
transmitRequest(platform,byeRequest);
}
}

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

View File

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

View File

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

View File

@ -341,7 +341,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
logger.info("Ack 等待超时");
mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc);
// 回复bye
try {
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
}, 60 * 1000);
responseSdpAck(serverTransaction, content.toString(), platform);
@ -657,12 +661,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
try {
responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
} catch (SipException e) {
throw new RuntimeException(e);
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
}
}
});
@ -729,12 +729,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
}
}
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
} catch (SipException e) {
throw new RuntimeException(e);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
}

View File

@ -93,7 +93,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
logger.warn("[设备未找到 ] {}", deviceId);
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
};
}else {
@ -113,23 +115,15 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
// 失败的回复
try {
responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
}
}, eventResult -> {
// 成功的回复
try {
responseAck(serverTransaction, eventResult.statusCode);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
}
});
}

View File

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

View File

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

View File

@ -217,12 +217,8 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
// 回复200 OK
try {
responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) {
throw new RuntimeException(e);
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 报警通知回复: {}", e.getMessage());
}
Element deviceIdElement = rootElement.element("DeviceID");
String channelId = deviceIdElement.getText().toString();

View File

@ -78,12 +78,8 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
deviceService.online(device);
}
}
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 心跳回复: {}", e.getMessage());
}
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
@ -67,12 +68,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
// 回复200 OK
try {
responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 录像流推送完毕回复200OK: {}", e.getMessage());
}
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
String NotifyType =getText(rootElement, "NotifyType");
@ -89,7 +86,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
// 先从会话内查找
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
cmder.streamByeCmd(device.getDeviceId(), ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
try {
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
} catch (InvalidArgumentException | ParseException | SsrcTransactionNotFoundException | SipException e) {
logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage());
}
// 如果级联播放需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题需要将点播CallId进行上下级绑定
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null);
@ -99,7 +101,11 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
logger.warn("[级联消息发送]发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId());
return;
}
try {
sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
}
}
}
}

View File

@ -59,12 +59,8 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen
logger.info("不支持alarm查询");
try {
responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query");
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 alarm查询回复200OK: {}", e.getMessage());
}
}

View File

@ -100,12 +100,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
// 回复无通道
cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), 0);
}
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 目录查询: {}", e.getMessage());
}
}

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
} catch (ParseException | SipException | InvalidArgumentException e) {
e.printStackTrace();
logger.error("[命令发送失败] 国标级联 语音喊话: {}", e.getMessage());
}
}

View File

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

View File

@ -63,12 +63,8 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
msg.setKey(key);
msg.setData(json);
deferredResultHolder.invokeAllResult(msg);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 设备配置查询: {}", e.getMessage());
}
}

View File

@ -58,12 +58,8 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare
msg.setKey(key);
msg.setData(json);
deferredResultHolder.invokeAllResult(msg);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 设备控制: {}", e.getMessage());
}
}

View File

@ -60,12 +60,8 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
// 回复200 OK
try {
responseAck(getServerTransaction(evt), Response.OK);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 设备状态应答回复200OK: {}", e.getMessage());
}
Element deviceIdElement = element.element("DeviceID");
Element onlineElement = element.element("Online");

View File

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

View File

@ -147,7 +147,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
}
}
} catch (DocumentException e) {
throw new RuntimeException(e);
logger.error("xml解析异常 ", e);
} finally {
taskQueueHandlerRun = false;
}
@ -155,13 +155,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
});
}
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}finally {
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage());
} finally {
taskQueueHandlerRun = false;
}
}

View File

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

View File

@ -15,10 +15,13 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.header.CallIdHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Response;
import java.text.ParseException;
/**
* @description:Register响应处理器
@ -87,7 +90,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
if (response.getStatusCode() == Response.UNAUTHORIZED) {
WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
try {
sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage());
}
}else if (response.getStatusCode() == Response.OK){
if (platformRegisterInfo.isRegister()) {

View File

@ -1,8 +1,11 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
import com.genersoft.iot.vmp.conf.SystemInfoTimerTask;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -13,6 +16,8 @@ import javax.sip.header.CallIdHeader;
@Component
public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor {
private Logger logger = LoggerFactory.getLogger(TimeoutProcessorImpl.class);
@Autowired
private SIPProcessorObserver processorObserver;
@ -36,7 +41,7 @@ public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor
sipSubscribe.removeErrorSubscribe(callId);
sipSubscribe.removeOkSubscribe(callId);
} catch (Exception e) {
e.printStackTrace();
logger.error("[超时事件失败]: {}", e.getMessage());
}
}
}

View File

@ -70,4 +70,47 @@ public class SipUtils {
return String.valueOf(System.currentTimeMillis());
}
/**
* 云台指令码计算
*
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
* @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
* @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
*/
public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) {
int cmdCode = 0;
if (leftRight == 2) {
cmdCode|=0x01; // 右移
} else if(leftRight == 1) {
cmdCode|=0x02; // 左移
}
if (upDown == 2) {
cmdCode|=0x04; // 下移
} else if(upDown == 1) {
cmdCode|=0x08; // 上移
}
if (inOut == 2) {
cmdCode |= 0x10; // 放大
} else if(inOut == 1) {
cmdCode |= 0x20; // 缩小
}
StringBuilder builder = new StringBuilder("A50F01");
String strTmp;
strTmp = String.format("%02X", cmdCode);
builder.append(strTmp, 0, 2);
strTmp = String.format("%02X", moveSpeed);
builder.append(strTmp, 0, 2);
builder.append(strTmp, 0, 2);
strTmp = String.format("%X", zoomSpeed);
builder.append(strTmp, 0, 1).append("0");
//计算校验码
int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100;
strTmp = String.format("%02X", checkCode);
builder.append(strTmp, 0, 2);
return builder.toString();
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,11 +2,17 @@ package com.genersoft.iot.vmp.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.*;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -22,13 +28,6 @@ import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@ -92,6 +91,10 @@ public class PlayServiceImpl implements IPlayService {
@Autowired
private VideoStreamSessionManager streamSession;
@Autowired
private IDeviceService deviceService;
@Autowired
private UserSetting userSetting;
@ -261,14 +264,14 @@ public class PlayServiceImpl implements IPlayService {
System.out.println("设置超时任务: " + timeOutTaskKey);
dynamicTask.startDelay( timeOutTaskKey,()->{
SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
if (dialog != null) {
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
timeoutCallback.run(1, "收流超时");
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null);
}else {
logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
try {
cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[点播超时] 发送BYE失败 {}", e.getMessage());
} catch (SsrcTransactionNotFoundException e) {
timeoutCallback.run(0, "点播超时");
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
@ -282,6 +285,7 @@ public class PlayServiceImpl implements IPlayService {
logger.info("[点播端口分配异常]deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
return;
}
try {
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
logger.info("收到订阅消息: " + response.toJSONString());
System.out.println("停止超时任务: " + timeOutTaskKey);
@ -349,6 +353,19 @@ public class PlayServiceImpl implements IPlayService {
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
errorEvent.response(event);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 点播消息: {}", e.getMessage());
dynamicTask.stop(timeOutTaskKey);
mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
eventResult.msg = "命令发送失败";
errorEvent.response(eventResult);
}
}
@Override
@ -439,17 +456,18 @@ public class PlayServiceImpl implements IPlayService {
playBackResult.setCode(ErrorCode.ERROR100.getCode());
playBackResult.setMsg("回放超时");
playBackResult.setData(requestMessage);
SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
try {
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage());
} catch (SsrcTransactionNotFoundException e) {
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
if (dialog != null) {
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
}else {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
}
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
// 回复之前所有的点播请求
playBackCallback.call(playBackResult);
result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
@ -489,6 +507,7 @@ public class PlayServiceImpl implements IPlayService {
playBackCallback.call(playBackResult);
};
try {
cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
hookEvent, eventResult -> {
if (eventResult.type == SipSubscribe.EventResultType.response) {
@ -542,6 +561,13 @@ public class PlayServiceImpl implements IPlayService {
}
}, errorEvent);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 回放: {}", e.getMessage());
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
eventResult.msg = "命令发送失败";
errorEvent.response(eventResult);
}
return result;
}
@ -587,20 +613,33 @@ public class PlayServiceImpl implements IPlayService {
downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg("录像下载请求超时");
hookCallBack.call(downloadResult);
SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
if (dialog != null) {
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
}else {
try {
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[录像流]录像下载请求超时, 发送BYE失败 {}", e.getMessage());
} catch (SsrcTransactionNotFoundException e) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
}
cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
// 回复之前所有的点播请求
hookCallBack.call(downloadResult);
}, userSetting.getPlayTimeout());
SipSubscribe.Event errorEvent = event -> {
dynamicTask.stop(downLoadTimeOutTaskKey);
downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
downloadResult.setEvent(event);
hookCallBack.call(downloadResult);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
};
try {
cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
inviteStreamInfo -> {
logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
@ -617,16 +656,14 @@ public class PlayServiceImpl implements IPlayService {
downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
downloadResult.setResponse(inviteStreamInfo.getResponse());
hookCallBack.call(downloadResult);
}, event -> {
dynamicTask.stop(downLoadTimeOutTaskKey);
downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
downloadResult.setEvent(event);
hookCallBack.call(downloadResult);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
});
}, errorEvent);
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
eventResult.msg = "命令发送失败";
errorEvent.response(eventResult);
}
return result;
}
@ -705,7 +742,11 @@ public class PlayServiceImpl implements IPlayService {
for (SendRtpItem sendRtpItem : sendRtpItems) {
if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
try {
sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
}
}
}
}
@ -714,8 +755,17 @@ public class PlayServiceImpl implements IPlayService {
if (allSsrc.size() > 0) {
for (SsrcTransaction ssrcTransaction : allSsrc) {
if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) {
cmder.streamByeCmd(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(),
Device device = deviceService.queryDevice(ssrcTransaction.getDeviceId());
if (device == null) {
continue;
}
try {
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(),
ssrcTransaction.getStream(), null);
} catch (InvalidArgumentException | ParseException | SipException |
SsrcTransactionNotFoundException e) {
logger.error("[zlm离线]为正在使用此zlm的设备 发送BYE失败 {}", e.getMessage());
}
}
}
}

View File

@ -93,7 +93,6 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPus
try {
gBMap.put(streamPushExcelDto.getApp() + streamPushExcelDto.getStream(), streamPushExcelDto.getGbId());
}catch (IllegalArgumentException e) {
e.printStackTrace();
errorGBList.add(streamPushExcelDto.getGbId() + "(不同的app+stream使用了相同的国标ID)");
return;
}

View File

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

View File

@ -156,7 +156,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
try {
playMsgCallback.handler(responseSendItemMsg);
} catch (ParseException e) {
throw new RuntimeException(e);
logger.error("[REDIS消息处理异常] ", e);
}
}
break;

View File

@ -17,49 +17,6 @@ public class GpsUtil {
public static BaiduPoint Wgs84ToBd09(String xx, String yy) {
// try {
// Socket s = new Socket("api.map.baidu.com", 80);
// BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
// OutputStream out = s.getOutputStream();
// StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4");
// sb.append("&x=" + xx + "&y=" + yy);
// sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");
// sb.append("User-Agent: Java/1.6.0_20\r\n");
// sb.append("Host: api.map.baidu.com:80\r\n");
// sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");
// sb.append("Connection: Close\r\n");
// sb.append("\r\n");
// out.write(sb.toString().getBytes());
// String json = "";
// String tmp = "";
// while ((tmp = br.readLine()) != null) {
// // logger.info(tmp);
// json += tmp;
// }
//
// s.close();
// int start = json.indexOf("cbk_3976");
// int end = json.lastIndexOf("}");
// if (start != -1 && end != -1 && json.contains("\"x\":\"")) {
// json = json.substring(start, end);
// String[] point = json.split(",");
// String x = point[1].split(":")[1].replace("\"", "");
// String y = point[2].split(":")[1].replace("\"", "");
// BaiduPoint bdPoint= new BaiduPoint();
// bdPoint.setBdLng(new String(decode(x)));
// bdPoint.setBdLat(new String(decode(y)));
// return bdPoint;
// //return (new String(decode(x)) + "," + new String(decode(y)));
// } else {
// logger.info("gps坐标无效");
// }
// out.close();
// br.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
double lng = Double.parseDouble(xx);
double lat = Double.parseDouble(yy);
Double[] gcj02 = Coordtransform.WGS84ToGCJ02(lng, lat);

View File

@ -1,48 +0,0 @@
package com.genersoft.iot.vmp.utils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IpUtil {
public static String getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress="";
}
// ipAddress = this.getRequest().getRemoteAddr();
return ipAddress;
}
}

View File

@ -1,73 +0,0 @@
package com.genersoft.iot.vmp.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 一个优秀的颓废程序猿
*/
@Component
public class JarFileUtils {
private static Logger log = LoggerFactory.getLogger(JarFileUtils.class);
private static Map<String, String> map = new HashMap<>();
public Map<String, String> readJarFile() {
JarFile jarFile = null;
BufferedReader br = null;
try {
// 获取jar的运行路径因linux下jar的路径为file:/app/.../test.jar!/BOOT-INF/class!/这种格式所以需要去掉file:!/BOOT-INF/class!/
String jarFilePath = ClassUtils.getDefaultClassLoader().getResource("").getPath().replace("!/BOOT-INF/classes!/", "");
if (jarFilePath.startsWith("file")) {
jarFilePath = jarFilePath.substring(5);
}
log.debug("jarFilePath:" + jarFilePath);
// 通过JarFile的getJarEntry方法读取META-INF/MANIFEST.MF
jarFile = new JarFile(jarFilePath);
JarEntry entry = jarFile.getJarEntry("META-INF/MANIFEST.MF");
log.info("读取的内容:" + entry.toString());
// 如果读取到MANIFEST.MF文件内容则转换为string
if (entry != null) {
InputStream in = jarFile.getInputStream(entry);
StringBuilder sb = new StringBuilder();
br = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = br.readLine()) != null) {
if (line != null && line.contains(":")) {
int index = line.indexOf(":");
map.put(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim());
}
}
return map;
}
} catch (IOException e) {
log.debug("读取MANIFEST.MF文件异常:" + e.getMessage());
} finally {
try {
if (null != br) {
br.close();
}
if (null != jarFile) {
jarFile.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return map;
}
}

View File

@ -1,31 +0,0 @@
package com.genersoft.iot.vmp.utils;
import java.io.*;
public class SerializeUtils {
public static byte[] serialize(Object obj){
byte[] bytes = null;
try {
ByteArrayOutputStream baos=new ByteArrayOutputStream();;
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(obj);
bytes=baos.toByteArray();
baos.close();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
public static Object deSerialize(byte[] bytes){
Object obj=null;
try {
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
ObjectInputStream ois=new ObjectInputStream(bais);
obj=ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;
@ -31,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
/**
* 位置信息管理
*/
@ -105,6 +109,7 @@ public class MobilePositionController {
Device device = storager.queryVideoDevice(deviceId);
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
try {
cmder.mobilePostitionQuery(device, event -> {
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
@ -112,6 +117,10 @@ public class MobilePositionController {
msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 获取移动位置信息: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L);
result.onTimeout(()->{
logger.warn(String.format("获取移动位置信息超时"));

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

View File

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

View File

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

View File

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

View File

@ -96,7 +96,7 @@ public class MediaController {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
logger.error("[线程休眠失败] {}", e.getMessage());
}
if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
String host = request.getHeader("Host");

View File

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

View File

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
import com.alibaba.fastjson.JSONArray;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -36,6 +37,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;
@ -102,12 +106,23 @@ public class PlayController {
throw new ControllerException(ErrorCode.ERROR400);
}
Device device = storager.queryVideoDevice(deviceId);
if (device == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在");
}
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
if (streamInfo == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到");
}
cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, null);
try {
logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
cmder.streamByeCmd(device, channelId, streamInfo.getStream(), null, null);
} catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
@ -221,6 +236,7 @@ public class PlayController {
resultHolder.invokeResult(msg);
return result;
}
try {
cmder.audioBroadcastCmd(device, (event) -> {
RequestMessage msg = new RequestMessage();
msg.setKey(key);
@ -233,6 +249,10 @@ public class PlayController {
msg.setData(json);
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 语音广播: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
result.onTimeout(() -> {
logger.warn("语音广播操作超时, 设备未返回应答指令");

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.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@ -21,12 +22,15 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
/**
* @author lin
*/
@ -92,7 +96,15 @@ public class PlaybackController {
if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
throw new ControllerException(ErrorCode.ERROR400);
}
cmder.streamByeCmd(deviceId, channelId, stream, null);
Device device = storager.queryVideoDevice(deviceId);
if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + " 未找到");
}
try {
cmder.streamByeCmd(device, channelId, stream, null);
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "发送bye失败 " + e.getMessage());
}
}
@ -107,7 +119,11 @@ public class PlaybackController {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
}
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
try {
cmder.playPauseCmd(device, streamInfo);
} catch (InvalidArgumentException | ParseException | SipException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
}
@ -122,7 +138,11 @@ public class PlaybackController {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
}
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
try {
cmder.playResumeCmd(device, streamInfo);
} catch (InvalidArgumentException | ParseException | SipException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
}
@ -138,7 +158,11 @@ public class PlaybackController {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
}
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
try {
cmder.playSeekCmd(device, streamInfo, seekTime);
} catch (InvalidArgumentException | ParseException | SipException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
}
@Operation(summary = "回放倍速播放")
@ -157,6 +181,10 @@ public class PlaybackController {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed0.25 0.5 1、2、4");
}
Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
try {
cmder.playSpeedCmd(device, streamInfo, speed);
} catch (InvalidArgumentException | ParseException | SipException e) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
}
}

View File

@ -1,6 +1,8 @@
package com.genersoft.iot.vmp.vmanager.gb28181.ptz;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -18,6 +20,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.UUID;
@Tag(name = "云台控制")
@ -98,7 +103,12 @@ public class PtzController {
default:
break;
}
try {
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@ -117,7 +127,12 @@ public class PtzController {
}
Device device = storager.queryVideoDevice(deviceId);
try {
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 前端控制: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
}
@ -146,6 +161,7 @@ public class PtzController {
return result;
}
resultHolder.put(key, uuid, result);
try {
cmder.presetQuery(device, channelId, event -> {
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
@ -153,6 +169,10 @@ public class PtzController {
msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
resultHolder.invokeResult(msg);
});
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 获取设备预置位: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
return result;
}
}

View File

@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.utils.DateUtil;
@ -31,6 +33,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.UUID;
@ -54,6 +59,12 @@ public class GBRecordController {
@Autowired
private IPlayService playService;
@Autowired
private IDeviceService deviceService;
@Operation(summary = "录像查询")
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true)
@ -81,6 +92,7 @@ public class GBRecordController {
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
try {
cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
WVPResult<RecordInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(ErrorCode.ERROR100.getCode());
@ -88,6 +100,10 @@ public class GBRecordController {
msg.setData(wvpResult);
resultHolder.invokeResult(msg);
}));
} catch (InvalidArgumentException | SipException | ParseException e) {
logger.error("[命令发送失败] 查询录像: {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
}
// 录像查询以channelId作为deviceId查询
resultHolder.put(key, uuid, result);
@ -131,14 +147,24 @@ public class GBRecordController {
@GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
cmder.streamByeCmd(deviceId, channelId, stream, null);
if (logger.isDebugEnabled()) {
logger.debug(String.format("设备历史媒体下载停止 API调用deviceId/channelId%s_%s", deviceId, channelId));
}
if (deviceId == null || channelId == null) {
throw new ControllerException(ErrorCode.ERROR100);
throw new ControllerException(ErrorCode.ERROR400);
}
Device device = deviceService.queryDevice(deviceId);
if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "未找到");
}
try {
cmder.streamByeCmd(device, channelId, stream, null);
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
logger.error("[停止历史媒体下载]停止历史媒体下载发送BYE失败 {}", e.getMessage());
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
}
}

View File

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

View File

@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.web.gb28181;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@ -17,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
/**
* API兼容实时直播
*/
@ -40,6 +46,9 @@ public class ApiStreamController {
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IDeviceService deviceService;
@Autowired
private IPlayService playService;
@ -177,7 +186,19 @@ public class ApiStreamController {
result.put("error","未找到流信息");
return result;
}
cmder.streamByeCmd(serial, code, streamInfo.getStream(), null);
Device device = deviceService.queryDevice(serial);
if (device == null) {
JSONObject result = new JSONObject();
result.put("error","未找到设备");
return result;
}
try {
cmder.streamByeCmd(device, code, streamInfo.getStream(), null);
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
JSONObject result = new JSONObject();
result.put("error","发送BYE失败" + e.getMessage());
return result;
}
redisCatchStorage.stopPlay(streamInfo);
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
return null;