From eb4716ba82f13078dd88e967e7906080c0ac0205 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期五, 05 十一月 2021 18:33:53 +0800 Subject: [PATCH] 添加目录订阅消息与接口 --- src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java | 61 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java | 14 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/ISIPResponseProcessor.java | 15 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java | 40 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java | 75 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java | 123 ++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java | 197 +++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor.java | 1103 +++++++++++++++++++++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java | 386 +++++++ src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java | 24 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java | 97 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java | 179 +++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java | 49 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java | 115 ++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java | 47 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java | 104 ++ src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java | 48 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java | 384 +++++++ src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java | 42 19 files changed, 3,103 insertions(+), 0 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java new file mode 100644 index 0000000..145c29b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java @@ -0,0 +1,42 @@ +package com.genersoft.iot.vmp.conf; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; + +/** + * 鍔ㄦ�佸畾鏃朵换鍔� + */ +@Component +public class DynamicTask { + + @Autowired + private ThreadPoolTaskScheduler threadPoolTaskScheduler; + + private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>(); + + @Bean + public ThreadPoolTaskScheduler threadPoolTaskScheduler() { + return new ThreadPoolTaskScheduler(); + } + + public String startCron(String key, Runnable task, String corn) { + stopCron(key); + ScheduledFuture future = threadPoolTaskScheduler.schedule(task, new CronTrigger(corn)); + futureMap.put(key, future); + return "startCron"; + } + + public void stopCron(String key) { + if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { + futureMap.get(key).cancel(true); + } + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java new file mode 100644 index 0000000..8e79941 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java @@ -0,0 +1,14 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request; + +import javax.sip.RequestEvent; + +/** + * @description: 瀵筍IP浜嬩欢杩涜澶勭悊锛屽寘鎷瑀equest锛� response锛� timeout锛� ioException, transactionTerminated,dialogTerminated + * @author: panlinlin + * @date: 2021骞�11鏈�5鏃� 15锛�47 + */ +public interface ISIPRequestProcessor { + + void process(RequestEvent event); + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java new file mode 100644 index 0000000..6cb9e7e --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorAbstract.java @@ -0,0 +1,179 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request; + +import gov.nist.javax.sip.SipProviderImpl; +import gov.nist.javax.sip.SipStackImpl; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.stack.SIPServerTransaction; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +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 javax.sip.*; +import javax.sip.address.Address; +import javax.sip.address.AddressFactory; +import javax.sip.address.SipURI; +import javax.sip.header.ContentTypeHeader; +import javax.sip.header.HeaderFactory; +import javax.sip.header.ViaHeader; +import javax.sip.message.MessageFactory; +import javax.sip.message.Request; +import javax.sip.message.Response; +import java.io.ByteArrayInputStream; +import java.text.ParseException; + +/** + * @description:澶勭悊鎺ユ敹IPCamera鍙戞潵鐨凷IP鍗忚璇锋眰娑堟伅 + * @author: songww + * @date: 2020骞�5鏈�3鏃� 涓嬪崍4:42:22 + */ +public abstract class SIPRequestProcessorAbstract implements InitializingBean, ISIPRequestProcessor { + + private final static Logger logger = LoggerFactory.getLogger(SIPRequestProcessorAbstract.class); + + @Autowired + @Qualifier(value="tcpSipProvider") + private SipProviderImpl tcpSipProvider; + + @Autowired + @Qualifier(value="udpSipProvider") + private SipProviderImpl udpSipProvider; + + /** + * 鏍规嵁 RequestEvent 鑾峰彇 ServerTransaction + * @param evt + * @return + */ + public ServerTransaction getServerTransaction(RequestEvent evt) { + Request request = evt.getRequest(); + ServerTransaction serverTransaction = evt.getServerTransaction(); + // 鍒ゆ柇TCP杩樻槸UDP + boolean isTcp = false; + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); + String transport = reqViaHeader.getTransport(); + if (transport.equals("TCP")) { + isTcp = true; + } + + if (serverTransaction == null) { + try { + if (isTcp) { + SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack(); + serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); + if (serverTransaction == null) { + serverTransaction = tcpSipProvider.getNewServerTransaction(request); + } + } else { + SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack(); + serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true); + if (serverTransaction == null) { + serverTransaction = udpSipProvider.getNewServerTransaction(request); + } + } + } catch (TransactionAlreadyExistsException e) { + logger.error(e.getMessage()); + } catch (TransactionUnavailableException e) { + logger.error(e.getMessage()); + } + } + return serverTransaction; + } + + public AddressFactory getAddressFactory() { + try { + return SipFactory.getInstance().createAddressFactory(); + } catch (PeerUnavailableException e) { + e.printStackTrace(); + } + return null; + } + + public HeaderFactory getHeaderFactory() { + try { + return SipFactory.getInstance().createHeaderFactory(); + } catch (PeerUnavailableException e) { + e.printStackTrace(); + } + return null; + } + + public MessageFactory getMessageFactory() { + try { + return SipFactory.getInstance().createMessageFactory(); + } catch (PeerUnavailableException e) { + e.printStackTrace(); + } + return null; + } + + /*** + * 鍥炲鐘舵�佺爜 + * 100 trying + * 200 OK + * 400 + * 404 + * @param evt + * @throws SipException + * @throws InvalidArgumentException + * @throws ParseException + */ + public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (statusCode >= 200) { + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); + } + } + + public void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); + response.setReasonPhrase(msg); + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (statusCode >= 200) { + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); + } + } + + /** + * 鍥炲甯dp鐨�200 + * @param evt + * @param sdp + * @throws SipException + * @throws InvalidArgumentException + * @throws ParseException + */ + public void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); + SipFactory sipFactory = SipFactory.getInstance(); + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); + response.setContent(sdp, contentTypeHeader); + + SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); + + Address concatAddress = sipFactory.createAddressFactory().createAddress( + sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() + )); + response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); + getServerTransaction(evt).sendResponse(response); + } + + public Element getRootElement(RequestEvent evt) throws DocumentException { + return getRootElement(evt, "gb2312"); + } + public Element getRootElement(RequestEvent evt, String charset) throws DocumentException { + if (charset == null) charset = "gb2312"; + Request request = evt.getRequest(); + SAXReader reader = new SAXReader(); + reader.setEncoding(charset); + Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); + return xml.getRootElement(); + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java new file mode 100644 index 0000000..4121758 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -0,0 +1,123 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.Dialog; +import javax.sip.DialogState; +import javax.sip.RequestEvent; +import javax.sip.address.SipURI; +import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; +import javax.sip.header.ToHeader; +import java.util.HashMap; +import java.util.Map; + +/** + * @description:ACK璇锋眰澶勭悊鍣� + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍5:31:45 + */ +@Component +public class AckRequestProcessor extends SIPRequestProcessorAbstract { + + private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class); + private String method = "ACK"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private IMediaServerService mediaServerService; + + + /** + * 澶勭悊 ACK璇锋眰 + * + * @param evt + */ + @Override + public void process(RequestEvent evt) { + Dialog dialog = evt.getDialog(); + if (dialog == null) return; + if (dialog.getState()== DialogState.CONFIRMED) { + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); + String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; + String deviceId = sendRtpItem.getDeviceId(); + StreamInfo streamInfo = null; + if (deviceId == null) { + streamInfo = new StreamInfo(); + streamInfo.setApp(sendRtpItem.getApp()); + streamInfo.setStreamId(sendRtpItem.getStreamId()); + }else { + streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); + sendRtpItem.setStreamId(streamInfo.getStreamId()); + streamInfo.setApp("rtp"); + } + + redisCatchStorage.updateSendRTPSever(sendRtpItem); + logger.info(platformGbId); + logger.info(channelId); + Map<String, Object> param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",streamInfo.getApp()); + param.put("stream",streamInfo.getStreamId()); + param.put("ssrc", sendRtpItem.getSsrc()); + param.put("dst_url",sendRtpItem.getIp()); + param.put("dst_port", sendRtpItem.getPort()); + param.put("is_udp", is_Udp); + //param.put ("src_port", sendRtpItem.getLocalPort()); + // 璁惧鎺ㄦ祦鏌ヨ锛屾垚鍔熷悗鎵嶈兘杞帹 + boolean rtpPushed = false; + long startTime = System.currentTimeMillis(); + while (!rtpPushed) { + try { + if (System.currentTimeMillis() - startTime < 30 * 1000) { + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { + rtpPushed = true; + logger.info("宸茶幏鍙栬澶囨帹娴乕{}/{}]锛屽紑濮嬪悜涓婄骇鎺ㄦ祦[{}:{}]", + streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); + zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); + } else { + logger.info("绛夊緟璁惧鎺ㄦ祦[{}/{}].......", + streamInfo.getApp() ,streamInfo.getStreamId()); + Thread.sleep(1000); + continue; + } + } else { + rtpPushed = true; + logger.info("璁惧鎺ㄦ祦[{}/{}]瓒呮椂锛岀粓姝㈠悜涓婄骇鎺ㄦ祦", + streamInfo.getApp() ,streamInfo.getStreamId()); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java new file mode 100644 index 0000000..275e2cf --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java @@ -0,0 +1,115 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.*; +import javax.sip.address.SipURI; +import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; +import javax.sip.header.ToHeader; +import javax.sip.message.Response; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; + +/** + * @description: BYE璇锋眰澶勭悊鍣� + * @author: lawrencehj + * @date: 2021骞�3鏈�9鏃� + */ +@Component +public class ByeRequestProcessor extends SIPRequestProcessorAbstract { + + private Logger logger = LoggerFactory.getLogger(ByeRequestProcessor.class); + + @Autowired + private ISIPCommander cmder; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private IMediaServerService mediaServerService; + + private String method = "BYE"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + /** + * 澶勭悊BYE璇锋眰 + * @param evt + */ + @Override + public void process(RequestEvent evt) { + try { + responseAck(evt, Response.OK); + Dialog dialog = evt.getDialog(); + if (dialog == null) return; + if (dialog.getState().equals(DialogState.TERMINATED)) { + String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId); + logger.info("鏀跺埌bye, [{}/{}]", platformGbId, channelId); + if (sendRtpItem != null){ + String streamId = sendRtpItem.getStreamId(); + Map<String, Object> param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",sendRtpItem.getApp()); + param.put("stream",streamId); + param.put("ssrc",sendRtpItem.getSsrc()); + logger.info("鍋滄鍚戜笂绾ф帹娴侊細" + streamId); + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); + redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); + if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { + logger.info(streamId + "鏃犲叾瀹冭鐪嬭�咃紝閫氱煡璁惧鍋滄鎺ㄦ祦"); + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); + } + } + // 鍙兘鏄澶囦富鍔ㄥ仠姝� + Device device = storager.queryVideoDeviceByChannelId(platformGbId); + if (device != null) { + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); + if (streamInfo != null) { + redisCatchStorage.stopPlay(streamInfo); + } + storager.stopPlay(device.getDeviceId(), channelId); + mediaServerService.closeRTPServer(device, channelId); + } + } + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java new file mode 100644 index 0000000..b2bd9d9 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java @@ -0,0 +1,40 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.RequestEvent; + +/** + * @description:CANCEL璇锋眰澶勭悊鍣� + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍5:32:23 + */ +@Component +public class CancelRequestProcessor extends SIPRequestProcessorAbstract { + + private String method = "CANCEL"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + /** + * 澶勭悊CANCEL璇锋眰 + * + * @param evt 浜嬩欢 + */ + @Override + public void process(RequestEvent evt) { + // TODO 浼樺厛绾�99 Cancel Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傚彇娑堟寚浠� + + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java new file mode 100644 index 0000000..6984fab --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -0,0 +1,386 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.service.IPlayService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; +import gov.nist.javax.sip.address.AddressImpl; +import gov.nist.javax.sip.address.SipUri; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sdp.*; +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; +import javax.sip.SipException; +import javax.sip.address.SipURI; +import javax.sip.header.FromHeader; +import javax.sip.message.Request; +import javax.sip.message.Response; +import java.text.ParseException; +import java.util.Vector; + +/** + * @description:澶勭悊INVITE璇锋眰 + * @author: panll + * @date: 2021骞�1鏈�14鏃� + */ +@SuppressWarnings("rawtypes") +@Component +public class InviteRequestProcessor extends SIPRequestProcessorAbstract { + + private final static Logger logger = LoggerFactory.getLogger(InviteRequestProcessor.class); + + private String method = "INVITE"; + + @Autowired + private SIPCommanderFroPlatform cmderFroPlatform; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private SIPCommander cmder; + + @Autowired + private IPlayService playService; + + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Autowired + private IMediaServerService mediaServerService; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + /** + * 澶勭悊invite璇锋眰 + * + * @param evt + * 璇锋眰娑堟伅 + */ + @Override + public void process(RequestEvent evt) { + // Invite Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傝棰戞寚浠� + try { + Request request = evt.getRequest(); + SipURI sipURI = (SipURI) request.getRequestURI(); + String channelId = sipURI.getUser(); + String requesterId = null; + + FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); + AddressImpl address = (AddressImpl) fromHeader.getAddress(); + SipUri uri = (SipUri) address.getURI(); + requesterId = uri.getUser(); + + if (requesterId == null || channelId == null) { + logger.info("鏃犳硶浠嶧romHeader鐨凙ddress涓幏鍙栧埌骞冲彴id锛岃繑鍥�400"); + responseAck(evt, Response.BAD_REQUEST); // 鍙傛暟涓嶅叏锛� 鍙�400锛岃姹傞敊璇� + return; + } + + // 鏌ヨ璇锋眰鏂规槸鍚︿笂绾у钩鍙� + ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); + if (platform != null) { + // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾 + DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); + GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); + MediaServerItem mediaServerItem = null; + // 涓嶆槸閫氶亾鍙兘鏄洿鎾祦 + if (channel != null && gbStream == null ) { + if (channel.getStatus() == 0) { + logger.info("閫氶亾绂荤嚎锛岃繑鍥�400"); + responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); + return; + } + responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑 + }else if(channel == null && gbStream != null){ + String mediaServerId = gbStream.getMediaServerId(); + mediaServerItem = mediaServerService.getOne(mediaServerId); + if (mediaServerItem == null) { + logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410",gbStream.getApp(), gbStream.getStream(), mediaServerId); + responseAck(evt, Response.GONE, "media server not found"); + return; + } + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + if (!streamReady ) { + logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛岃繑鍥�400",gbStream.getApp(), gbStream.getStream()); + responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); + return; + } + responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑 + }else { + logger.info("閫氶亾涓嶅瓨鍦紝杩斿洖404"); + responseAck(evt, Response.NOT_FOUND); // 閫氶亾涓嶅瓨鍦紝鍙�404锛岃祫婧愪笉瀛樺湪 + return; + } + // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡 + String contentString = new String(request.getRawContent()); + + // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎绉婚櫎浠ヨВ鏋愩�� + int ssrcIndex = contentString.indexOf("y="); + //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� + String ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + String substring = contentString.substring(0, contentString.indexOf("y=")); + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); + + // 鑾峰彇鏀寔鐨勬牸寮� + Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 + //String ip = null; + int port = -1; + //boolean recvonly = false; + boolean mediaTransmissionTCP = false; + Boolean tcpActive = null; + for (Object description : mediaDescriptions) { + MediaDescription mediaDescription = (MediaDescription) description; + Media media = mediaDescription.getMedia(); + + Vector mediaFormats = media.getMediaFormats(false); + if (mediaFormats.contains("96")) { + port = media.getMediaPort(); + //String mediaType = media.getMediaType(); + String protocol = media.getProtocol(); + + // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp + if ("TCP/RTP/AVP".equals(protocol)) { + String setup = mediaDescription.getAttribute("setup"); + if (setup != null) { + mediaTransmissionTCP = true; + if ("active".equals(setup)) { + tcpActive = true; + } else if ("passive".equals(setup)) { + tcpActive = false; + } + } + } + break; + } + } + if (port == -1) { + logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); + // 鍥炲涓嶆敮鎸佺殑鏍煎紡 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 + return; + } + String username = sdp.getOrigin().getUsername(); + String addressStr = sdp.getOrigin().getAddress(); + //String sessionName = sdp.getSessionName().getValue(); + logger.info("[涓婄骇鐐规挱]鐢ㄦ埛锛歿}锛� 鍦板潃锛歿}:{}锛� ssrc锛歿}", username, addressStr, port, ssrc); + Device device = null; + // 閫氳繃 channel 鍜� gbStream 鏄惁涓簄ull 鍊煎垽鏂潵婧愭槸鐩存挱娴佸悎閫傚浗鏍� + if (channel != null) { + device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId); + if (device == null) { + logger.warn("鐐规挱骞冲彴{}鐨勯�氶亾{}鏃舵湭鎵惧埌璁惧淇℃伅", requesterId, channel); + responseAck(evt, Response.SERVER_INTERNAL_ERROR); + return; + } + mediaServerItem = playService.getNewMediaServerItem(device); + if (mediaServerItem == null) { + logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm"); + responseAck(evt, Response.BUSY_HERE); + return; + } + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + device.getDeviceId(), channelId, + mediaTransmissionTCP); + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + responseAck(evt, Response.BUSY_HERE); + return; + } + + // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� + redisCatchStorage.updateSendRTPSever(sendRtpItem); + // 閫氱煡涓嬬骇鎺ㄦ祦锛� + PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{ + // 鏀跺埌鎺ㄦ祦锛� 鍥炲200OK, 绛夊緟ack + // if (sendRtpItem == null) return; + sendRtpItem.setStatus(1); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + // TODO 娣诲姞瀵箃cp鐨勬敮鎸� + + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); + content.append("t=0 0\r\n"); + content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("y="+ ssrc + "\r\n"); + content.append("f=\r\n"); + + try { + responseAck(evt, content.toString()); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } ,((event) -> { + // 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒 + Response response = null; + try { + response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); + } catch (ParseException | SipException | InvalidArgumentException e) { + e.printStackTrace(); + } + })); + if (logger.isDebugEnabled()) { + logger.debug(playResult.getResult().toString()); + } + + }else if (gbStream != null) { + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + gbStream.getApp(), gbStream.getStream(), channelId, + mediaTransmissionTCP); + + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + responseAck(evt, Response.BUSY_HERE); + return; + } + + // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� + redisCatchStorage.updateSendRTPSever(sendRtpItem); + + sendRtpItem.setStatus(1); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + // TODO 娣诲姞瀵箃cp鐨勬敮鎸� + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); + content.append("t=0 0\r\n"); + content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:96 PS/90000\r\n"); + content.append("y="+ ssrc + "\r\n"); + content.append("f=\r\n"); + + try { + responseAck(evt, content.toString()); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + } else { + // 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛� + Device device = storager.queryVideoDevice(requesterId); + if (device != null) { + logger.info("鏀跺埌璁惧" + requesterId + "鐨勮闊冲箍鎾璉nvite璇锋眰"); + responseAck(evt, Response.TRYING); + + String contentString = new String(request.getRawContent()); + // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎绉婚櫎浠ヨВ鏋愩�� + String substring = contentString; + String ssrc = "0000000404"; + int ssrcIndex = contentString.indexOf("y="); + if (ssrcIndex > 0) { + substring = contentString.substring(0, ssrcIndex); + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + } + ssrcIndex = substring.indexOf("f="); + if (ssrcIndex > 0) { + substring = contentString.substring(0, ssrcIndex); + } + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); + + // 鑾峰彇鏀寔鐨勬牸寮� + Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 + int port = -1; + //boolean recvonly = false; + boolean mediaTransmissionTCP = false; + Boolean tcpActive = null; + for (int i = 0; i < mediaDescriptions.size(); i++) { + MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); + Media media = mediaDescription.getMedia(); + + Vector mediaFormats = media.getMediaFormats(false); + if (mediaFormats.contains("8")) { + port = media.getMediaPort(); + String protocol = media.getProtocol(); + // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp + if ("TCP/RTP/AVP".equals(protocol)) { + String setup = mediaDescription.getAttribute("setup"); + if (setup != null) { + mediaTransmissionTCP = true; + if ("active".equals(setup)) { + tcpActive = true; + } else if ("passive".equals(setup)) { + tcpActive = false; + } + } + } + break; + } + } + if (port == -1) { + logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); + // 鍥炲涓嶆敮鎸佺殑鏍煎紡 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 + return; + } + String username = sdp.getOrigin().getUsername(); + String addressStr = sdp.getOrigin().getAddress(); + logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", username, addressStr, port, ssrc); + + } else { + logger.warn("鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹�"); + responseAck(evt, Response.BAD_REQUEST); + } + } + + } catch (SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + logger.warn("sdp瑙f瀽閿欒"); + e.printStackTrace(); + } catch (SdpParseException e) { + e.printStackTrace(); + } catch (SdpException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor.java new file mode 100644 index 0000000..f4d2b86 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor.java @@ -0,0 +1,1103 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.VManageBootstrap; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.conf.UserSetup; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread; +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.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import com.genersoft.iot.vmp.service.IDeviceAlarmService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.utils.GpsUtil; +import com.genersoft.iot.vmp.utils.SpringBeanFactory; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; +import gov.nist.javax.sip.SipStackImpl; +import gov.nist.javax.sip.address.SipUri; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.sip.*; +import javax.sip.address.SipURI; +import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; +import javax.sip.header.ToHeader; +import javax.sip.message.Response; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + +import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; + +/** + * @description:MESSAGE璇锋眰澶勭悊鍣� + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍5:32:41 + */ +@SuppressWarnings(value={"unchecked", "rawtypes"}) +@Component +public class MessageRequestProcessor extends SIPRequestProcessorAbstract { + + public static volatile List<String> threadNameList = new ArrayList(); + private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); + + private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_"; + private static final String MESSAGE_KEEP_ALIVE = "Keepalive"; + private static final String MESSAGE_CONFIG_DOWNLOAD = "ConfigDownload"; + private static final String MESSAGE_CATALOG = "Catalog"; + private static final String MESSAGE_DEVICE_INFO = "DeviceInfo"; + private static final String MESSAGE_ALARM = "Alarm"; + private static final String MESSAGE_RECORD_INFO = "RecordInfo"; + private static final String MESSAGE_MEDIA_STATUS = "MediaStatus"; + private static final String MESSAGE_BROADCAST = "Broadcast"; + private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus"; + private static final String MESSAGE_DEVICE_CONTROL = "DeviceControl"; + private static final String MESSAGE_DEVICE_CONFIG = "DeviceConfig"; + private static final String MESSAGE_MOBILE_POSITION = "MobilePosition"; + private static final String MESSAGE_PRESET_QUERY = "PresetQuery"; + private String method = "MESSAGE"; + + @Autowired + private UserSetup userSetup; + + @Autowired + private SIPCommander cmder; + + @Autowired + private SipConfig config; + + @Autowired + private SIPCommanderFroPlatform cmderFroPlatform; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private EventPublisher publisher; + + @Autowired + private RedisUtil redis; + + @Autowired + private DeferredResultHolder deferredResultHolder; + + @Autowired + private DeviceOffLineDetector offLineDetector; + + @Autowired + private IDeviceAlarmService deviceAlarmService; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + /** + * 澶勭悊MESSAGE璇锋眰 + * + * @param evt + */ + @Override + public void process(RequestEvent evt) { + + try { + Element rootElement = getRootElement(evt); + String cmd = getText(rootElement, "CmdType"); + + if (MESSAGE_KEEP_ALIVE.equals(cmd)) { + logger.debug("鎺ユ敹鍒癒eepAlive娑堟伅"); + processMessageKeepAlive(evt); + } else if (MESSAGE_CONFIG_DOWNLOAD.equals(cmd)) { + logger.debug("鎺ユ敹鍒癈onfigDownload娑堟伅"); + processMessageConfigDownload(evt); + } else if (MESSAGE_CATALOG.equals(cmd)) { + logger.debug("鎺ユ敹鍒癈atalog娑堟伅"); + processMessageCatalogList(evt); + } else if (MESSAGE_DEVICE_INFO.equals(cmd)) { + // DeviceInfo娑堟伅澶勭悊 + processMessageDeviceInfo(evt); + } else if (MESSAGE_DEVICE_STATUS.equals(cmd)) { + // DeviceStatus娑堟伅澶勭悊 + processMessageDeviceStatus(evt); + } else if (MESSAGE_DEVICE_CONTROL.equals(cmd)) { + logger.debug("鎺ユ敹鍒癉eviceControl娑堟伅"); + processMessageDeviceControl(evt); + } else if (MESSAGE_DEVICE_CONFIG.equals(cmd)) { + logger.info("鎺ユ敹鍒癉eviceConfig娑堟伅"); + processMessageDeviceConfig(evt); + } else if (MESSAGE_ALARM.equals(cmd)) { + logger.debug("鎺ユ敹鍒癆larm娑堟伅"); + processMessageAlarm(evt); + } else if (MESSAGE_RECORD_INFO.equals(cmd)) { + logger.debug("鎺ユ敹鍒癛ecordInfo娑堟伅"); + processMessageRecordInfo(evt); + }else if (MESSAGE_MEDIA_STATUS.equals(cmd)) { + logger.debug("鎺ユ敹鍒癕ediaStatus娑堟伅"); + processMessageMediaStatus(evt); + } else if (MESSAGE_MOBILE_POSITION.equals(cmd)) { + logger.debug("鎺ユ敹鍒癕obilePosition娑堟伅"); + processMessageMobilePosition(evt); + } else if (MESSAGE_PRESET_QUERY.equals(cmd)) { + logger.debug("鎺ユ敹鍒癙resetQuery娑堟伅"); + processMessagePresetQuery(evt); + } else if (MESSAGE_BROADCAST.equals(cmd)) { + // Broadcast娑堟伅澶勭悊 + processMessageBroadcast(evt); + } else { + logger.debug("鎺ユ敹鍒版秷鎭細" + cmd); + responseAck(evt, Response.OK); + } + } catch (DocumentException | SipException |InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊MobilePosition绉诲姩浣嶇疆娑堟伅 + * + * @param evt + */ + private void processMessageMobilePosition(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊MobilePosition绉诲姩浣嶇疆娑堟伅鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt, device.getCharset()); + + MobilePosition mobilePosition = new MobilePosition(); + if (!StringUtils.isEmpty(device.getName())) { + mobilePosition.setDeviceName(device.getName()); + } + mobilePosition.setDeviceId(deviceId); + mobilePosition.setChannelId(getText(rootElement, "DeviceID")); + mobilePosition.setTime(getText(rootElement, "Time")); + mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); + mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); + if (NumericUtil.isDouble(getText(rootElement, "Speed"))) { + mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed"))); + } else { + mobilePosition.setSpeed(0.0); + } + if (NumericUtil.isDouble(getText(rootElement, "Direction"))) { + mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction"))); + } else { + mobilePosition.setDirection(0.0); + } + if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) { + mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude"))); + } else { + mobilePosition.setAltitude(0.0); + } + mobilePosition.setReportSource("Mobile Position"); + BaiduPoint bp = new BaiduPoint(); + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); + logger.info("鐧惧害鍧愭爣锛�" + bp.getBdLng() + ", " + bp.getBdLat()); + mobilePosition.setGeodeticSystem("BD-09"); + mobilePosition.setCnLng(bp.getBdLng()); + mobilePosition.setCnLat(bp.getBdLat()); + if (!userSetup.getSavePositionHistory()) { + storager.clearMobilePositionsByDeviceId(deviceId); + } + storager.insertMobilePosition(mobilePosition); + //鍥炲 200 OK + responseAck(evt, Response.OK); + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊DeviceStatus璁惧鐘舵�丮essage + * + * @param evt + */ + private void processMessageDeviceStatus(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊DeviceStatus璁惧鐘舵�丮essage鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt); + String name = rootElement.getName(); + Element deviceIdElement = rootElement.element("DeviceID"); + String channelId = deviceIdElement.getText(); + if (name.equalsIgnoreCase("Query")) { // 鍖哄垎鏄疪esponse鈥斺�旀煡璇㈠搷搴旓紝杩樻槸Query鈥斺�旀煡璇㈣姹� + logger.info("鎺ユ敹鍒癉eviceStatus鏌ヨ娑堟伅"); + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); + String platformId = ((SipUri) fromHeader.getAddress().getURI()).getUser(); + if (platformId == null) { + responseAck(evt, Response.NOT_FOUND); + return; + } else { + // 鍥炲200 OK + responseAck(evt, Response.OK); + String sn = rootElement.element("SN").getText(); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); + cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag()); + } + } else { + logger.info("鎺ユ敹鍒癉eviceStatus搴旂瓟娑堟伅"); + // 妫�鏌ヨ澶囨槸鍚﹀瓨鍦紝 涓嶅瓨鍦ㄥ垯涓嶅洖澶� + if (storager.exists(deviceId)) { + // 鍥炲200 OK + responseAck(evt, Response.OK); + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId + channelId); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); + } else { + } + } + } + + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊DeviceControl璁惧鐘舵�丮essage + * + * @param evt + */ + private void processMessageDeviceControl(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊DeviceControl璁惧鐘舵�丮essage鏈壘鍒拌澶囦俊鎭�"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + //String result = getText(rootElement, "Result"); + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (rootElement.getName().equals("Response")) {//} !StringUtils.isEmpty(result)) { + // 姝ゅ鏄鏈钩鍙板彂鍑篋eviceControl鎸囦护鐨勫簲绛� + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; + msg.setKey(key); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + } else { + // 姝ゅ鏄笂绾у彂鍑虹殑DeviceControl鎸囦护 + String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); + String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); + // 杩滅▼鍚姩鍔熻兘 + if (!StringUtils.isEmpty(getText(rootElement, "TeleBoot"))) { + if (deviceId.equals(targetGBId)) { + // 杩滅▼鍚姩鏈钩鍙帮細闇�瑕佸湪閲嶆柊鍚姩绋嬪簭鍚庡厛瀵筍ipStack瑙g粦 + logger.info("鎵ц杩滅▼鍚姩鏈钩鍙板懡浠�"); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); + cmderFroPlatform.unregister(parentPlatform, null, null); + + Thread restartThread = new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(3000); + SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); + SipStackImpl stack = (SipStackImpl)up.getSipStack(); + stack.stop(); + Iterator listener = stack.getListeningPoints(); + while (listener.hasNext()) { + stack.deleteListeningPoint((ListeningPoint) listener.next()); + } + Iterator providers = stack.getSipProviders(); + while (providers.hasNext()) { + stack.deleteSipProvider((SipProvider) providers.next()); + } + VManageBootstrap.restart(); + } catch (InterruptedException ignored) { + } catch (ObjectInUseException e) { + e.printStackTrace(); + } + } + }); + + restartThread.setDaemon(false); + restartThread.start(); + } else { + // 杩滅▼鍚姩鎸囧畾璁惧 + } + } + // 浜戝彴/鍓嶇鎺у埗鍛戒护 + if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) { + String cmdString = getText(rootElement,"PTZCmd"); + Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId); + cmder.fronEndCmd(deviceForPlatform, deviceId, cmdString); + } + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊DeviceConfig璁惧鐘舵�丮essage + * + * @param evt + */ + private void processMessageDeviceConfig(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊DeviceConfig璁惧鐘舵�丮essage娑堟伅鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (rootElement.getName().equals("Response")) { + // 姝ゅ鏄鏈钩鍙板彂鍑篋eviceControl鎸囦护鐨勫簲绛� + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId; + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + } else { + // 姝ゅ鏄笂绾у彂鍑虹殑DeviceConfig鎸囦护 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊ConfigDownload璁惧鐘舵�丮essage + * + * @param evt + */ + private void processMessageConfigDownload(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊ConfigDownload璁惧鐘舵�丮essage鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + deviceId + channelId; + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (rootElement.getName().equals("Response")) { + // 姝ゅ鏄鏈钩鍙板彂鍑篋eviceControl鎸囦护鐨勫簲绛� + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + } else { + // 姝ゅ鏄笂绾у彂鍑虹殑DeviceConfig鎸囦护 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊PresetQuery棰勭疆浣嶅垪琛∕essage + * + * @param evt + */ + private void processMessagePresetQuery(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊PresetQuery棰勭疆浣嶅垪琛∕essage鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId + channelId; + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (rootElement.getName().equals("Response")) {// !StringUtils.isEmpty(result)) { + // 姝ゅ鏄鏈钩鍙板彂鍑篋eviceControl鎸囦护鐨勫簲绛� + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + } else { + // 姝ゅ鏄笂绾у彂鍑虹殑DeviceControl鎸囦护 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊DeviceInfo璁惧淇℃伅Message + * + * @param evt + */ + private void processMessageDeviceInfo(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(deviceId); + + Element rootElement = getRootElement(evt); + String requestName = rootElement.getName(); + Element deviceIdElement = rootElement.element("DeviceID"); + String channelId = deviceIdElement.getTextTrim(); + String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + deviceId + channelId; + if (device != null ) { + rootElement = getRootElement(evt, device.getCharset()); + } + if (requestName.equals("Query")) { + logger.info("鎺ユ敹鍒癉eviceInfo鏌ヨ娑堟伅"); + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); + if (parentPlatform == null) { + responseAck(evt, Response.NOT_FOUND); + return; + } else { + // 鍥炲200 OK + responseAck(evt, Response.OK); + String sn = rootElement.element("SN").getText(); + cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag()); + } + } else { + logger.debug("鎺ユ敹鍒癉eviceInfo搴旂瓟娑堟伅"); + if (device == null) { + logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + + device.setName(getText(rootElement, "DeviceName")); + + device.setManufacturer(getText(rootElement, "Manufacturer")); + device.setModel(getText(rootElement, "Model")); + device.setFirmware(getText(rootElement, "Firmware")); + if (StringUtils.isEmpty(device.getStreamMode())) { + device.setStreamMode("UDP"); + } + storager.updateDevice(device); + + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(device); + deferredResultHolder.invokeAllResult(msg); + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); + } + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 鏀跺埌catalog璁惧鐩綍鍒楄〃璇锋眰 澶勭悊 + * + * @param evt + */ + private void processMessageCatalogList(RequestEvent evt) { + try { + + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(deviceId); + + + Element rootElement = getRootElement(evt); + String name = rootElement.getName(); + Element deviceIdElement = rootElement.element("DeviceID"); + String channelId = deviceIdElement.getText(); + Element deviceListElement = rootElement.element("DeviceList"); + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId; + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); + if (name.equalsIgnoreCase("Query")) { // 鍖哄垎鏄疪esponse鈥斺�旀煡璇㈠搷搴旓紝杩樻槸Query鈥斺�旀煡璇㈣姹� + // TODO 鍚庣画灏嗕唬鐮佹媶鍒� + if (parentPlatform == null) { + responseAck(evt, Response.NOT_FOUND); + return; + } else { + // 鍥炲200 OK + responseAck(evt, Response.OK); + + Element snElement = rootElement.element("SN"); + String sn = snElement.getText(); + // 鍑嗗鍥炲閫氶亾淇℃伅 + List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); + // 鏌ヨ鍏宠仈鐨勭洿鎾�氶亾 + List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); + int size = channelReduces.size() + gbStreams.size(); + // 鍥炲绾ц仈鐨勯�氶亾 + if (channelReduces.size() > 0) { + for (ChannelReduce channelReduce : channelReduces) { + DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); + cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); + } + } + // 鍥炲鐩存挱鐨勯�氶亾 + if (gbStreams.size() > 0) { + for (GbStream gbStream : gbStreams) { + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setChannelId(gbStream.getGbId()); + deviceChannel.setName(gbStream.getName()); + deviceChannel.setLongitude(gbStream.getLongitude()); + deviceChannel.setLatitude(gbStream.getLatitude()); + deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); + deviceChannel.setManufacture("wvp-pro"); + deviceChannel.setStatus(gbStream.isStatus()?1:0); +// deviceChannel.setParentId(parentPlatform.getDeviceGBId()); + deviceChannel.setRegisterWay(1); + deviceChannel.setCivilCode(config.getDomain()); + deviceChannel.setModel("live"); + deviceChannel.setOwner("wvp-pro"); +// deviceChannel.setAddress("test"); + deviceChannel.setParental(0); + deviceChannel.setSecrecy("0"); + deviceChannel.setSecrecy("0"); + + cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); + } + } + if (size == 0) { + // 鍥炲鏃犻�氶亾 + cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size); + } + } + + + } else { + if (device == null) { + logger.warn("鏀跺埌catalog璁惧鐩綍鍒楄〃璇锋眰鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + deviceListElement = getRootElement(evt, device.getCharset()).element("DeviceList"); + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); + if (deviceListIterator != null) { + + // 閬嶅巻DeviceList + while (deviceListIterator.hasNext()) { + Element itemDevice = deviceListIterator.next(); + Element channelDeviceElement = itemDevice.element("DeviceID"); + if (channelDeviceElement == null) { + continue; + } + String channelDeviceId = channelDeviceElement.getText(); + Element channdelNameElement = itemDevice.element("Name"); + String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; + Element statusElement = itemDevice.element("Status"); + String status = statusElement != null ? statusElement.getText().toString() : "ON"; + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setName(channelName); + deviceChannel.setChannelId(channelDeviceId); + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR鐨勫吋瀹规�у鐞� + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { + deviceChannel.setStatus(1); + } + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { + deviceChannel.setStatus(0); + } + + deviceChannel.setManufacture(getText(itemDevice, "Manufacturer")); + deviceChannel.setModel(getText(itemDevice, "Model")); + deviceChannel.setOwner(getText(itemDevice, "Owner")); + deviceChannel.setCivilCode(getText(itemDevice, "CivilCode")); + deviceChannel.setBlock(getText(itemDevice, "Block")); + deviceChannel.setAddress(getText(itemDevice, "Address")); + if (getText(itemDevice, "Parental") == null || getText(itemDevice, "Parental") == "") { + deviceChannel.setParental(0); + } else { + deviceChannel.setParental(Integer.parseInt(getText(itemDevice, "Parental"))); + } + deviceChannel.setParentId(getText(itemDevice, "ParentID")); + if (getText(itemDevice, "SafetyWay") == null || getText(itemDevice, "SafetyWay") == "") { + deviceChannel.setSafetyWay(0); + } else { + deviceChannel.setSafetyWay(Integer.parseInt(getText(itemDevice, "SafetyWay"))); + } + if (getText(itemDevice, "RegisterWay") == null || getText(itemDevice, "RegisterWay") == "") { + deviceChannel.setRegisterWay(1); + } else { + deviceChannel.setRegisterWay(Integer.parseInt(getText(itemDevice, "RegisterWay"))); + } + deviceChannel.setCertNum(getText(itemDevice, "CertNum")); + if (getText(itemDevice, "Certifiable") == null || getText(itemDevice, "Certifiable") == "") { + deviceChannel.setCertifiable(0); + } else { + deviceChannel.setCertifiable(Integer.parseInt(getText(itemDevice, "Certifiable"))); + } + if (getText(itemDevice, "ErrCode") == null || getText(itemDevice, "ErrCode") == "") { + deviceChannel.setErrCode(0); + } else { + deviceChannel.setErrCode(Integer.parseInt(getText(itemDevice, "ErrCode"))); + } + deviceChannel.setEndTime(getText(itemDevice, "EndTime")); + deviceChannel.setSecrecy(getText(itemDevice, "Secrecy")); + deviceChannel.setIpAddress(getText(itemDevice, "IPAddress")); + if (getText(itemDevice, "Port") == null || getText(itemDevice, "Port") == "") { + deviceChannel.setPort(0); + } else { + deviceChannel.setPort(Integer.parseInt(getText(itemDevice, "Port"))); + } + deviceChannel.setPassword(getText(itemDevice, "Password")); + if (NumericUtil.isDouble(getText(itemDevice, "Longitude"))) { + deviceChannel.setLongitude(Double.parseDouble(getText(itemDevice, "Longitude"))); + } else { + deviceChannel.setLongitude(0.00); + } + if (NumericUtil.isDouble(getText(itemDevice, "Latitude"))) { + deviceChannel.setLatitude(Double.parseDouble(getText(itemDevice, "Latitude"))); + } else { + deviceChannel.setLatitude(0.00); + } + if (getText(itemDevice, "PTZType") == null || getText(itemDevice, "PTZType") == "") { + deviceChannel.setPTZType(0); + } else { + deviceChannel.setPTZType(Integer.parseInt(getText(itemDevice, "PTZType"))); + } + deviceChannel.setHasAudio(true); // 榛樿鍚湁闊抽锛屾挱鏀炬椂鍐嶆鏌ユ槸鍚︽湁闊抽鍙婃槸鍚AC + storager.updateChannel(device.getDeviceId(), deviceChannel); + } + + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(device); + deferredResultHolder.invokeAllResult(msg); + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); + } + } + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 鏀跺埌alarm璁惧鎶ヨ淇℃伅 澶勭悊 + * + * @param evt + */ + private void processMessageAlarm(RequestEvent evt) { + try { + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊alarm璁惧鎶ヨ淇℃伅鏈壘鍒拌澶囦俊鎭�"); + responseAck(evt, Response.NOT_FOUND); + return; + } + Element rootElement = getRootElement(evt, device.getCharset()); + Element deviceIdElement = rootElement.element("DeviceID"); + String channelId = deviceIdElement.getText().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId + channelId; + // 鍥炲200 OK + responseAck(evt, Response.OK); + + if (device.getCharset() != null) { + rootElement = getRootElement(evt, device.getCharset()); + } + + if (rootElement.getName().equals("Notify")) { // 澶勭悊鎶ヨ閫氱煡 + DeviceAlarm deviceAlarm = new DeviceAlarm(); + deviceAlarm.setDeviceId(deviceId); + deviceAlarm.setChannelId(channelId); + deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority")); + deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod")); + deviceAlarm.setAlarmTime(getText(rootElement, "AlarmTime")); + if (getText(rootElement, "AlarmDescription") == null) { + deviceAlarm.setAlarmDescription(""); + } else { + deviceAlarm.setAlarmDescription(getText(rootElement, "AlarmDescription")); + } + if (NumericUtil.isDouble(getText(rootElement, "Longitude"))) { + deviceAlarm.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); + } else { + deviceAlarm.setLongitude(0.00); + } + if (NumericUtil.isDouble(getText(rootElement, "Latitude"))) { + deviceAlarm.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); + } else { + deviceAlarm.setLatitude(0.00); + } + + if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) { + if ( deviceAlarm.getAlarmMethod().equals("4")) { + MobilePosition mobilePosition = new MobilePosition(); + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); + mobilePosition.setTime(deviceAlarm.getAlarmTime()); + mobilePosition.setLongitude(deviceAlarm.getLongitude()); + mobilePosition.setLatitude(deviceAlarm.getLatitude()); + mobilePosition.setReportSource("GPS Alarm"); + BaiduPoint bp = new BaiduPoint(); + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); + logger.info("鐧惧害鍧愭爣锛�" + bp.getBdLng() + ", " + bp.getBdLat()); + mobilePosition.setGeodeticSystem("BD-09"); + mobilePosition.setCnLng(bp.getBdLng()); + mobilePosition.setCnLat(bp.getBdLat()); + if (!userSetup.getSavePositionHistory()) { + storager.clearMobilePositionsByDeviceId(deviceId); + } + storager.insertMobilePosition(mobilePosition); + } + } + logger.debug("瀛樺偍鎶ヨ淇℃伅銆佹姤璀﹀垎绫�"); + // 瀛樺偍鎶ヨ淇℃伅銆佹姤璀﹀垎绫� + deviceAlarmService.add(deviceAlarm); + + if (offLineDetector.isOnline(deviceId)) { + publisher.deviceAlarmEventPublish(deviceAlarm); + } + } else if (rootElement.getName().equals("Response")) { // 澶勭悊鎶ヨ鏌ヨ鍝嶅簲 + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 鏀跺埌keepalive璇锋眰 澶勭悊 + * + * @param evt + */ + private void processMessageKeepAlive(RequestEvent evt) { + try { + + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + + // 妫�鏌ヨ澶囨槸鍚﹀瓨鍦ㄥ苟鍦ㄧ嚎锛� 涓嶅湪绾垮垯璁剧疆涓哄湪绾� + if (device != null ) { + // 鍥炲200 OK + responseAck(evt, Response.OK); + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); + }else{ + logger.warn("鏀跺埌[ "+deviceId+" ]蹇冭烦淇℃伅, 浣嗘槸璁惧涓嶅瓨鍦�, 鍥炲404"); + Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest()); + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (serverTransaction.getDialog() != null) { + serverTransaction.getDialog().delete(); + } + } + +// if (device != null && device.getOnline() == 1) { +// +// if (offLineDetector.isOnline(deviceId)) { +// publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); +// } else { +// } +// }else { +//// logger.warn("鏀跺埌[ "+deviceId+" ]蹇冭烦淇℃伅, 浣嗘槸璁惧" + (device == null? "涓嶅瓨鍦�":"绂荤嚎") + ", 鍥炲401"); +//// Response response = getMessageFactory().createResponse(Response.UNAUTHORIZED, evt.getRequest()); +//// getServerTransaction(evt).sendResponse(response); +// publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); +// +// } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /*** + * 澶勭悊RecordInfo璁惧褰曞儚鍒楄〃Message璇锋眰 TODO 杩囨湡鏃堕棿鏆傛椂鍐欐180绉掞紝鍚庣画涓嶥eferredResult瓒呮椂鏃堕棿淇濇寔涓�鑷� + * + * @param evt + */ + private void processMessageRecordInfo(RequestEvent evt) { + try { + + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + + // 鍥炲200 OK + responseAck(evt, Response.OK); + String uuid = UUID.randomUUID().toString().replace("-", ""); + RecordInfo recordInfo = new RecordInfo(); + Element rootElement = getRootElement(evt); + Element deviceIdElement = rootElement.element("DeviceID"); + String channelId = deviceIdElement.getText().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId; + if (device != null ) { + rootElement = getRootElement(evt, device.getCharset()); + } + recordInfo.setDeviceId(deviceId); + recordInfo.setChannelId(channelId); + recordInfo.setName(getText(rootElement, "Name")); + if (getText(rootElement, "SumNum")== null || getText(rootElement, "SumNum") =="") { + recordInfo.setSumNum(0); + } else { + recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum"))); + } + String sn = getText(rootElement, "SN"); + Element recordListElement = rootElement.element("RecordList"); + if (recordListElement == null || recordInfo.getSumNum() == 0) { + logger.info("鏃犲綍鍍忔暟鎹�"); + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(recordInfo); + deferredResultHolder.invokeAllResult(msg); + } else { + Iterator<Element> recordListIterator = recordListElement.elementIterator(); + List<RecordItem> recordList = new ArrayList<RecordItem>(); + if (recordListIterator != null) { + RecordItem record = new RecordItem(); + logger.info("澶勭悊褰曞儚鍒楄〃鏁版嵁..."); + // 閬嶅巻DeviceList + while (recordListIterator.hasNext()) { + Element itemRecord = recordListIterator.next(); + Element recordElement = itemRecord.element("DeviceID"); + if (recordElement == null) { + logger.info("璁板綍涓虹┖锛屼笅涓�涓�..."); + continue; + } + record = new RecordItem(); + record.setDeviceId(getText(itemRecord, "DeviceID")); + record.setName(getText(itemRecord, "Name")); + record.setFilePath(getText(itemRecord, "FilePath")); + record.setAddress(getText(itemRecord, "Address")); + record.setStartTime( + DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "StartTime"))); + record.setEndTime( + DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "EndTime"))); + record.setSecrecy(itemRecord.element("Secrecy") == null ? 0 + : Integer.parseInt(getText(itemRecord, "Secrecy"))); + record.setType(getText(itemRecord, "Type")); + record.setRecorderId(getText(itemRecord, "RecorderID")); + recordList.add(record); + } + recordInfo.setRecordList(recordList); + } + + // 鏀圭敤鍗曠嫭绾跨▼缁熻宸茶幏鍙栧綍鍍忔枃浠舵暟閲忥紝閬垮厤澶氬寘骞惰鍒嗗埆缁熻涓嶅畬鏁寸殑闂 + String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; + redis.set(cacheKey + "_" + uuid, recordList, 90); + if (!threadNameList.contains(cacheKey)) { + threadNameList.add(cacheKey); + CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo); + chk.setName(cacheKey); + chk.setDeferredResultHolder(deferredResultHolder); + chk.setRedis(redis); + chk.setLogger(logger); + chk.start(); + if (logger.isDebugEnabled()) { + logger.debug("Start Thread " + cacheKey + "."); + } + } else { + if (logger.isDebugEnabled()) { + logger.debug("Thread " + cacheKey + " already started."); + } + } + + // 瀛樺湪褰曞儚涓斿鏋滃綋鍓嶅綍鍍忔槑缁嗕釜鏁板皬浜庢�绘潯鏁帮紝璇存槑鎷嗗寘杩斿洖锛岄渶瑕佺粍瑁咃紝鏆備笉杩斿洖 + // if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { + // // 涓洪槻姝㈣繛缁姹傝璁惧鐨勫綍鍍忔暟鎹紝杩斿洖鏁版嵁閿欎贡锛岀壒澧炲姞sn杩涜鍖哄垎 + // String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; + + // redis.set(cacheKey + "_" + uuid, recordList, 90); + // List<Object> cacheKeys = redis.scan(cacheKey + "_*"); + // List<RecordItem> totalRecordList = new ArrayList<RecordItem>(); + // for (int i = 0; i < cacheKeys.size(); i++) { + // totalRecordList.addAll((List<RecordItem>) redis.get(cacheKeys.get(i).toString())); + // } + // if (totalRecordList.size() < recordInfo.getSumNum()) { + // logger.info("宸茶幏鍙�" + totalRecordList.size() + "椤瑰綍鍍忔暟鎹紝鍏�" + recordInfo.getSumNum() + "椤�"); + // return; + // } + // logger.info("褰曞儚鏁版嵁宸插叏閮ㄨ幏鍙栵紝鍏�" + recordInfo.getSumNum() + "椤�"); + // recordInfo.setRecordList(totalRecordList); + // for (int i = 0; i < cacheKeys.size(); i++) { + // redis.del(cacheKeys.get(i).toString()); + // } + // } + // // 鑷劧椤哄簭鎺掑簭, 鍏冪礌杩涜鍗囧簭鎺掑垪 + // recordInfo.getRecordList().sort(Comparator.naturalOrder()); + } + // 璧板埌杩欓噷锛屾湁浠ヤ笅鍙兘锛�1銆佹病鏈夊綍鍍忎俊鎭�,绗竴娆℃敹鍒皉ecordinfo鐨勬秷鎭嵆杩斿洖鍝嶅簲鏁版嵁锛屾棤redis鎿嶄綔 + // 2銆佹湁褰曞儚鏁版嵁锛屼笖绗竴娆″嵆鏀跺埌瀹屾暣鏁版嵁锛岃繑鍥炲搷搴旀暟鎹紝鏃爎edis鎿嶄綔 + // 3銆佹湁褰曞儚鏁版嵁锛屽湪瓒呮椂鏃堕棿鍐呮敹鍒板娆″寘缁勮鍚庢暟閲忚冻澶燂紝杩斿洖鏁版嵁 + + // RequestMessage msg = new RequestMessage(); + // msg.setDeviceId(deviceId); + // msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); + // msg.setData(recordInfo); + // deferredResultHolder.invokeResult(msg); + // logger.info("澶勭悊瀹屾垚锛岃繑鍥炵粨鏋�"); + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /** + * 鏀跺埌MediaStatus娑堟伅澶勭悊 + * + * @param evt + */ + private void processMessageMediaStatus(RequestEvent evt){ + try { + + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + + // 鍥炲200 OK + responseAck(evt, Response.OK); + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + String NotifyType =getText(rootElement, "NotifyType"); + if (NotifyType.equals("121")){ + logger.info("濯掍綋鎾斁瀹屾瘯锛岄�氱煡鍏虫祦"); + StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, "*"); + if (streamInfo != null) { + redisCatchStorage.stopPlayback(streamInfo); + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId()); + } + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊AudioBroadcast璇煶骞挎挱Message + * + * @param evt + */ + private void processMessageBroadcast(RequestEvent evt) { + try { + + String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); + // 鏌ヨ璁惧鏄惁瀛樺湪 + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + logger.warn("澶勭悊DeviceInfo璁惧淇℃伅Message鏃舵湭鎵惧埌璁惧淇℃伅"); + responseAck(evt, Response.NOT_FOUND); + return; + } + + Element rootElement = getRootElement(evt); + String channelId = getText(rootElement, "DeviceID"); + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId + channelId; + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (rootElement.getName().equals("Response")) { + // 姝ゅ鏄鏈钩鍙板彂鍑築roadcast鎸囦护鐨勫簲绛� + JSONObject json = new JSONObject(); + XmlUtil.node2Json(rootElement, json); + if (logger.isDebugEnabled()) { + logger.debug(json.toJSONString()); + } + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(json); + deferredResultHolder.invokeAllResult(msg); + } else { + // 姝ゅ鏄笂绾у彂鍑虹殑Broadcast鎸囦护 + } + } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java new file mode 100644 index 0000000..88bf45a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java @@ -0,0 +1,384 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.UserSetup; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.utils.GpsUtil; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.SipException; +import javax.sip.header.FromHeader; +import javax.sip.message.Response; +import java.text.ParseException; +import java.util.Iterator; + +/** + * @description: Notify璇锋眰澶勭悊鍣� + * @author: lawrencehj + * @date: 2021骞�1鏈�27鏃� + */ +@Component +public class NotifyRequestProcessor extends SIPRequestProcessorAbstract { + + + private final static Logger logger = LoggerFactory.getLogger(NotifyRequestProcessor.class); + + @Autowired + private UserSetup userSetup; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private EventPublisher publisher; + + @Autowired + private DeviceOffLineDetector offLineDetector; + + private static final String NOTIFY_CATALOG = "Catalog"; + private static final String NOTIFY_ALARM = "Alarm"; + private static final String NOTIFY_MOBILE_POSITION = "MobilePosition"; + private String method = "NOTIFY"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + @Override + public void process(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + String cmd = XmlUtil.getText(rootElement, "CmdType"); + + if (NOTIFY_CATALOG.equals(cmd)) { + logger.info("鎺ユ敹鍒癈atalog閫氱煡"); + processNotifyCatalogList(evt); + } else if (NOTIFY_ALARM.equals(cmd)) { + logger.info("鎺ユ敹鍒癆larm閫氱煡"); + processNotifyAlarm(evt); + } else if (NOTIFY_MOBILE_POSITION.equals(cmd)) { + logger.info("鎺ユ敹鍒癕obilePosition閫氱煡"); + processNotifyMobilePosition(evt); + } else { + logger.info("鎺ユ敹鍒版秷鎭細" + cmd); + responseAck(evt, Response.OK); + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /** + * 澶勭悊MobilePosition绉诲姩浣嶇疆Notify + * + * @param evt + */ + private void processNotifyMobilePosition(RequestEvent evt) { + try { + // 鍥炲 200 OK + Element rootElement = getRootElement(evt); + MobilePosition mobilePosition = new MobilePosition(); + Element deviceIdElement = rootElement.element("DeviceID"); + String deviceId = deviceIdElement.getTextTrim().toString(); + Device device = storager.queryVideoDevice(deviceId); + if (device != null) { + if (!StringUtils.isEmpty(device.getName())) { + mobilePosition.setDeviceName(device.getName()); + } + } + mobilePosition.setDeviceId(XmlUtil.getText(rootElement, "DeviceID")); + mobilePosition.setTime(XmlUtil.getText(rootElement, "Time")); + mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); + mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) { + mobilePosition.setSpeed(Double.parseDouble(XmlUtil.getText(rootElement, "Speed"))); + } else { + mobilePosition.setSpeed(0.0); + } + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Direction"))) { + mobilePosition.setDirection(Double.parseDouble(XmlUtil.getText(rootElement, "Direction"))); + } else { + mobilePosition.setDirection(0.0); + } + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Altitude"))) { + mobilePosition.setAltitude(Double.parseDouble(XmlUtil.getText(rootElement, "Altitude"))); + } else { + mobilePosition.setAltitude(0.0); + } + mobilePosition.setReportSource("Mobile Position"); + BaiduPoint bp = new BaiduPoint(); + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); + logger.info("鐧惧害鍧愭爣锛�" + bp.getBdLng() + ", " + bp.getBdLat()); + mobilePosition.setGeodeticSystem("BD-09"); + mobilePosition.setCnLng(bp.getBdLng()); + mobilePosition.setCnLat(bp.getBdLat()); + if (!userSetup.getSavePositionHistory()) { + storager.clearMobilePositionsByDeviceId(deviceId); + } + storager.insertMobilePosition(mobilePosition); + responseAck(evt, Response.OK); + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 澶勭悊alarm璁惧鎶ヨNotify + * + * @param evt + */ + private void processNotifyAlarm(RequestEvent evt) { + try { + Element rootElement = getRootElement(evt); + Element deviceIdElement = rootElement.element("DeviceID"); + String deviceId = deviceIdElement.getText().toString(); + + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + return; + } + rootElement = getRootElement(evt, device.getCharset()); + DeviceAlarm deviceAlarm = new DeviceAlarm(); + deviceAlarm.setDeviceId(deviceId); + deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority")); + deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod")); + deviceAlarm.setAlarmTime(XmlUtil.getText(rootElement, "AlarmTime")); + if (XmlUtil.getText(rootElement, "AlarmDescription") == null) { + deviceAlarm.setAlarmDescription(""); + } else { + deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription")); + } + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) { + deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude"))); + } else { + deviceAlarm.setLongitude(0.00); + } + if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) { + deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude"))); + } else { + deviceAlarm.setLatitude(0.00); + } + + if (deviceAlarm.getAlarmMethod().equals("4")) { + MobilePosition mobilePosition = new MobilePosition(); + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); + mobilePosition.setTime(deviceAlarm.getAlarmTime()); + mobilePosition.setLongitude(deviceAlarm.getLongitude()); + mobilePosition.setLatitude(deviceAlarm.getLatitude()); + mobilePosition.setReportSource("GPS Alarm"); + BaiduPoint bp = new BaiduPoint(); + bp = GpsUtil.Wgs84ToBd09(String.valueOf(mobilePosition.getLongitude()), String.valueOf(mobilePosition.getLatitude())); + logger.info("鐧惧害鍧愭爣锛�" + bp.getBdLng() + ", " + bp.getBdLat()); + mobilePosition.setGeodeticSystem("BD-09"); + mobilePosition.setCnLng(bp.getBdLng()); + mobilePosition.setCnLat(bp.getBdLat()); + if (!userSetup.getSavePositionHistory()) { + storager.clearMobilePositionsByDeviceId(deviceId); + } + storager.insertMobilePosition(mobilePosition); + } + // TODO: 闇�瑕佸疄鐜板瓨鍌ㄦ姤璀︿俊鎭�佹姤璀﹀垎绫� + + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (offLineDetector.isOnline(deviceId)) { + publisher.deviceAlarmEventPublish(deviceAlarm); + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + /*** + * 澶勭悊catalog璁惧鐩綍鍒楄〃Notify + * + * @param evt + */ + private void processNotifyCatalogList(RequestEvent evt) { + try { + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); + String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); + + Element rootElement = getRootElement(evt); + Element deviceIdElement = rootElement.element("DeviceID"); + String channelId = deviceIdElement.getText(); + Device device = storager.queryVideoDevice(deviceId); + if (device == null) { + return; + } + if (device != null ) { + rootElement = getRootElement(evt, device.getCharset()); + } + Element deviceListElement = rootElement.element("DeviceList"); + if (deviceListElement == null) { + return; + } + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); + if (deviceListIterator != null) { + + // 閬嶅巻DeviceList + while (deviceListIterator.hasNext()) { + Element itemDevice = deviceListIterator.next(); + Element channelDeviceElement = itemDevice.element("DeviceID"); + if (channelDeviceElement == null) { + continue; + } + String channelDeviceId = channelDeviceElement.getTextTrim(); + Element channdelNameElement = itemDevice.element("Name"); + String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : ""; + Element statusElement = itemDevice.element("Status"); + String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON"; + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setName(channelName); + deviceChannel.setChannelId(channelDeviceId); + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR鐨勫吋瀹规�у鐞� + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { + deviceChannel.setStatus(1); + } + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { + deviceChannel.setStatus(0); + } + + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer")); + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model")); + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner")); + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode")); + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block")); + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address")); + if (XmlUtil.getText(itemDevice, "Parental") == null + || XmlUtil.getText(itemDevice, "Parental") == "") { + deviceChannel.setParental(0); + } else { + deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental"))); + } + deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID")); + if (XmlUtil.getText(itemDevice, "SafetyWay") == null + || XmlUtil.getText(itemDevice, "SafetyWay") == "") { + deviceChannel.setSafetyWay(0); + } else { + deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay"))); + } + if (XmlUtil.getText(itemDevice, "RegisterWay") == null + || XmlUtil.getText(itemDevice, "RegisterWay") == "") { + deviceChannel.setRegisterWay(1); + } else { + deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay"))); + } + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum")); + if (XmlUtil.getText(itemDevice, "Certifiable") == null + || XmlUtil.getText(itemDevice, "Certifiable") == "") { + deviceChannel.setCertifiable(0); + } else { + deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable"))); + } + if (XmlUtil.getText(itemDevice, "ErrCode") == null + || XmlUtil.getText(itemDevice, "ErrCode") == "") { + deviceChannel.setErrCode(0); + } else { + deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode"))); + } + deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime")); + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy")); + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress")); + if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") { + deviceChannel.setPort(0); + } else { + deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); + } + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password")); + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) { + deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude"))); + } else { + deviceChannel.setLongitude(0.00); + } + if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) { + deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude"))); + } else { + deviceChannel.setLatitude(0.00); + } + if (XmlUtil.getText(itemDevice, "PTZType") == null + || XmlUtil.getText(itemDevice, "PTZType") == "") { + deviceChannel.setPTZType(0); + } else { + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); + } + deviceChannel.setHasAudio(true); // 榛樿鍚湁闊抽锛屾挱鏀炬椂鍐嶆鏌ユ槸鍚︽湁闊抽鍙婃槸鍚AC + storager.updateChannel(device.getDeviceId(), deviceChannel); + } + + // RequestMessage msg = new RequestMessage(); + // msg.setDeviceId(deviceId); + // msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG); + // msg.setData(device); + // deferredResultHolder.invokeResult(msg); + // 鍥炲200 OK + responseAck(evt, Response.OK); + if (offLineDetector.isOnline(deviceId)) { + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); + } + } + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { + e.printStackTrace(); + } + } + + + + + public void setCmder(SIPCommander cmder) { + } + + public void setStorager(IVideoManagerStorager storager) { + this.storager = storager; + } + + public void setPublisher(EventPublisher publisher) { + this.publisher = publisher; + } + + public void setRedis(RedisUtil redis) { + } + + public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) { + } + + public void setOffLineDetector(DeviceOffLineDetector offLineDetector) { + this.offLineDetector = offLineDetector; + } + + public IRedisCatchStorage getRedisCatchStorage() { + return redisCatchStorage; + } + + public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { + this.redisCatchStorage = redisCatchStorage; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java new file mode 100644 index 0000000..e16043d --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -0,0 +1,197 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; +import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import gov.nist.javax.sip.RequestEventExt; +import gov.nist.javax.sip.address.AddressImpl; +import gov.nist.javax.sip.address.SipUri; +import gov.nist.javax.sip.header.Expires; +import gov.nist.javax.sip.header.SIPDateHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; +import javax.sip.SipException; +import javax.sip.header.*; +import javax.sip.message.Request; +import javax.sip.message.Response; +import java.security.NoSuchAlgorithmException; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Locale; + +/** + * @description:鏀跺埌娉ㄥ唽璇锋眰 澶勭悊 + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍4:47:25 + */ +@Component +public class RegisterRequestProcessor extends SIPRequestProcessorAbstract { + + private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class); + + public String method = "REGISTER"; + + @Autowired + private SipConfig sipConfig; + + @Autowired + private RegisterLogicHandler handler; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private EventPublisher publisher; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + /** + * 鏀跺埌娉ㄥ唽璇锋眰 澶勭悊 + * @param evt + */ + @Override + public void process(RequestEvent evt) { + try { + RequestEventExt evtExt = (RequestEventExt)evt; + String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); + logger.info("[{}] 鏀跺埌娉ㄥ唽璇锋眰锛屽紑濮嬪鐞�", requestAddress); + Request request = evt.getRequest(); + + Response response = null; + boolean passwordCorrect = false; + // 娉ㄥ唽鏍囧織 0锛氭湭鎼哄甫鎺堟潈澶存垨鑰呭瘑鐮侀敊璇� 1锛氭敞鍐屾垚鍔� 2锛氭敞閿�鎴愬姛 + int registerFlag = 0; + FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); + AddressImpl address = (AddressImpl) fromHeader.getAddress(); + SipUri uri = (SipUri) address.getURI(); + String deviceId = uri.getUser(); + Device device = storager.queryVideoDevice(deviceId); + AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); + // 鏍¢獙瀵嗙爜鏄惁姝g‘ + if (authorhead != null) { + passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, + sipConfig.getPassword()); + } + if (StringUtils.isEmpty(sipConfig.getPassword())){ + passwordCorrect = true; + } + + // 鏈惡甯︽巿鏉冨ご鎴栬�呭瘑鐮侀敊璇� 鍥炲401 + if (authorhead == null ) { + + logger.info("[{}] 鏈惡甯︽巿鏉冨ご 鍥炲401", requestAddress); + response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); + new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); + }else { + if (!passwordCorrect){ + // 娉ㄥ唽澶辫触 + response = getMessageFactory().createResponse(Response.FORBIDDEN, request); + response.setReasonPhrase("wrong password"); + logger.info("[{}] 瀵嗙爜/SIP鏈嶅姟鍣↖D閿欒, 鍥炲403", requestAddress); + }else { + // 鎼哄甫鎺堟潈澶村苟涓斿瘑鐮佹纭� + response = getMessageFactory().createResponse(Response.OK, request); + // 娣诲姞date澶� + SIPDateHeader dateHeader = new SIPDateHeader(); + // 浣跨敤鑷繁淇敼鐨� + WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); + dateHeader.setDate(wvpSipDate); + response.addHeader(dateHeader); + + ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); + if (expiresHeader == null) { + response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); + return; + } + // 娣诲姞Contact澶� + response.addHeader(request.getHeader(ContactHeader.NAME)); + // 娣诲姞Expires澶� + response.addHeader(request.getExpires()); + + // 鑾峰彇鍒伴�氫俊鍦板潃绛変俊鎭� + ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); + String received = viaHeader.getReceived(); + int rPort = viaHeader.getRPort(); + // 瑙f瀽鏈湴鍦板潃鏇夸唬 + if (StringUtils.isEmpty(received) || rPort == -1) { + received = viaHeader.getHost(); + rPort = viaHeader.getPort(); + } + // + + if (device == null) { + device = new Device(); + device.setStreamMode("UDP"); + device.setCharset("gb2312"); + device.setDeviceId(deviceId); + device.setFirsRegister(true); + } + device.setIp(received); + device.setPort(rPort); + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); + // 娉ㄩ攢鎴愬姛 + if (expiresHeader.getExpires() == 0) { + registerFlag = 2; + } + // 娉ㄥ唽鎴愬姛 + else { + device.setExpires(expiresHeader.getExpires()); + registerFlag = 1; + // 鍒ゆ柇TCP杩樻槸UDP + boolean isTcp = false; + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); + String transport = reqViaHeader.getTransport(); + if (transport.equals("TCP")) { + isTcp = true; + } + device.setTransport(isTcp ? "TCP" : "UDP"); + } + } + } + + ServerTransaction serverTransaction = getServerTransaction(evt); + serverTransaction.sendResponse(response); + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete(); + // 娉ㄥ唽鎴愬姛 + // 淇濆瓨鍒皉edis + // 涓嬪彂catelog鏌ヨ鐩綍 + if (registerFlag == 1 ) { + logger.info("[{}] 娉ㄥ唽鎴愬姛! deviceId:" + device.getDeviceId(), requestAddress); + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER); + // 閲嶆柊娉ㄥ唽鏇存柊璁惧鍜岄�氶亾锛屼互鍏嶈澶囨浛鎹㈡垨鏇存柊鍚庝俊鎭棤娉曟洿鏂� + handler.onRegister(device); + } else if (registerFlag == 2) { + logger.info("[{}] 娉ㄩ攢鎴愬姛! deviceId:" + device.getDeviceId(), requestAddress); + publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); + } + } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java new file mode 100644 index 0000000..d5f582c --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java @@ -0,0 +1,75 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; + +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorAbstract; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.ServerTransaction; +import javax.sip.SipException; +import javax.sip.header.ExpiresHeader; +import javax.sip.message.Request; +import javax.sip.message.Response; +import java.text.ParseException; + +/** + * @description:SUBSCRIBE璇锋眰澶勭悊鍣� + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍5:31:20 + */ +@Component +public class SubscribeRequestProcessor extends SIPRequestProcessorAbstract { + + private Logger logger = LoggerFactory.getLogger(SubscribeRequestProcessor.class); + private String method = "SUBSCRIBE"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addRequestProcessor(method, this); + } + + /** + * 澶勭悊SUBSCRIBE璇锋眰 + * + * @param evt + */ + @Override + public void process(RequestEvent evt) { + Request request = evt.getRequest(); + + try { + Response response = null; + response = getMessageFactory().createResponse(200, request); + if (response != null) { + ExpiresHeader expireHeader = getHeaderFactory().createExpiresHeader(30); + response.setExpires(expireHeader); + } + logger.info("response : " + response.toString()); + ServerTransaction transaction = getServerTransaction(evt); + if (transaction != null) { + transaction.sendResponse(response); + transaction.getDialog().delete(); + transaction.terminate(); + } else { + logger.info("processRequest serverTransactionId is null."); + } + + } catch (ParseException e) { + e.printStackTrace(); + } catch (SipException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/ISIPResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/ISIPResponseProcessor.java new file mode 100644 index 0000000..50fb202 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/ISIPResponseProcessor.java @@ -0,0 +1,15 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.response; + +import javax.sip.ResponseEvent; + +/** + * @description:澶勭悊鎺ユ敹IPCamera鍙戞潵鐨凷IP鍗忚鍝嶅簲娑堟伅 + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍4:42:22 + */ +public interface ISIPResponseProcessor { + + void process(ResponseEvent evt); + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java new file mode 100644 index 0000000..d44c1a9 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java @@ -0,0 +1,49 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; + +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.gb28181.SipLayer; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.ResponseEvent; + +/** + * @description: BYE璇锋眰鍝嶅簲鍣� + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍5:32:05 + */ +@Component +public class ByeResponseProcessor extends SIPResponseProcessorAbstract { + + private String method = "BYE"; + + @Autowired + private SipLayer sipLayer; + + @Autowired + private SipConfig config; + + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addResponseProcessor(method, this); + } + /** + * 澶勭悊BYE鍝嶅簲 + * + * @param evt + */ + @Override + public void process(ResponseEvent evt) { + // TODO Auto-generated method stub + System.out.println("鏀跺埌bye"); + } + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java new file mode 100644 index 0000000..80d7e2b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java @@ -0,0 +1,47 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; + +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.gb28181.SipLayer; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.ResponseEvent; + +/** + * @description: CANCEL鍝嶅簲澶勭悊鍣� + * @author: panlinlin + * @date: 2021骞�11鏈�5鏃� 16:35 + */ +@Component +public class CancelResponseProcessor extends SIPResponseProcessorAbstract { + + private String method = "CANCEL"; + + @Autowired + private SipLayer sipLayer; + + @Autowired + private SipConfig config; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addResponseProcessor(method, this); + } + /** + * 澶勭悊CANCEL鍝嶅簲 + * + * @param evt + */ + @Override + public void process(ResponseEvent evt) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java new file mode 100644 index 0000000..5446a90 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java @@ -0,0 +1,97 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; + +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.gb28181.SipLayer; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; +import gov.nist.javax.sip.ResponseEventExt; +import gov.nist.javax.sip.stack.SIPDialog; +import org.slf4j.Logger; +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.address.SipURI; +import javax.sip.header.CSeqHeader; +import javax.sip.message.Request; +import javax.sip.message.Response; +import java.text.ParseException; + + +/** + * @description: 澶勭悊INVITE鍝嶅簲 + * @author: panlinlin + * @date: 2021骞�11鏈�5鏃� 16锛�40 + */ +@Component +public class InviteResponseProcessor extends SIPResponseProcessorAbstract { + + private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class); + private String method = "INVITE"; + + @Autowired + private SipLayer sipLayer; + + @Autowired + private SipConfig config; + + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addResponseProcessor(method, this); + } + + @Autowired + private VideoStreamSessionManager streamSession; + + /** + * 澶勭悊invite鍝嶅簲 + * + * @param evt 鍝嶅簲娑堟伅 + * @throws ParseException + */ + @Override + public void process(ResponseEvent evt ){ + try { + Response response = evt.getResponse(); + int statusCode = response.getStatusCode(); + // trying涓嶄細鍥炲 + if (statusCode == Response.TRYING) { + } + // 鎴愬姛鍝嶅簲 + // 涓嬪彂ack + if (statusCode == Response.OK) { + ResponseEventExt event = (ResponseEventExt)evt; + SIPDialog dialog = (SIPDialog)evt.getDialog(); + CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); + Request reqAck = dialog.createAck(cseq.getSeqNumber()); + SipURI requestURI = (SipURI) reqAck.getRequestURI(); + try { + requestURI.setHost(event.getRemoteIpAddress()); + } catch (ParseException e) { + e.printStackTrace(); + } + requestURI.setPort(event.getRemotePort()); + reqAck.setRequestURI(requestURI); + logger.info("鍚� " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "鍥炲ack"); + SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI(); + String deviceId = requestURI.getUser(); + String channelId = sipURI.getUser(); + + dialog.sendAck(reqAck); + + } + } catch (InvalidArgumentException | SipException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java new file mode 100644 index 0000000..a5dced3 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java @@ -0,0 +1,104 @@ +package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; + +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.ResponseEvent; +import javax.sip.header.CallIdHeader; +import javax.sip.header.WWWAuthenticateHeader; +import javax.sip.message.Response; + +/** + * @description:Register鍝嶅簲澶勭悊鍣� + * @author: swwheihei + * @date: 2020骞�5鏈�3鏃� 涓嬪崍5:32:23 + */ +@Component +public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { + + private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class); + private String method = "REGISTER"; + + @Autowired + private ISIPCommanderForPlatform sipCommanderForPlatform; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Override + public void afterPropertiesSet() throws Exception { + // 娣诲姞娑堟伅澶勭悊鐨勮闃� + sipProcessorObserver.addResponseProcessor(method, this); + } + + /** + * 澶勭悊Register鍝嶅簲 + * + * @param evt 浜嬩欢 + */ + @Override + public void process(ResponseEvent evt) { + Response response = evt.getResponse(); + CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME); + String callId = callIdHeader.getCallId(); + + String platformGBId = redisCatchStorage.queryPlatformRegisterInfo(callId); + if (platformGBId == null) { + logger.info(String.format("鏈壘鍒癱allId锛� %s 鐨勬敞鍐�/娉ㄩ攢骞冲彴id", callId )); + return; + } + + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId); + if (parentPlatformCatch == null) { + logger.warn(String.format("鏀跺埌 %s 鐨勬敞鍐�/娉ㄩ攢%S璇锋眰, 浣嗘槸骞冲彴缂撳瓨淇℃伅鏈煡璇㈠埌!!!", platformGBId, response.getStatusCode())); + return; + } + String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "娉ㄩ攢" : "娉ㄥ唽"; + logger.info(String.format("鏀跺埌 %s %s鐨�%S鍝嶅簲", platformGBId, action, response.getStatusCode() )); + ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform(); + if (parentPlatform == null) { + logger.warn(String.format("鏀跺埌 %s %s鐨�%S璇锋眰, 浣嗘槸骞冲彴淇℃伅鏈煡璇㈠埌!!!", platformGBId, action, response.getStatusCode())); + return; + } + + if (response.getStatusCode() == 401) { + WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); + sipCommanderForPlatform.register(parentPlatform, callId, www, null, null); + }else if (response.getStatusCode() == 200){ + // 娉ㄥ唽/娉ㄩ攢鎴愬姛 + logger.info(String.format("%s %s鎴愬姛", platformGBId, action)); + redisCatchStorage.delPlatformRegisterInfo(callId); + parentPlatform.setStatus("娉ㄥ唽".equals(action)); + // 鍙栧洖Expires璁剧疆锛岄伩鍏嶆敞閿�杩囩▼涓缃负0 + ParentPlatform parentPlatformTmp = storager.queryParentPlatByServerGBId(platformGBId); + String expires = parentPlatformTmp.getExpires(); + parentPlatform.setExpires(expires); + parentPlatform.setId(parentPlatformTmp.getId()); + storager.updateParentPlatformStatus(platformGBId, "娉ㄥ唽".equals(action)); + + redisCatchStorage.updatePlatformRegister(parentPlatform); + + redisCatchStorage.updatePlatformKeepalive(parentPlatform); + + parentPlatformCatch.setParentPlatform(parentPlatform); + + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); + } + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java new file mode 100644 index 0000000..0cb8413 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java @@ -0,0 +1,24 @@ +package com.genersoft.iot.vmp.service; + +import com.genersoft.iot.vmp.gb28181.bean.Device; + +/** + * 璁惧鐩稿叧涓氬姟澶勭悊 + */ +public interface IDeviceService { + + /** + * 娣诲姞鐩綍璁㈤槄 + * @param device 璁惧淇℃伅 + * @return + */ + boolean addCatalogSubscribe(Device device); + + /** + * 绉婚櫎鐩綍璁㈤槄 + * @param device 璁惧淇℃伅 + * @return + */ + boolean removeCatalogSubscribe(Device device); + +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java new file mode 100644 index 0000000..eb179d7 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java @@ -0,0 +1,48 @@ +package com.genersoft.iot.vmp.service.bean; + +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.sip.ResponseEvent; + +public class CatalogSubscribeTask implements Runnable{ + private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class); + private Device device; + private ISIPCommander sipCommander; + + public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) { + this.device = device; + this.sipCommander = sipCommander; + } + + @Override + public void run() { + sipCommander.catalogSubscribe(device, eventResult -> { + ResponseEvent event = (ResponseEvent) eventResult.event; + Element rootElement = null; + try { + rootElement = XmlUtil.getRootElement(event.getResponse().getRawContent(), "gb2312"); + } catch (DocumentException e) { + e.printStackTrace(); + } + Element resultElement = rootElement.element("Result"); + String result = resultElement.getText(); + if (result.toUpperCase().equals("OK")){ + // 鎴愬姛 + logger.info("鐩綍璁㈤槄鎴愬姛锛� {}", device.getDeviceId()); + }else { + // 澶辫触 + logger.info("鐩綍璁㈤槄澶辫触锛� {}-{}", device.getDeviceId(), result); + } + + },eventResult -> { + // 澶辫触 + logger.warn("鐩綍璁㈤槄澶辫触锛� {}-淇′护鍙戦�佸け璐�", device.getDeviceId()); + }); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java new file mode 100644 index 0000000..595f38c --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -0,0 +1,61 @@ +package com.genersoft.iot.vmp.service.impl; + +import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.service.IDeviceService; +import com.genersoft.iot.vmp.service.bean.CatalogSubscribeTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DeviceServiceImpl implements IDeviceService { + + private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class); + + @Autowired + private DynamicTask dynamicTask; +; + + @Autowired + private ISIPCommander sipCommander; + + @Override + public boolean addCatalogSubscribe(Device device) { + if (device == null || device.getSubscribeCycleForCatalog() < 0) { + return false; + } + // 娣诲姞鐩綍璁㈤槄 + CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander); + catalogSubscribeTask.run(); + // 鎻愬墠寮�濮嬪埛鏂拌闃� + String cron = getCron(device.getSubscribeCycleForCatalog() - 60); + dynamicTask.startCron(device.getDeviceId(), catalogSubscribeTask, cron); + return true; + } + + @Override + public boolean removeCatalogSubscribe(Device device) { + if (device == null || device.getSubscribeCycleForCatalog() < 0) { + return false; + } + dynamicTask.stopCron(device.getDeviceId()); + return true; + } + + public String getCron(int time) { + if (time <= 59) { + return "0/" + time +" * * * * ?"; + }else if (time <= 60* 59) { + int minute = time/(60); + return "0 0/" + minute +" * * * ?"; + }else if (time <= 60* 60* 59) { + int hour = time/(60*60); + return "0 0 0/" + hour +" * * ?"; + }else { + return "0 0/10 * * * ?"; + } + } +} -- Gitblit v1.8.0