Merge branch 'wvp-28181-2.0' into main-dev
# Conflicts:
# src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
# src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
# src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
| | |
| | | <version>2.1.3</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.google.guava</groupId> |
| | | <artifactId>guava</artifactId> |
| | | <version>20.0</version> |
| | | </dependency> |
| | | |
| | | <!-- jsonè§£æåºfastjson2 --> |
| | | <dependency> |
| | | <groupId>com.alibaba.fastjson2</groupId> |
| | |
| | | alter table wvp_device_channel |
| | | change stream_id stream_id varying(255) |
| | | change stream_id stream_id varying(255) |
| | | |
| | | alter table wvp_platform |
| | | add auto_push_channel bool default false |
| | | |
| | | alter table wvp_stream_proxy |
| | | add stream_key varying(255) |
| | |
| | | create_time character varying(50), |
| | | update_time character varying(50), |
| | | as_message_channel bool default false, |
| | | auto_push_channel bool default false, |
| | | constraint uk_platform_unique_server_gb_id unique (server_gb_id) |
| | | ); |
| | | |
| | |
| | | create_time character varying(50), |
| | | name character varying(255), |
| | | update_time character varying(50), |
| | | stream_key character varying(255), |
| | | enable_disable_none_reader bool default false, |
| | | constraint uk_stream_proxy_app_stream unique (app, stream) |
| | | ); |
| | |
| | | @Schema(description = "æ¯å¦ä½ä¸ºæ¶æ¯éé") |
| | | private boolean asMessageChannel; |
| | | |
| | | @Schema(description = "æ¯å¦ä½ä¸ºæ¶æ¯éé") |
| | | private boolean autoPushChannel; |
| | | |
| | | public Integer getId() { |
| | | return id; |
| | | } |
| | |
| | | public void setAsMessageChannel(boolean asMessageChannel) { |
| | | this.asMessageChannel = asMessageChannel; |
| | | } |
| | | |
| | | public boolean isAutoPushChannel() { |
| | | return autoPushChannel; |
| | | } |
| | | |
| | | public void setAutoPushChannel(boolean autoPushChannel) { |
| | | this.autoPushChannel = autoPushChannel; |
| | | } |
| | | } |
| | |
| | | |
| | | public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) { |
| | | catalogMap.put(platformId, subscribeInfo); |
| | | // æ·»å 订é
å°æ |
| | | String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; |
| | | // æ·»å ä»»å¡å¤ç订é
è¿æ |
| | | dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()), |
| | | subscribeInfo.getExpires() * 1000); |
| | | if (subscribeInfo.getExpires() > 0) { |
| | | // æ·»å 订é
å°æ |
| | | String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId; |
| | | // æ·»å ä»»å¡å¤ç订é
è¿æ |
| | | dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()), |
| | | subscribeInfo.getExpires() * 1000); |
| | | } |
| | | } |
| | | |
| | | public SubscribeInfo getCatalogSubscribe(String platformId) { |
| | |
| | | dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId), |
| | | subscribeInfo.getGpsInterval() * 1000); |
| | | String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; |
| | | // æ·»å ä»»å¡å¤ç订é
è¿æ |
| | | dynamicTask.startDelay(taskOverdueKey, () -> { |
| | | removeMobilePositionSubscribe(subscribeInfo.getId()); |
| | | }, |
| | | subscribeInfo.getExpires() * 1000); |
| | | if (subscribeInfo.getExpires() > 0) { |
| | | // æ·»å ä»»å¡å¤ç订é
è¿æ |
| | | dynamicTask.startDelay(taskOverdueKey, () -> { |
| | | removeMobilePositionSubscribe(subscribeInfo.getId()); |
| | | }, |
| | | subscribeInfo.getExpires() * 1000); |
| | | } |
| | | } |
| | | |
| | | public SubscribeInfo getMobilePositionSubscribe(String platformId) { |
| | |
| | | |
| | | } |
| | | |
| | | public SubscribeInfo() { |
| | | } |
| | | |
| | | private String id; |
| | | |
| | | private SIPRequest request; |
| | |
| | | */ |
| | | private String sn; |
| | | private int gpsInterval; |
| | | |
| | | /** |
| | | * 模æçFromTag |
| | | */ |
| | | private String simulatedFromTag; |
| | | |
| | | /** |
| | | * 模æçToTag |
| | | */ |
| | | private String simulatedToTag; |
| | | |
| | | /** |
| | | * 模æçCallID |
| | | */ |
| | | private String simulatedCallId; |
| | | |
| | | public String getId() { |
| | | return id; |
| | |
| | | public void setGpsInterval(int gpsInterval) { |
| | | this.gpsInterval = gpsInterval; |
| | | } |
| | | |
| | | public String getSimulatedFromTag() { |
| | | return simulatedFromTag; |
| | | } |
| | | |
| | | public void setSimulatedFromTag(String simulatedFromTag) { |
| | | this.simulatedFromTag = simulatedFromTag; |
| | | } |
| | | |
| | | public String getSimulatedCallId() { |
| | | return simulatedCallId; |
| | | } |
| | | |
| | | public void setSimulatedCallId(String simulatedCallId) { |
| | | this.simulatedCallId = simulatedCallId; |
| | | } |
| | | |
| | | public String getSimulatedToTag() { |
| | | return simulatedToTag; |
| | | } |
| | | |
| | | public void setSimulatedToTag(String simulatedToTag) { |
| | | this.simulatedToTag = simulatedToTag; |
| | | } |
| | | } |
| | |
| | | } |
| | | if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ |
| | | for (GbStream gbStream : event.getGbStreams()) { |
| | | if (gbStream.getStreamType().equals("push") && !userSetting.isUsePushingAsStatus()) { |
| | | if (gbStream != null |
| | | && gbStream.getStreamType() != null |
| | | && gbStream.getStreamType().equals("push") |
| | | && !userSetting.isUsePushingAsStatus()) { |
| | | continue; |
| | | } |
| | | DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform); |
| | |
| | | SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), |
| | | parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); |
| | | Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); |
| | | FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag()); |
| | | FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse() != null ? subscribeInfo.getResponse().getToTag(): subscribeInfo.getSimulatedToTag()); |
| | | // to |
| | | SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); |
| | | Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); |
| | | ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag()); |
| | | ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest() != null ?subscribeInfo.getRequest().getFromTag(): subscribeInfo.getSimulatedFromTag()); |
| | | |
| | | // Forwards |
| | | MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); |
| | |
| | | // 设置ç¼ç ï¼ é²æ¢ä¸æä¹±ç |
| | | messageFactory.setDefaultContentEncodingCharset("gb2312"); |
| | | |
| | | CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId()); |
| | | CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest() != null ? subscribeInfo.getRequest().getCallIdHeader().getCallId(): subscribeInfo.getSimulatedCallId()); |
| | | |
| | | request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, |
| | | toHeader, viaHeaders, maxForwards); |
| | |
| | | |
| | | CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport()); |
| | | |
| | | Request request = headerProviderPlatformProvider.createMessageRequest( |
| | | parentPlatform, |
| | | keepaliveXml.toString(), |
| | | SipUtils.getNewFromTag(), |
| | | SipUtils.getNewViaTag(), |
| | | callIdHeader); |
| | | sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent); |
| | | Request request = headerProviderPlatformProvider.createMessageRequest( |
| | | parentPlatform, |
| | | keepaliveXml.toString(), |
| | | SipUtils.getNewFromTag(), |
| | | SipUtils.getNewViaTag(), |
| | | callIdHeader); |
| | | sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent); |
| | | return callIdHeader.getCallId(); |
| | | } |
| | | |
| | |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| | | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| | | import com.google.common.primitives.Bytes; |
| | | import gov.nist.javax.sip.message.SIPRequest; |
| | | import gov.nist.javax.sip.message.SIPResponse; |
| | | import org.apache.commons.lang3.ArrayUtils; |
| | |
| | | result.add(rawContent[i]); |
| | | } |
| | | } |
| | | Byte[] bytes = new Byte[0]; |
| | | byte[] bytesResult = ArrayUtils.toPrimitive(result.toArray(bytes)); |
| | | byte[] bytesResult = Bytes.toArray(result); |
| | | |
| | | Document xml; |
| | | try { |
| | | xml = reader.read(new ByteArrayInputStream(bytesResult)); |
| | | }catch (DocumentException e) { |
| | | logger.warn("[xmlè§£æå¼å¸¸]ï¼ æ¿æå¦ä¸ï¼ \r\n{}", new String(bytesResult)); |
| | | logger.warn("[xmlè§£æå¼å¸¸]ï¼ æ¿æå¦ä¸ï¼ å°è¯å
¼å®¹æ§å¤ç"); |
| | | logger.warn("[xmlè§£æå¼å¸¸]ï¼ åæå¦ä¸ï¼ \r\n{}", new String(bytesResult)); |
| | | logger.warn("[xmlè§£æå¼å¸¸]ï¼ åæå¦ä¸ï¼ å°è¯å
¼å®¹æ§å¤ç"); |
| | | String[] xmlLineArray = new String(bytesResult).split("\\r?\\n"); |
| | | |
| | | // å
¼å®¹æµ·åº·çaddressåæ®µå¸¦æ<ç ´æ¢xmlç»æå¯¼è´æ æ³è§£æxmlçé®é¢ |
| | |
| | | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| | | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| | | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
| | | import com.genersoft.iot.vmp.service.IPlatformService; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| | | import gov.nist.javax.sip.message.SIPRequest; |
| | | import gov.nist.javax.sip.message.SIPResponse; |
| | |
| | | |
| | | @Autowired |
| | | private SIPSender sipSender; |
| | | |
| | | |
| | | @Autowired |
| | | private IPlatformService platformService; |
| | | |
| | | @Override |
| | | public void afterPropertiesSet() throws Exception { |
| | |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("æªå¤ççå¼å¸¸ ", e); |
| | | } |
| | | if (subscribeHolder.getCatalogSubscribe(platformId) == null && platform.isAutoPushChannel()) { |
| | | platformService.addSimulatedSubscribeInfo(platform); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | taskExecutor.execute(()->{ |
| | | try { |
| | | |
| | | String sn = getText(rootElement, "SN"); |
| | | String channelId = getText(rootElement, "DeviceID"); |
| | | RecordInfo recordInfo = new RecordInfo(); |
| | |
| | | }
|
| | | // æ¨æµé´æçå¤ç
|
| | | if (!"rtp".equals(param.getApp())) {
|
| | | StreamProxyItem stream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
|
| | | if (stream != null) {
|
| | | HookResultForOnPublish result = HookResultForOnPublish.SUCCESS();
|
| | | result.setEnable_audio(stream.isEnableAudio());
|
| | | result.setEnable_mp4(stream.isEnableMp4());
|
| | | return result;
|
| | | }
|
| | | if (userSetting.getPushAuthority()) {
|
| | | // æ¨æµé´æ
|
| | | if (param.getParams() == null) {
|
| | |
| | | } |
| | | |
| | | private OkHttpClient getClient(){ |
| | | return getClient(null); |
| | | } |
| | | |
| | | private OkHttpClient getClient(Integer readTimeOut){ |
| | | if (client == null) { |
| | | if (readTimeOut == null) { |
| | | readTimeOut = 10; |
| | | } |
| | | OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); |
| | | //todo ææ¶åæ»è¶
æ¶æ¶é´ å为5s |
| | | // è®¾ç½®è¿æ¥è¶
æ¶æ¶é´ |
| | | httpClientBuilder.connectTimeout(5,TimeUnit.SECONDS); |
| | | httpClientBuilder.connectTimeout(8,TimeUnit.SECONDS); |
| | | // 设置读åè¶
æ¶æ¶é´ |
| | | httpClientBuilder.readTimeout(10,TimeUnit.SECONDS); |
| | | httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS); |
| | | // è®¾ç½®è¿æ¥æ± |
| | | httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES)); |
| | | if (logger.isDebugEnabled()) { |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { |
| | | OkHttpClient client = getClient(); |
| | | return sendPost(mediaServerItem, api, param, callback, null); |
| | | } |
| | | |
| | | |
| | | public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback, Integer readTimeOut) { |
| | | OkHttpClient client = getClient(readTimeOut); |
| | | |
| | | if (mediaServerItem == null) { |
| | | return null; |
| | |
| | | return sendPost(mediaServerItem, "delFFmpegSource",param, null); |
| | | } |
| | | |
| | | public JSONObject delStreamProxy(MediaServerItem mediaServerItem, String key){ |
| | | Map<String, Object> param = new HashMap<>(); |
| | | param.put("key", key); |
| | | return sendPost(mediaServerItem, "delStreamProxy",param, null); |
| | | } |
| | | |
| | | public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){ |
| | | return sendPost(mediaServerItem, "getServerConfig",null, null); |
| | | } |
| | |
| | | param.put("enable_mp4", enable_mp4?1:0); |
| | | param.put("enable_audio", enable_audio?1:0); |
| | | param.put("rtp_type", rtp_type); |
| | | return sendPost(mediaServerItem, "addStreamProxy",param, null); |
| | | return sendPost(mediaServerItem, "addStreamProxy",param, null, 20); |
| | | } |
| | | |
| | | public JSONObject closeStreams(MediaServerItem mediaServerItem, String app, String stream) { |
| | |
| | | @Schema(description = "æ¯å¦ æ 人è§çæ¶èªå¨åç¨") |
| | | private boolean enableDisableNoneReader; |
| | | |
| | | @Schema(description = "ææµä»£çæ¶zlmè¿åçkeyï¼ç¨äºåæ¢ææµä»£ç") |
| | | private String streamKey; |
| | | |
| | | public String getType() { |
| | | return type; |
| | | } |
| | |
| | | this.enableAudio = enable_audio; |
| | | } |
| | | |
| | | public String getStreamKey() { |
| | | return streamKey; |
| | | } |
| | | |
| | | public void setStreamKey(String streamKey) { |
| | | this.streamKey = streamKey; |
| | | } |
| | | } |
| | |
| | | * @param catalogId |
| | | */ |
| | | void delAllPlatformInfo(String platformId, String catalogId); |
| | | |
| | | List<GbStream> getGbChannelWithGbid(String gbId); |
| | | } |
| | |
| | | * è¯é³åè¯åå¤BYE |
| | | */ |
| | | void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream,boolean sendBye, MediaServerItem mediaServerItem); |
| | | |
| | | void addSimulatedSubscribeInfo(ParentPlatform parentPlatform); |
| | | } |
| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.TransactionDefinition; |
| | | import org.springframework.transaction.TransactionStatus; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.ObjectUtils; |
| | | |
| | | import java.util.ArrayList; |
| | |
| | | eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.DEL); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<GbStream> getGbChannelWithGbid(String gbId) { |
| | | return gbStreamMapper.selectByGBId(gbId); |
| | | } |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| | | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; |
| | |
| | | import com.genersoft.iot.vmp.utils.DateUtil; |
| | | import com.github.pagehelper.PageHelper; |
| | | import com.github.pagehelper.PageInfo; |
| | | import gov.nist.javax.sip.message.SIPRequest; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | import javax.sip.InvalidArgumentException; |
| | | import javax.sip.ResponseEvent; |
| | | import javax.sip.PeerUnavailableException; |
| | | import javax.sip.SipException; |
| | | import javax.sip.SipFactory; |
| | | import javax.sip.address.Address; |
| | | import javax.sip.address.SipURI; |
| | | import javax.sip.header.*; |
| | | import javax.sip.message.Request; |
| | | import java.text.ParseException; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.UUID; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * @author lin |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | return false; |
| | | } |
| | | |
| | |
| | | try { |
| | | commanderForPlatform.keepalive(parentPlatform, eventResult -> { |
| | | // å¿è·³å¤±è´¥ |
| | | if (eventResult.type == SipSubscribe.EventResultType.timeout) { |
| | | // å¿è·³è¶
æ¶ |
| | | ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); |
| | | // æ¤æ¶æ¯ç¬¬ä¸æ¬¡å¿è·³è¶
æ¶ï¼ å¹³å°ç¦»çº¿ |
| | | if (platformCatch.getKeepAliveReply() == 2) { |
| | | // 设置平å°ç¦»çº¿ï¼å¹¶éæ°æ³¨å |
| | | logger.info("[彿 级è] 䏿¬¡å¿è·³è¶
æ¶, å¹³å°{}({})离线", parentPlatform.getName(), parentPlatform.getServerGBId()); |
| | | offline(parentPlatform, false); |
| | | } |
| | | |
| | | }else { |
| | | if (eventResult.type != SipSubscribe.EventResultType.timeout) { |
| | | logger.warn("[彿 级è]åéå¿è·³æ¶å°é误ï¼codeï¼ {}, msg: {}", eventResult.statusCode, eventResult.msg); |
| | | } |
| | | // å¿è·³å¤±è´¥ |
| | | ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); |
| | | // æ¤æ¶æ¯ç¬¬ä¸æ¬¡å¿è·³è¶
æ¶ï¼ å¹³å°ç¦»çº¿ |
| | | if (platformCatch.getKeepAliveReply() == 2) { |
| | | // 设置平å°ç¦»çº¿ï¼å¹¶éæ°æ³¨å |
| | | logger.info("[彿 级è] 䏿¬¡å¿è·³å¤±è´¥, å¹³å°{}({})离线", parentPlatform.getName(), parentPlatform.getServerGBId()); |
| | | offline(parentPlatform, false); |
| | | }else { |
| | | platformCatch.setKeepAliveReply(platformCatch.getKeepAliveReply() + 1); |
| | | redisCatchStorage.updatePlatformCatchInfo(platformCatch); |
| | | } |
| | | |
| | | }, eventResult -> { |
| | |
| | | }, |
| | | (parentPlatform.getKeepTimeout())*1000); |
| | | } |
| | | if (parentPlatform.isAutoPushChannel()) { |
| | | if (subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId()) == null) { |
| | | addSimulatedSubscribeInfo(parentPlatform); |
| | | } |
| | | }else { |
| | | SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId()); |
| | | if (catalogSubscribe != null && catalogSubscribe.getExpires() == -1) { |
| | | subscribeHolder.removeCatalogSubscribe(parentPlatform.getServerGBId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void addSimulatedSubscribeInfo(ParentPlatform parentPlatform) { |
| | | // èªå¨æ·»å 䏿¡æ¨¡æç订é
ä¿¡æ¯ |
| | | SubscribeInfo subscribeInfo = new SubscribeInfo(); |
| | | subscribeInfo.setId(parentPlatform.getServerGBId()); |
| | | subscribeInfo.setExpires(-1); |
| | | subscribeInfo.setEventType("Catalog"); |
| | | int random = (int) Math.floor(Math.random() * 10000); |
| | | subscribeInfo.setEventId(random + ""); |
| | | subscribeInfo.setSimulatedCallId(UUID.randomUUID().toString().replace("-", "") + "@" + parentPlatform.getServerIP()); |
| | | subscribeInfo.setSimulatedFromTag(UUID.randomUUID().toString().replace("-", "")); |
| | | subscribeInfo.setSimulatedToTag(UUID.randomUUID().toString().replace("-", "")); |
| | | subscribeHolder.putCatalogSubscribe(parentPlatform.getServerGBId(), subscribeInfo); |
| | | } |
| | | |
| | | private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){ |
| | |
| | | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| | | import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; |
| | |
| | | |
| | | @Autowired |
| | | private ZLMRESTfulUtils zlmresTfulUtils; |
| | | |
| | | @Autowired |
| | | private ZLMServerFactory zlmServerFactory; |
| | | |
| | | @Autowired |
| | | private StreamProxyMapper streamProxyMapper; |
| | |
| | | dstUrl = String.format("%s://%s:%s/%s/%s", schemaForUri, "127.0.0.1", port, param.getApp(), |
| | | param.getStream()); |
| | | }else { |
| | | dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(), |
| | | dstUrl = String.format("rtsp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtspPort(), param.getApp(), |
| | | param.getStream()); |
| | | } |
| | | param.setDstUrl(dstUrl); |
| | |
| | | callback.run(ErrorCode.ERROR100.getCode(), "ä¿å失败", null); |
| | | return; |
| | | } |
| | | |
| | | HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(param.getApp(), param.getStream(), true, "rtsp", mediaInfo.getId()); |
| | | hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItem, response) -> { |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( |
| | | mediaInfo, param.getApp(), param.getStream(), null, null); |
| | | callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); |
| | | }); |
| | | if (param.isEnable()) { |
| | | String talkKey = UUID.randomUUID().toString(); |
| | | dynamicTask.startCron(talkKey, ()->{ |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); |
| | | if (streamInfo != null) { |
| | | callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); |
| | | } |
| | | }, 1000); |
| | | String delayTalkKey = UUID.randomUUID().toString(); |
| | | dynamicTask.startDelay(delayTalkKey, ()->{ |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); |
| | |
| | | dynamicTask.stop(talkKey); |
| | | callback.run(ErrorCode.ERROR100.getCode(), "è¶
æ¶", null); |
| | | } |
| | | }, 5000); |
| | | }, 7000); |
| | | JSONObject jsonObject = addStreamProxyToZlm(param); |
| | | if (jsonObject != null && jsonObject.getInteger("code") == 0) { |
| | | hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); |
| | | dynamicTask.stop(talkKey); |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( |
| | | mediaInfo, param.getApp(), param.getStream(), null, null); |
| | |
| | | if (mediaServerItem == null) { |
| | | return null; |
| | | } |
| | | if ("default".equals(param.getType())){ |
| | | result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl().trim(), |
| | | param.isEnableAudio(), param.isEnableMp4(), param.getRtpType()); |
| | | }else if ("ffmpeg".equals(param.getType())) { |
| | | if (zlmServerFactory.isStreamReady(mediaServerItem, param.getApp(), param.getStream())) { |
| | | zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream()); |
| | | } |
| | | if ("ffmpeg".equalsIgnoreCase(param.getType())){ |
| | | result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrcUrl().trim(), param.getDstUrl(), |
| | | param.getTimeoutMs() + "", param.isEnableAudio(), param.isEnableMp4(), |
| | | param.getFfmpegCmdKey()); |
| | | }else { |
| | | result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl().trim(), |
| | | param.isEnableAudio(), param.isEnableMp4(), param.getRtpType()); |
| | | } |
| | | System.out.println("addStreamProxyToZlm===="); |
| | | System.out.println(result); |
| | | if (result != null && result.getInteger("code") == 0) { |
| | | JSONObject data = result.getJSONObject("data"); |
| | | if (data == null) { |
| | | logger.warn("[è·åææµä»£ççç»ææ°æ®Data] å¤±è´¥ï¼ {}", result ); |
| | | return result; |
| | | } |
| | | String key = data.getString("key"); |
| | | if (key == null) { |
| | | logger.warn("[è·åææµä»£ççç»ææ°æ®Dataä¸çKEY] å¤±è´¥ï¼ {}", result ); |
| | | return result; |
| | | } |
| | | param.setStreamKey(key); |
| | | streamProxyMapper.update(param); |
| | | } |
| | | return result; |
| | | } |
| | |
| | | return null; |
| | | } |
| | | MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); |
| | | JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream()); |
| | | JSONObject result = null; |
| | | if ("ffmpeg".equalsIgnoreCase(param.getType())){ |
| | | result = zlmresTfulUtils.delFFmpegSource(mediaServerItem, param.getStreamKey()); |
| | | }else { |
| | | result = zlmresTfulUtils.delStreamProxy(mediaServerItem, param.getStreamKey()); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | |
| | | StreamProxyItem streamProxyItem = videoManagerStorager.queryStreamProxy(app, stream); |
| | | if (streamProxyItem != null) { |
| | | gbStreamService.sendCatalogMsg(streamProxyItem, CatalogEvent.DEL); |
| | | |
| | | // 妿å
³èäºå½æ é£ä¹ç§»é¤å
³è |
| | | platformGbStreamMapper.delByAppAndStream(app, stream); |
| | | gbStreamMapper.del(app, stream); |
| | | videoManagerStorager.deleteStreamProxy(app, stream); |
| | | redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PULL", app, stream); |
| | | JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyItem); |
| | | if (jsonObject != null && jsonObject.getInteger("code") == 0) { |
| | | // 妿å
³èäºå½æ é£ä¹ç§»é¤å
³è |
| | | gbStreamMapper.del(app, stream); |
| | | platformGbStreamMapper.delByAppAndStream(app, stream); |
| | | // TODO 妿å
³èçæ¨æµï¼ é£ä¹ç¶æè®¾ç½®ä¸ºç¦»çº¿ |
| | | logger.info("[ç§»é¤ä»£ç]ï¼ ä»£çï¼ {}/{}, ä»zlmç§»é¤æå", app, stream); |
| | | }else { |
| | | logger.info("[ç§»é¤ä»£ç]ï¼ ä»£çï¼ {}/{}, ä»zlmç§»é¤å¤±è´¥", app, stream); |
| | | } |
| | | redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PULL", app, stream); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | } |
| | | } |
| | | if (streamPushItemListFroPlatform.size() > 0) { |
| | | if (!streamPushItemListFroPlatform.isEmpty()) { |
| | | platformGbStreamMapper.batchAdd(streamPushItemListFroPlatform); |
| | | // åééç¥ |
| | | for (String platformId : platformForEvent.keySet()) { |
| | |
| | | " <if test='query != null'> AND (dc.channel_id LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%'))</if> " + |
| | | " <if test='online == true' > AND dc.status=true</if> " + |
| | | " <if test='online == false' > AND dc.status=false</if> " + |
| | | " <if test='hasSubChannel!= null and has_sub_channel == true' > AND dc.sub_count > 0</if> " + |
| | | " <if test='hasSubChannel!= null and has_sub_channel == false' > AND dc.sub_count = 0</if> " + |
| | | " <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc.sub_count > 0</if> " + |
| | | " <if test='hasSubChannel!= null and hasSubChannel == false' > AND dc.sub_count = 0</if> " + |
| | | " <if test='catalogId == null ' > AND dc.id not in (select device_channel_id from wvp_platform_gb_channel where platform_id=#{platformId} ) </if> " + |
| | | " <if test='catalogId != null ' > AND pgc.platform_id = #{platformId} and pgc.catalog_id=#{catalogId} </if> " + |
| | | " ORDER BY dc.device_id, dc.channel_id ASC" + |
| | |
| | | public interface ParentPlatformMapper { |
| | | |
| | | @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+ |
| | | "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,"+ |
| | | "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,auto_push_channel,"+ |
| | | "status,start_offline_push,catalog_id,administrative_division,catalog_group,create_time,update_time) " + |
| | | " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + |
| | | " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " + |
| | | " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, #{autoPushChannel}, " + |
| | | " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})") |
| | | int addParentPlatform(ParentPlatform parentPlatform); |
| | | |
| | |
| | | "ptz=#{ptz}, " + |
| | | "rtcp=#{rtcp}, " + |
| | | "as_message_channel=#{asMessageChannel}, " + |
| | | "auto_push_channel=#{autoPushChannel}, " + |
| | | "status=#{status}, " + |
| | | "start_offline_push=#{startOfflinePush}, " + |
| | | "catalog_group=#{catalogGroup}, " + |
| | |
| | | public interface StreamProxyMapper { |
| | | |
| | | @Insert("INSERT INTO wvp_stream_proxy (type, name, app, stream,media_server_id, url, src_url, dst_url, " + |
| | | "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_audio, enable_mp4, enable, status, enable_remove_none_reader, enable_disable_none_reader, create_time) VALUES" + |
| | | "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_audio, enable_mp4, enable, status, stream_key, enable_remove_none_reader, enable_disable_none_reader, create_time) VALUES" + |
| | | "(#{type}, #{name}, #{app}, #{stream}, #{mediaServerId}, #{url}, #{srcUrl}, #{dstUrl}, " + |
| | | "#{timeoutMs}, #{ffmpegCmdKey}, #{rtpType}, #{enableAudio}, #{enableMp4}, #{enable}, #{status}, " + |
| | | "#{timeoutMs}, #{ffmpegCmdKey}, #{rtpType}, #{enableAudio}, #{enableMp4}, #{enable}, #{status}, #{streamKey}, " + |
| | | "#{enableRemoveNoneReader}, #{enableDisableNoneReader}, #{createTime} )") |
| | | int add(StreamProxyItem streamProxyDto); |
| | | |
| | |
| | | "enable_audio=#{enableAudio}, " + |
| | | "enable=#{enable}, " + |
| | | "status=#{status}, " + |
| | | "stream_key=#{streamKey}, " + |
| | | "enable_remove_none_reader=#{enableRemoveNoneReader}, " + |
| | | "enable_disable_none_reader=#{enableDisableNoneReader}, " + |
| | | "enable_mp4=#{enableMp4} " + |
| | |
| | | @Select("SELECT st.*, pgs.gb_id, pgs.name, pgs.longitude, pgs.latitude FROM wvp_stream_proxy st LEFT join wvp_gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream order by st.create_time desc") |
| | | List<StreamProxyItem> selectAll(); |
| | | |
| | | @Select("SELECT st.*, pgs.gb_id, pgs.name, pgs.longitude, pgs.latitude FROM wvp_stream_proxy st LEFT join wvp_gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=#{enable} order by st.create_time desc") |
| | | @Select("SELECT st.*, pgs.gb_id, pgs.name, pgs.longitude, pgs.latitude, 'proxy' as streamType FROM wvp_stream_proxy st LEFT join wvp_gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=#{enable} order by st.create_time desc") |
| | | List<StreamProxyItem> selectForEnable(boolean enable); |
| | | |
| | | @Select("SELECT st.*, pgs.gb_id, pgs.name, pgs.longitude, pgs.latitude FROM wvp_stream_proxy st LEFT join wvp_gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.app=#{app} AND st.stream=#{stream} order by st.create_time desc") |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.context.request.async.DeferredResult; |
| | | |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import javax.sip.InvalidArgumentException; |
| | | import javax.sip.SipException; |
| | |
| | | try { |
| | | final InputStream in = Files.newInputStream(new File("snap" + File.separator + deviceId + "_" + channelId + (mark == null? ".jpg": ("_" + mark + ".jpg"))).toPath()); |
| | | resp.setContentType(MediaType.IMAGE_PNG_VALUE); |
| | | ServletOutputStream outputStream = resp.getOutputStream(); |
| | | IOUtils.copy(in, resp.getOutputStream()); |
| | | in.close(); |
| | | outputStream.close(); |
| | | } catch (IOException e) { |
| | | resp.setStatus(HttpServletResponse.SC_NOT_FOUND); |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.vmanager.gb28181.gbStream; |
| | | |
| | | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| | | import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.service.IGbStreamService; |
| | | import com.genersoft.iot.vmp.service.IPlatformService; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| | | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| | | import com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean.GbStreamParam; |
| | | import com.github.pagehelper.PageInfo; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | import org.springframework.util.ObjectUtils; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @Tag(name = "è§é¢æµå
³èå°çº§èå¹³å°") |
| | |
| | | private IGbStreamService gbStreamService; |
| | | |
| | | @Autowired |
| | | private IVideoManagerStorage storager; |
| | | private IPlatformService platformService; |
| | | |
| | | |
| | | /** |
| | |
| | | gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * ä¿å彿 å
³è |
| | | * @param gbId |
| | | * @return |
| | | */ |
| | | @Operation(summary = "ä¿å彿 å
³è") |
| | | @GetMapping(value = "/addWithGbid") |
| | | @ResponseBody |
| | | public void add(String gbId, String platformGbId, @RequestParam(required = false) String catalogGbId){ |
| | | List<GbStream> gbStreams = gbStreamService.getGbChannelWithGbid(gbId); |
| | | if (gbStreams.isEmpty()) { |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "gbIdçä¿¡æ¯æªæ¾å°"); |
| | | } |
| | | gbStreamService.addPlatformInfo(gbStreams, platformGbId, catalogGbId); |
| | | } |
| | | } |
| | |
| | | return streamProxyService.getAll(page, count); |
| | | } |
| | | |
| | | @Operation(summary = "æ¥è¯¢æµä»£ç") |
| | | @Parameter(name = "app", description = "åºç¨å") |
| | | @Parameter(name = "stream", description = "æµId") |
| | | @GetMapping(value = "/one") |
| | | @ResponseBody |
| | | public StreamProxyItem one(String app, String stream){ |
| | | |
| | | return streamProxyService.getStreamProxyByAppAndStream(app, stream); |
| | | } |
| | | |
| | | @Operation(summary = "ä¿å代ç", parameters = { |
| | | @Parameter(name = "param", description = "代çåæ°", required = true), |
| | | }) |
| | |
| | | if (ObjectUtils.isEmpty(param.getType())) { |
| | | param.setType("default"); |
| | | } |
| | | if (ObjectUtils.isEmpty(param.getRtpType())) { |
| | | param.setRtpType("1"); |
| | | } |
| | | if (ObjectUtils.isEmpty(param.getGbId())) { |
| | | param.setGbId(null); |
| | | } |
| | | StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); |
| | | if (streamProxyItem != null) { |
| | | streamProxyService.del(param.getApp(), param.getStream()); |
| | | } |
| | | |
| | | RequestMessage requestMessage = new RequestMessage(); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_PROXY + param.getApp() + param.getStream(); |
| | |
| | | <el-form-item label="å
¶ä»é项"> |
| | | <el-checkbox label="å¯ç¨" v-model="platform.enable" @change="checkExpires"></el-checkbox> |
| | | <!-- <el-checkbox label="äºå°æ§å¶" v-model="platform.ptz"></el-checkbox>--> |
| | | <el-checkbox label="æèµ·ç¦»çº¿æ¨æµ" v-model="platform.startOfflinePush"></el-checkbox> |
| | | <el-checkbox label="æèµ·æ¨æµ" v-model="platform.startOfflinePush"></el-checkbox> |
| | | <el-checkbox label="RTCPä¿æ´»" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox> |
| | | <el-checkbox label="ä½ä¸ºæ¶æ¯éé" v-model="platform.asMessageChannel" ></el-checkbox> |
| | | <el-checkbox label="æ¶æ¯éé" v-model="platform.asMessageChannel" ></el-checkbox> |
| | | <el-checkbox label="æ¨ééé" v-model="platform.autoPushChannel" ></el-checkbox> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onSubmit">{{ |
| | |
| | | ptz: true, |
| | | rtcp: false, |
| | | asMessageChannel: false, |
| | | autoPushChannel: false, |
| | | name: null, |
| | | serverGBId: null, |
| | | serverGBDomain: null, |
| | |
| | | this.platform.ptz = platform.ptz; |
| | | this.platform.rtcp = platform.rtcp; |
| | | this.platform.asMessageChannel = platform.asMessageChannel; |
| | | this.platform.autoPushChannel = platform.autoPushChannel; |
| | | this.platform.name = platform.name; |
| | | this.platform.serverGBId = platform.serverGBId; |
| | | this.platform.serverGBDomain = platform.serverGBDomain; |
| | |
| | | ptz: true, |
| | | rtcp: false, |
| | | asMessageChannel: false, |
| | | autoPushChannel: false, |
| | | name: null, |
| | | serverGBId: null, |
| | | administrativeDivision: null, |