尝试修复catalog获取失败。服务重启后设备未注册仍上报keeplive处理
This commit is contained in:
@@ -79,7 +79,7 @@ public interface ISIPCommander {
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public String playbackStreamCmd(Device device,String channelId, String recordId, String startTime, String endTime);
|
||||
public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime);
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.sip.ClientTransaction;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.message.Request;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
@@ -19,8 +18,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SsrcUtil;
|
||||
|
||||
import tk.mybatis.mapper.util.StringUtil;
|
||||
|
||||
/**
|
||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||
* @author: songww
|
||||
@@ -181,16 +178,16 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
@Override
|
||||
public String playbackStreamCmd(Device device, String channelId, String recordId, String startTime, String endTime) {
|
||||
public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) {
|
||||
try {
|
||||
|
||||
String ssrc = SsrcUtil.getPlayBackSsrc();
|
||||
//
|
||||
StringBuffer content = new StringBuffer(200);
|
||||
content.append("v=0\r\n");
|
||||
content.append("o="+channelId+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n");
|
||||
content.append("o="+device.getDeviceId()+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n");
|
||||
content.append("s=Playback\r\n");
|
||||
content.append("u="+recordId+":3\r\n");
|
||||
content.append("u="+channelId+":3\r\n");
|
||||
content.append("c=IN IP4 "+sipConfig.getMediaIp()+"\r\n");
|
||||
content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
|
||||
if(device.getTransport().equals("TCP")) {
|
||||
@@ -439,11 +436,15 @@ public class SIPCommander implements ISIPCommander {
|
||||
}
|
||||
|
||||
private void transmitRequest(Device device, Request request) throws SipException {
|
||||
ClientTransaction clientTransaction = null;
|
||||
if(device.getTransport().equals("TCP")) {
|
||||
sipLayer.getTcpSipProvider().sendRequest(request);
|
||||
clientTransaction = sipLayer.getTcpSipProvider().getNewClientTransaction(request);
|
||||
//sipLayer.getTcpSipProvider().sendRequest(request);
|
||||
} else if(device.getTransport().equals("UDP")) {
|
||||
sipLayer.getUdpSipProvider().sendRequest(request);
|
||||
clientTransaction = sipLayer.getUdpSipProvider().getNewClientTransaction(request);
|
||||
//sipLayer.getUdpSipProvider().sendRequest(request);
|
||||
}
|
||||
clientTransaction.sendRequest();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
@@ -69,8 +70,21 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
|
||||
@Autowired
|
||||
private DeferredResultHolder deferredResultHolder;
|
||||
|
||||
@Autowired
|
||||
private DeviceOffLineDetector offLineDetector;
|
||||
|
||||
private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
|
||||
|
||||
private static final String MESSAGE_CATALOG = "Catalog";
|
||||
private static final String MESSAGE_DEVICE_INFO = "DeviceInfo";
|
||||
private static final String MESSAGE_KEEP_ALIVE = "Keepalive";
|
||||
private static final String MESSAGE_ALARM = "Alarm";
|
||||
private static final String MESSAGE_RECORD_INFO = "RecordInfo";
|
||||
// private static final String MESSAGE_BROADCAST = "Broadcast";
|
||||
// private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
|
||||
// private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
|
||||
// private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";
|
||||
|
||||
/**
|
||||
* 处理MESSAGE请求
|
||||
*
|
||||
@@ -85,22 +99,31 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
|
||||
this.transaction = transaction;
|
||||
|
||||
Request request = evt.getRequest();
|
||||
|
||||
if (new String(request.getRawContent()).contains("<CmdType>Keepalive</CmdType>")) {
|
||||
logger.info("接收到KeepAlive消息");
|
||||
processMessageKeepAlive(evt);
|
||||
} else if (new String(request.getRawContent()).contains("<CmdType>Catalog</CmdType>")) {
|
||||
logger.info("接收到Catalog消息");
|
||||
processMessageCatalogList(evt);
|
||||
} else if (new String(request.getRawContent()).contains("<CmdType>DeviceInfo</CmdType>")) {
|
||||
logger.info("接收到DeviceInfo消息");
|
||||
processMessageDeviceInfo(evt);
|
||||
} else if (new String(request.getRawContent()).contains("<CmdType>Alarm</CmdType>")) {
|
||||
logger.info("接收到Alarm消息");
|
||||
processMessageAlarm(evt);
|
||||
} else if (new String(request.getRawContent()).contains("<CmdType>RecordInfo</CmdType>")) {
|
||||
logger.info("接收到RecordInfo消息");
|
||||
processMessageRecordInfo(evt);
|
||||
SAXReader reader = new SAXReader();
|
||||
Document xml;
|
||||
try {
|
||||
xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
|
||||
Element rootElement = xml.getRootElement();
|
||||
String cmd = rootElement.element("CmdType").getStringValue();
|
||||
|
||||
if (MESSAGE_KEEP_ALIVE.equals(cmd)) {
|
||||
logger.info("接收到KeepAlive消息");
|
||||
processMessageKeepAlive(evt);
|
||||
} else if (MESSAGE_CATALOG.equals(cmd)) {
|
||||
logger.info("接收到Catalog消息");
|
||||
processMessageCatalogList(evt);
|
||||
} else if (MESSAGE_DEVICE_INFO.equals(cmd)) {
|
||||
logger.info("接收到DeviceInfo消息");
|
||||
processMessageDeviceInfo(evt);
|
||||
} else if (MESSAGE_ALARM.equals(cmd)) {
|
||||
logger.info("接收到Alarm消息");
|
||||
processMessageAlarm(evt);
|
||||
} else if (MESSAGE_RECORD_INFO.equals(cmd)) {
|
||||
logger.info("接收到RecordInfo消息");
|
||||
processMessageRecordInfo(evt);
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -247,12 +270,17 @@ public class MessageRequestProcessor implements ISIPRequestProcessor {
|
||||
*/
|
||||
private void processMessageKeepAlive(RequestEvent evt){
|
||||
try {
|
||||
Request request = evt.getRequest();
|
||||
Response response = layer.getMessageFactory().createResponse(Response.OK,request);
|
||||
Element rootElement = getRootElement(evt);
|
||||
Element deviceIdElement = rootElement.element("DeviceID");
|
||||
String deviceId = XmlUtil.getText(rootElement,"DeviceID");
|
||||
Request request = evt.getRequest();
|
||||
Response response = null;
|
||||
if (offLineDetector.isOnline(deviceId)) {
|
||||
response = layer.getMessageFactory().createResponse(Response.OK,request);
|
||||
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||
} else {
|
||||
response = layer.getMessageFactory().createResponse(Response.BAD_REQUEST,request);
|
||||
}
|
||||
transaction.sendResponse(response);
|
||||
publisher.onlineEventPublish(deviceIdElement.getText(), VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import javax.sip.ClientTransaction;
|
||||
import javax.sip.Dialog;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.ResponseEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.CSeqHeader;
|
||||
import javax.sip.header.ViaHeader;
|
||||
import javax.sip.message.Request;
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
||||
|
||||
/**
|
||||
@@ -20,20 +30,51 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
||||
@Component
|
||||
public class InviteResponseProcessor implements ISIPResponseProcessor {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
|
||||
|
||||
/**
|
||||
* 处理invite响应
|
||||
*
|
||||
* @param request
|
||||
* @param evt
|
||||
* 响应消息
|
||||
*/
|
||||
@Override
|
||||
public void process(ResponseEvent evt, SipLayer layer, SipConfig config) {
|
||||
try {
|
||||
Dialog dialog = evt.getDialog();
|
||||
Request reqAck =dialog.createAck(1L);
|
||||
dialog.sendAck(reqAck);
|
||||
Response response = evt.getResponse();
|
||||
int statusCode = response.getStatusCode();
|
||||
//trying不会回复
|
||||
if(statusCode == Response.TRYING){
|
||||
|
||||
}
|
||||
//成功响应
|
||||
//下发ack
|
||||
if(statusCode == Response.OK){
|
||||
ClientTransaction clientTransaction = evt.getClientTransaction();
|
||||
if(clientTransaction == null){
|
||||
logger.error("回复ACK时,clientTransaction为null >>> {}",response);
|
||||
return;
|
||||
}
|
||||
Dialog clientDialog = clientTransaction.getDialog();
|
||||
|
||||
CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||
long cseqId = clientCSeqHeader.getSeqNumber();
|
||||
/*
|
||||
createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
|
||||
有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
|
||||
所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。
|
||||
*/
|
||||
Request ackRequest = clientDialog.createAck(cseqId);
|
||||
SipURI requestURI = (SipURI) ackRequest.getRequestURI();
|
||||
ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
|
||||
requestURI.setHost(viaHeader.getHost());
|
||||
requestURI.setPort(viaHeader.getPort());
|
||||
clientDialog.sendAck(ackRequest);
|
||||
}
|
||||
} catch (InvalidArgumentException | SipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user