Browse Source

add gb 28181 zlm服务器连接

lifang 3 năm trước cách đây
mục cha
commit
b22c036501
31 tập tin đã thay đổi với 1931 bổ sung1448 xóa
  1. 10 10
      docker/dev-env/docker-compose.yml
  2. 8 2
      jetlinks-manager/media-manager/pom.xml
  3. 1 1
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/bean/SsrcConfig.java
  4. 215 0
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/config/MediaConfig.java
  5. 1 1
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/controller/ApiStreamController.java
  6. 3 3
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/AbstractSipProcessor.java
  7. 43 3
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/request/impl/InviteRequestProcessor.java
  8. 73 0
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/response/InviteResponseProcessor.java
  9. 4 6
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/response/RegisterResponseProcessor.java
  10. 597 0
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/service/LocalMediaServerItemServiceImpl.java
  11. 1 1
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/service/LocalPlayService.java
  12. 3 3
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/sip/SipRequestProcessorParent.java
  13. 2 2
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/sip/SipServerHelper.java
  14. 0 210
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/storage/IRedisCatchStorage.java
  15. 461 453
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/storage/impl/RedisCatchStorageImpl.java
  16. 10 17
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/transmit/SIPRequestHeaderProvider.java
  17. 1 5
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/transmit/cmd/SipCommander.java
  18. 140 179
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMHttpHookListener.java
  19. 31 19
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMHttpHookSubscribe.java
  20. 5 5
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMRESTfulUtils.java
  21. 18 18
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMRTPServerFactory.java
  22. 230 195
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMRunner.java
  23. 23 269
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/dto/MediaItem.java
  24. 11 8
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/entity/MediaServerItem.java
  25. 11 11
      jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/utils/RedisUtil.java
  26. 3 1
      jetlinks-standalone/pom.xml
  27. 4 1
      jetlinks-standalone/src/main/java/org/jetlinks/community/standalone/JetLinksApplication.java
  28. 3 1
      jetlinks-standalone/src/main/java/org/jetlinks/community/standalone/configuration/CroConfiguration.java
  29. 13 7
      jetlinks-standalone/src/main/resources/application.yml
  30. 5 17
      jetlinks-standalone/src/test/java/org/jetlinks/community/BridgeTest.java
  31. 1 0
      pom.xml

+ 10 - 10
docker/dev-env/docker-compose.yml

@@ -1,15 +1,15 @@
 version: '2'
 services:
-  redis:
-    image: redis:5.0.4
-    container_name: jetlinks-ce-redis
-    ports:
-      - "6379:6379"
-    volumes:
-      - "redis-volume:/data"
-    command: redis-server --appendonly yes
-    environment:
-      - TZ=Asia/Shanghai
+#  redis:
+#    image: redis:5.0.4
+#    container_name: jetlinks-ce-redis
+#    ports:
+#      - "6379:6379"
+#    volumes:
+#      - "redis-volume:/data"
+#    command: redis-server --appendonly yes
+#    environment:
+#      - TZ=Asia/Shanghai
   elasticsearch:
     image: elasticsearch:6.8.11
     container_name: jetlinks-ce-elasticsearch

+ 8 - 2
jetlinks-manager/media-manager/pom.xml

@@ -2,12 +2,13 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
     <parent>
-        <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
+        <artifactId>jetlinks-manager</artifactId>
         <version>1.10.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
     </parent>
-    <modelVersion>4.0.0</modelVersion>
 
     <artifactId>media-manager</artifactId>
 
@@ -34,6 +35,11 @@
             <version>${hsweb.framework.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>

+ 1 - 1
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/session/SsrcConfig.java → jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/bean/SsrcConfig.java

@@ -1,4 +1,4 @@
-package org.jetlinks.community.media.session;
+package org.jetlinks.community.media.bean;
 
 import java.util.ArrayList;
 import java.util.List;

+ 215 - 0
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/config/MediaConfig.java

@@ -0,0 +1,215 @@
+package org.jetlinks.community.media.config;
+
+import lombok.Data;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.StringUtils;
+
+import java.text.SimpleDateFormat;
+
+@Data
+@ConfigurationProperties(prefix = "media")
+public class MediaConfig {
+
+//    //@Value("${media.id:}")
+    private String id;
+
+    //@Value("${media.ip}")
+    private String ip;
+
+    //@Value("${media.hook-ip:${sip.ip}}")
+    private String hookIp;
+
+    //@Value("${sip.ip}")
+    private String sipIp;
+
+    //@Value("${sip.domain}")
+    private String sipDomain;
+
+    //@Value("${media.sdp-ip:${media.ip}}")
+    private String sdpIp;
+
+    //@Value("${media.stream-ip:${media.ip}}")
+    private String streamIp;
+
+    //@Value("${media.http-port}")
+    private Integer httpPort;
+
+    //@Value("${media.http-ssl-port:0}")
+    private Integer httpSSlPort = 0;
+
+    //@Value("${media.rtmp-port:0}")
+    private Integer rtmpPort = 0;
+
+    //@Value("${media.rtmp-ssl-port:0}")
+    private Integer rtmpSSlPort = 0;
+
+    //@Value("${media.rtp-proxy-port:0}")
+    private Integer rtpProxyPort = 0;
+
+    //@Value("${media.rtsp-port:0}")
+    private Integer rtspPort = 0;
+
+    //@Value("${media.rtsp-ssl-port:0}")
+    private Integer rtspSSLPort = 0;
+
+    //@Value("${media.auto-config:true}")
+    private boolean autoConfig = true;
+
+    //@Value("${media.secret}")
+    private String secret;
+
+    //@Value("${media.stream-none-reader-delay-ms:18000}")
+    private int streamNoneReaderDelayMS = 18000;
+
+    //@Value("${media.rtp.enable}")
+    private boolean rtpEnable;
+
+    //@Value("${media.rtp.port-range}")
+    private String rtpPortRange;
+
+
+    //@Value("${media.rtp.send-port-range}")
+    private String sendRtpPortRange;
+
+    //@Value("${media.record-assist-port:0}")
+    private Integer recordAssistPort = 0;
+
+    public String getId() {
+        return id;
+    }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public String getHookIp() {
+        if (StringUtils.isEmpty(hookIp)){
+            return sipIp;
+        }else {
+            return hookIp;
+        }
+
+    }
+
+    public String getSipIp() {
+        if (sipIp == null) {
+            return this.ip;
+        }else {
+            return sipIp;
+        }
+    }
+
+    public int getHttpPort() {
+        return httpPort;
+    }
+
+    public int getHttpSSlPort() {
+        return httpSSlPort;
+    }
+
+    public int getRtmpPort() {
+        return rtmpPort;
+    }
+
+    public int getRtmpSSlPort() {
+        return rtmpSSlPort;
+    }
+
+    public int getRtpProxyPort() {
+        if (rtpProxyPort == null) {
+            return 0;
+        }else {
+            return rtpProxyPort;
+        }
+
+    }
+
+    public int getRtspPort() {
+        return rtspPort;
+    }
+
+    public int getRtspSSLPort() {
+        return rtspSSLPort;
+    }
+
+    public boolean isAutoConfig() {
+        return autoConfig;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public int getStreamNoneReaderDelayMS() {
+        return streamNoneReaderDelayMS;
+    }
+
+    public boolean isRtpEnable() {
+        return rtpEnable;
+    }
+
+    public String getRtpPortRange() {
+        return rtpPortRange;
+    }
+
+    public int getRecordAssistPort() {
+        return recordAssistPort;
+    }
+
+    public String getSdpIp() {
+        if (StringUtils.isEmpty(sdpIp)){
+            return ip;
+        }else {
+            return sdpIp;
+        }
+    }
+
+    public String getStreamIp() {
+        if (StringUtils.isEmpty(streamIp)){
+            return ip;
+        }else {
+            return streamIp;
+        }
+    }
+
+    public String getSipDomain() {
+        return sipDomain;
+    }
+
+    public String getSendRtpPortRange() {
+        return sendRtpPortRange;
+    }
+
+    public MediaServerItem getMediaSerItem(){
+        MediaServerItem mediaServerItem = new MediaServerItem();
+        mediaServerItem.setId(id);
+        mediaServerItem.setIp(ip);
+        mediaServerItem.setDefaultServer(true);
+        mediaServerItem.setHookIp(getHookIp());
+        mediaServerItem.setSdpIp(getSdpIp());
+        mediaServerItem.setStreamIp(getStreamIp());
+        mediaServerItem.setHttpPort(httpPort);
+        mediaServerItem.setHttpSSlPort(httpSSlPort);
+        mediaServerItem.setRtmpPort(rtmpPort);
+        mediaServerItem.setRtmpSSlPort(rtmpSSlPort);
+        mediaServerItem.setRtpProxyPort(getRtpProxyPort());
+        mediaServerItem.setRtspPort(rtspPort);
+        mediaServerItem.setRtspSSLPort(rtspSSLPort);
+        mediaServerItem.setAutoConfig(autoConfig);
+        mediaServerItem.setSecret(secret);
+        mediaServerItem.setStreamNoneReaderDelayMS(streamNoneReaderDelayMS);
+        mediaServerItem.setRtpEnable(rtpEnable);
+        mediaServerItem.setRtpPortRange(rtpPortRange);
+        mediaServerItem.setSendRtpPortRange(sendRtpPortRange);
+        mediaServerItem.setRecordAssistPort(recordAssistPort);
+        mediaServerItem.setHookAliveInterval(120);
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        mediaServerItem.setCreateTime(format.format(System.currentTimeMillis()));
+        mediaServerItem.setUpdateTime(format.format(System.currentTimeMillis()));
+
+        return mediaServerItem;
+    }
+
+}

+ 1 - 1
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/controller/ApiStreamController.java

@@ -11,7 +11,7 @@
 //import org.jetlinks.community.media.entity.MediaDevice;
 //import org.jetlinks.community.media.enums.DeviceState;
 //import org.jetlinks.community.media.vmanager.gb28181.play.bean.PlayResult;
-//import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+//import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 //import org.jetlinks.community.utils.SipUtils;
 //import org.redisson.api.RedissonClient;
 //import org.springframework.web.bind.annotation.GetMapping;

+ 3 - 3
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/request/ISipRequestProcessor.java → jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/AbstractSipProcessor.java

@@ -1,4 +1,4 @@
-package org.jetlinks.community.media.event.request;
+package org.jetlinks.community.media.event;
 
 import lombok.extern.slf4j.Slf4j;
 import org.jetlinks.community.media.sip.processor.SipProcessorObserver;
@@ -12,7 +12,7 @@ import javax.sip.*;
  * @date:   2021年11月5日 15:47
  */
 @Slf4j
-public abstract class ISipRequestProcessor {
+public abstract class AbstractSipProcessor {
 
     @Autowired
     public SipProcessorObserver observer;
@@ -58,7 +58,7 @@ public abstract class ISipRequestProcessor {
     }
 
     public void processResponse(ResponseEvent event){
-
+        System.out.println(event);
     }
 
     public void processTimeout(TimeoutEvent event){

+ 43 - 3
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/request/impl/InviteRequestProcessor.java

@@ -1,17 +1,31 @@
 package org.jetlinks.community.media.event.request.impl;
 
 import gov.nist.javax.sip.address.AddressImpl;
+import gov.nist.javax.sip.address.GenericURI;
 import gov.nist.javax.sip.address.SipUri;
+import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
+import org.jetlinks.community.media.service.LocalMediaDeviceService;
+import org.jetlinks.community.media.sip.SipContext;
 import org.jetlinks.community.media.sip.SipRequestProcessorParent;
 import org.jetlinks.community.media.storage.IVideoManagerStorager;
+import org.jetlinks.community.media.transmit.SIPRequestHeaderProvider;
 import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import javax.sip.InvalidArgumentException;
+import javax.sip.PeerUnavailableException;
 import javax.sip.RequestEvent;
+import javax.sip.SipProvider;
 import javax.sip.address.SipURI;
+import javax.sip.address.URI;
+import javax.sip.header.CallIdHeader;
 import javax.sip.header.FromHeader;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
+import java.net.URL;
+import java.text.ParseException;
 
 /**
  * SIP命令类型: INVITE请求
@@ -19,13 +33,16 @@ import javax.sip.message.Response;
 @SuppressWarnings("rawtypes")
 @Component
 @Slf4j(topic = "sip-invite-request")
+@AllArgsConstructor
 public class InviteRequestProcessor extends SipRequestProcessorParent {
 
     //	@Autowired
 //	private SIPCommanderFroPlatform cmderFroPlatform;
 //
 //	@Autowired
-    private IVideoManagerStorager storager;
+//    private IVideoManagerStorager storager;
+
+    private final SIPRequestHeaderProvider headerProvider;
 //
 //	@Autowired
 //	private IRedisCatchStorage  redisCatchStorage;
@@ -40,7 +57,7 @@ public class InviteRequestProcessor extends SipRequestProcessorParent {
 //	private ZLMRTPServerFactory zlmrtpServerFactory;
 //
 //	@Autowired
-//	private IMediaServerService mediaServerService;
+	private final LocalMediaDeviceService mediaServerService;
 
     @Override
     public String getMethod() {
@@ -73,7 +90,30 @@ public class InviteRequestProcessor extends SipRequestProcessorParent {
                 responseAck(evt, Response.BAD_REQUEST);
                 return;
             }
-            responseAck(evt, Response.CALL_IS_BEING_FORWARDED);
+
+            mediaServerService.findById("34020000001320000003")
+                .doOnNext(device->{
+                    SipProvider sipProvider = SipContext.getSipProvider();
+                    String tm = Long.toString(System.currentTimeMillis());
+                    CallIdHeader callIdHeader =sipProvider.getNewCallId();
+                        try {
+                            Request inviteRequest = headerProvider
+                                .createInviteRequest(device, channelId, null, null, "FromInvt" + tm, null, "1000", callIdHeader);
+                            inviteRequest.setRequestURI( new GenericURI("1.15.89.83:10000"));
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        } catch (InvalidArgumentException e) {
+                            e.printStackTrace();
+                        } catch (PeerUnavailableException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                )
+                .subscribe();
+
+
+
+//            responseAck(evt, Response.CALL_IS_BEING_FORWARDED);
         }catch (Exception e){
             e.printStackTrace();
         }

+ 73 - 0
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/response/InviteResponseProcessor.java

@@ -0,0 +1,73 @@
+package org.jetlinks.community.media.event.response;
+
+import gov.nist.javax.sip.ResponseEventExt;
+import gov.nist.javax.sip.stack.SIPDialog;
+import lombok.extern.slf4j.Slf4j;
+import org.jetlinks.community.media.event.AbstractSipProcessor;
+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
+@Slf4j
+public class InviteResponseProcessor extends AbstractSipProcessor {
+	/**
+	 * 处理invite响应
+	 *
+	 * @param evt 响应消息
+	 * @throws ParseException
+	 */
+	@Override
+	public void processResponse(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);
+				log.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();
+		}
+	}
+
+    @Override
+    public String getMethod() {
+        return Request.INVITE;
+    }
+
+}

+ 4 - 6
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/event/response/RegisterResponseProcessor.java

@@ -4,9 +4,7 @@ import gov.nist.javax.sip.ResponseEventExt;
 import gov.nist.javax.sip.stack.SIPDialog;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.jetlinks.community.media.event.request.ISipRequestProcessor;
-import org.jetlinks.community.media.storage.IRedisCatchStorage;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.jetlinks.community.media.event.AbstractSipProcessor;
 import org.springframework.stereotype.Component;
 import javax.sip.InvalidArgumentException;
 import javax.sip.ResponseEvent;
@@ -17,15 +15,15 @@ import javax.sip.message.Request;
 import javax.sip.message.Response;
 import java.text.ParseException;
 
-/**    
+/**
  * @description:Register响应处理器
  * @author: swwheihei
- * @date:   2020年5月3日 下午5:32:23     
+ * @date:   2020年5月3日 下午5:32:23
  */
 @Component
 @AllArgsConstructor
 @Slf4j
-public class RegisterResponseProcessor extends ISipRequestProcessor {
+public class RegisterResponseProcessor extends AbstractSipProcessor {
 
 	/**
 	 * 处理Register响应

+ 597 - 0
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/service/LocalMediaServerItemServiceImpl.java

@@ -0,0 +1,597 @@
+package org.jetlinks.community.media.service;
+
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.crud.service.GenericReactiveCrudService;
+import org.jetlinks.community.media.contanst.VideoManagerConstants;
+import org.jetlinks.community.media.bean.SsrcConfig;
+import org.jetlinks.community.media.zlm.ZLMServerConfig;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
+import org.jetlinks.community.utils.RedisUtil;
+import org.jetlinks.core.cluster.ClusterManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+import java.text.SimpleDateFormat;
+
+/**
+ * 媒体服务器节点管理
+ */
+@Service
+@Slf4j
+public class LocalMediaServerItemServiceImpl extends GenericReactiveCrudService<MediaServerItem, String>  implements CommandLineRunner {
+
+//    private final SipConfig sipConfig;
+
+//    @Value("${server.ssl.enabled:false}")
+//    private boolean sslEnabled;
+//
+//    @Value("${server.port}")
+//    private Integer serverPort;
+
+
+    private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    private final RedisUtil redisUtil;
+
+    private final String serverId;
+
+    @Autowired
+    public LocalMediaServerItemServiceImpl(
+                                       ClusterManager clusterManager,
+                                       RedisUtil redisUtil)  {
+        this.serverId= clusterManager.getCurrentServerId();
+        this.redisUtil=redisUtil;
+    }
+
+    //    @Autowired
+//    private final UserSetup userSetup;
+//
+//    @Autowired
+//    private  final ZLMRESTfulUtils zlmresTfulUtils;
+//
+//    @Autowired
+//    private  final MediaServerMapper mediaServerMapper;
+//
+//    @Autowired
+//    private  final VideoStreamSessionManager streamSession;
+//
+//    @Autowired
+//    private final  ZLMRTPServerFactory zlmrtpServerFactory;
+//
+//    @Autowired
+//    private final  RedisUtil redisUtil;
+//
+//    @Autowired
+//    private  final IVideoManagerStorager storager;
+//
+//    @Autowired
+//    private final  IStreamProxyService streamProxyService;
+//
+//    @Autowired
+//    private  final EventPublisher publisher;
+//
+//    @Autowired
+//    JedisUtil jedisUtil;
+
+    /**
+     * 初始化
+     */
+    @Override
+    public void run(String... args) throws Exception {
+        log.info("[缓存初始化] Media Server ");
+        //查询所有媒体服务器数据
+        this.createQuery()
+            .fetch()
+            .filter(item->StrUtil.isNotEmpty(item.getId()))
+            .doOnNext(mediaServerItem->{
+                if (mediaServerItem.getSsrcConfig() == null) {
+                    //对ssrc进行更新 todo
+                    SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null,"");
+                    mediaServerItem.setSsrcConfig(ssrcConfig);
+                }
+            })
+            .doOnNext(mediaServerItem->redisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + serverId + "_" + mediaServerItem.getId(),mediaServerItem))
+            .subscribe();
+    }
+
+//
+//    @Override
+//    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) {
+//        return openRTPServer(mediaServerItem, streamId, false);
+//    }
+//
+//    @Override
+//    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback) {
+//        if (mediaServerItem == null || mediaServerItem.getId() == null) {
+//            return null;
+//        }
+//        // 获取mediaServer可用的ssrc
+//        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + mediaServerItem.getId();
+//
+//        SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
+//        if (ssrcConfig == null) {
+//            log.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
+//            return null;
+//        }else {
+//            String ssrc = null;
+//            if (isPlayback) {
+//                ssrc = ssrcConfig.getPlayBackSsrc();
+//            }else {
+//                ssrc = ssrcConfig.getPlaySsrc();
+//            }
+//
+//            if (streamId == null) {
+//                streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
+//            }
+//            int rtpServerPort = mediaServerItem.getRtpProxyPort();
+//            if (mediaServerItem.isRtpEnable()) {
+//                rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
+//            }
+//            redisUtil.set(key, mediaServerItem);
+//            return new SSRCInfo(rtpServerPort, ssrc, streamId);
+//        }
+//    }
+//
+//    @Override
+//    public void closeRTPServer(Device device, String channelId) {
+//        String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId);
+//        MediaServerItem mediaServerItem = this.getOne(mediaServerId);
+//        if (mediaServerItem != null) {
+//            String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+//            zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
+//            releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId));
+//        }
+//        streamSession.remove(device.getDeviceId(), channelId);
+//    }
+//
+//    @Override
+//    public void releaseSsrc(MediaServerItem mediaServerItem, String ssrc) {
+//        if (mediaServerItem == null || ssrc == null) {
+//            return;
+//        }
+//        SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
+//        ssrcConfig.releaseSsrc(ssrc);
+//        mediaServerItem.setSsrcConfig(ssrcConfig);
+//        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + mediaServerItem.getId();
+//        redisUtil.set(key, mediaServerItem);
+//    }
+//
+//    /**
+//     * zlm 重启后重置他的推流信息, TODO 给正在使用的设备发送停止命令
+//     */
+//    @Override
+//    public void clearRTPServer(MediaServerItem mediaServerItem) {
+//        mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()));
+//        redisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetup.getServerId(), mediaServerItem.getId(), 0);
+//    }
+//
+//
+//    @Override
+//    public void update(MediaServerItem mediaSerItem) {
+//        mediaServerMapper.update(mediaSerItem);
+//        MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
+//        MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
+//        if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) {
+//            mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
+//        }else {
+//            mediaServerItemInDataBase.setSsrcConfig(
+//                    new SsrcConfig(
+//                            mediaServerItemInDataBase.getId(),
+//                            null,
+//                            sipConfig.getDomain()
+//                    )
+//            );
+//        }
+//        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + mediaServerItemInDataBase.getId();
+//        redisUtil.set(key, mediaServerItemInDataBase);
+//    }
+//
+//    @Override
+//    public List<MediaServerItem> getAll() {
+//        List<MediaServerItem> result = new ArrayList<>();
+//        List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetup.getServerId() + "_" ));
+//        String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetup.getServerId();
+//        for (Object mediaServerKey : mediaServerKeys) {
+//            String key = (String) mediaServerKey;
+//            MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key);
+//            // 检查状态
+//            if (redisUtil.zScore(onlineKey, mediaServerItem.getId()) != null) {
+//                mediaServerItem.setStatus(true);
+//            }
+//            result.add(mediaServerItem);
+//        }
+//        result.sort((serverItem1, serverItem2)->{
+//            int sortResult = 0;
+//            try {
+//                sortResult = format.parse(serverItem1.getCreateTime()).compareTo(format.parse(serverItem2.getCreateTime()));
+//            } catch (ParseException e) {
+//                e.printStackTrace();
+//            }
+//            return  sortResult;
+//        });
+//        return result;
+//    }
+//
+//
+//    @Override
+//    public List<MediaServerItem> getAllFromDatabase() {
+//        return mediaServerMapper.queryAll();
+//    }
+//
+//    @Override
+//    public List<MediaServerItem> getAllOnline() {
+//        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetup.getServerId();
+//        Set<String> mediaServerIdSet = redisUtil.zRevRange(key, 0, -1);
+//
+//        List<MediaServerItem> result = new ArrayList<>();
+//        if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) {
+//            for (String mediaServerId : mediaServerIdSet) {
+//                String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + mediaServerId;
+//                result.add((MediaServerItem) redisUtil.get(serverKey));
+//            }
+//        }
+//        Collections.reverse(result);
+//        return result;
+//    }
+//
+//    /**
+//     * 获取单个zlm服务器
+//     * @param mediaServerId 服务id
+//     * @return MediaServerItem
+//     */
+//    @Override
+//    public MediaServerItem getOne(String mediaServerId) {
+//        if (mediaServerId == null) {
+//            return null;
+//        }
+//        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + mediaServerId;
+//        return (MediaServerItem)redisUtil.get(key);
+//    }
+//
+//    @Override
+//    public MediaServerItem getOneByHostAndPort(String host, int port) {
+//        return mediaServerMapper.queryOneByHostAndPort(host, port);
+//    }
+//
+
+    //todo
+    public Mono<MediaServerItem> getDefaultMediaServer() {
+//        return mediaServerMapper.queryDefault();
+        return null;
+    }
+
+    public Mono<Void> clearMediaServerForOnline() {
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + serverId;
+        return Mono.fromRunnable(()->redisUtil.del(key));
+    }
+//
+//    @Override
+//    public WVPResult<String> add(MediaServerItem mediaServerItem) {
+//        WVPResult<String> result = new WVPResult<>();
+//        mediaServerItem.setCreateTime(this.format.format(System.currentTimeMillis()));
+//        mediaServerItem.setUpdateTime(this.format.format(System.currentTimeMillis()));
+//        mediaServerItem.setHookAliveInterval(120);
+//        JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
+//        if (responseJSON != null) {
+//            JSONArray data = responseJSON.getJSONArray("data");
+//            if (data != null && data.size() > 0) {
+//                ZLMServerConfig zlmServerConfig= JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
+//                if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) {
+//                    result.setCode(-1);
+//                    result.setMsg("保存失败,媒体服务ID [ " + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
+//                    return result;
+//                }
+//                mediaServerItem.setId(zlmServerConfig.getGeneralMediaServerId());
+//                zlmServerConfig.setIp(mediaServerItem.getIp());
+//                mediaServerMapper.add(mediaServerItem);
+//                zlmServerOnline(zlmServerConfig);
+//                result.setCode(0);
+//                result.setMsg("success");
+//            }else {
+//                result.setCode(-1);
+//                result.setMsg("连接失败");
+//            }
+//
+//        }else {
+//            result.setCode(-1);
+//            result.setMsg("连接失败");
+//        }
+//       return result;
+//    }
+
+
+    //todo
+    public Mono<Integer> addToDatabase(MediaServerItem mediaSerItem) {
+        return this.createUpdate().execute();
+    }
+
+  //todo
+    public Mono<Integer> updateToDatabase(MediaServerItem mediaSerItem) {
+        return this.createUpdate().execute();
+    }
+
+    /**
+     * 处理zlm上线 todo
+     * @param zlmServerConfig zlm上线携带的参数
+     */
+    public Mono<Void> zlmServerOnline(ZLMServerConfig zlmServerConfig) {
+//        log.info("[ ZLM:{} ]-[ {}:{} ]已连接",
+//                zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
+//
+//        MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
+//        if (serverItem == null) {
+//            serverItem = mediaServerMapper.queryOneByHostAndPort(zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
+//        }
+//        if (serverItem == null) {
+//            log.warn("[未注册的zlm] 拒接接入:来自{}:{}", zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
+//            return;
+//        }
+//        serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval());
+//        if (serverItem.getHttpPort() == 0) {
+//            serverItem.setHttpPort(zlmServerConfig.getHttpPort());
+//        }
+//        if (serverItem.getHttpSSlPort() == 0) {
+//            serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
+//        }
+//        if (serverItem.getRtmpPort() == 0) {
+//            serverItem.setRtmpPort(zlmServerConfig.getRtmpPort());
+//        }
+//        if (serverItem.getRtmpSSlPort() == 0) {
+//            serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
+//        }
+//        if (serverItem.getRtspPort() == 0) {
+//            serverItem.setRtspPort(zlmServerConfig.getRtspPort());
+//        }
+//        if (serverItem.getRtspSSLPort() == 0) {
+//            serverItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
+//        }
+//        if (serverItem.getRtpProxyPort() == 0) {
+//            serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
+//        }
+//        serverItem.setStatus(true);
+//
+//        if (StringUtils.isEmpty(serverItem.getId())) {
+//            serverItem.setId(zlmServerConfig.getGeneralMediaServerId());
+//            mediaServerMapper.updateByHostAndPort(serverItem);
+//        }else {
+//            mediaServerMapper.update(serverItem);
+//        }
+//        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId();
+//        if (redisUtil.get(key) == null) {
+//            SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain());
+//            serverItem.setSsrcConfig(ssrcConfig);
+//        }else {
+//            MediaServerItem mediaServerItemInRedis = (MediaServerItem)redisUtil.get(key);
+//            serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
+//        }
+//        redisUtil.set(key, serverItem);
+//        resetOnlineServerItem(serverItem);
+//        updateMediaServerKeepalive(serverItem.getId(), null);
+//        setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
+//
+//        publisher.zlmOnlineEventPublish(serverItem.getId());
+        return Mono.empty();
+
+    }
+//
+//
+//    @Override
+//    public void zlmServerOffline(String mediaServerId) {
+//        delete(mediaServerId);
+//    }
+//
+//    @Override
+//    public void resetOnlineServerItem(MediaServerItem serverItem) {
+//        // 更新缓存
+//        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetup.getServerId();
+//        // 使用zset的分数作为当前并发量, 默认值设置为0
+//        if (redisUtil.zScore(key, serverItem.getId()) == null) {  // 不存在则设置默认值 已存在则重置
+//            redisUtil.zAdd(key, serverItem.getId(), 0L);
+//            // 查询服务流数量
+//            zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
+//                Integer code = mediaList.getInteger("code");
+//                if (code == 0) {
+//                    JSONArray data = mediaList.getJSONArray("data");
+//                    if (data != null) {
+//                        redisUtil.zAdd(key, serverItem.getId(), data.size());
+//                    }
+//                }
+//            }));
+//        }else {
+//            clearRTPServer(serverItem);
+//        }
+//
+//    }
+
+    /**
+     * 媒体服务器通道在线数
+     * @param mediaServerId
+     */
+    public Mono<Void> addCount(String mediaServerId) {
+        return Mono.fromRunnable(()->{
+            if (mediaServerId == null) {
+                return;
+            }
+            String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + serverId;
+            redisUtil.zIncrScore(key, mediaServerId, 1);
+        });
+    }
+
+    public Mono<Void> removeCount(String mediaServerId) {
+        return Mono.fromRunnable(()->{
+            String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + serverId;
+            redisUtil.zIncrScore(key, mediaServerId, - 1);
+        });
+
+    }
+//
+//    /**
+//     * 获取负载最低的节点
+//     * @return MediaServerItem
+//     */
+//    @Override
+//    public MediaServerItem getMediaServerForMinimumLoad() {
+//        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetup.getServerId();
+//
+//        if (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
+//            log.info("获取负载最低的节点时无在线节点");
+//            return null;
+//        }
+//
+//        // 获取分数最低的,及并发最低的
+//        Set<Object> objects = redisUtil.ZRange(key, 0, -1);
+//        ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects);
+//
+//        String mediaServerId = (String)mediaServerObjectS.get(0);
+//        return getOne(mediaServerId);
+//    }
+//
+//    /**
+//     * 对zlm服务器进行基础配置
+//     * @param mediaServerItem 服务ID
+//     * @param restart 是否重启zlm
+//     */
+//    @Override
+//    public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) {
+//        log.info("[ ZLM:{} ]-[ {}:{} ]设置zlm",
+//                mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+//        String protocol = sslEnabled ? "https" : "http";
+//        String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
+//        String recordHookPrex = null;
+//        if (mediaServerItem.getRecordAssistPort() != 0) {
+//            recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaServerItem.getRecordAssistPort());
+//        }
+//        Map<String, Object> param = new HashMap<>();
+//        param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
+//        param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264  -f flv %s");
+//        param.put("hook.enable","1");
+//        param.put("hook.on_flow_report","");
+//        param.put("hook.on_play",String.format("%s/on_play", hookPrex));
+//        param.put("hook.on_http_access","");
+//        param.put("hook.on_publish", String.format("%s/on_publish", hookPrex));
+//        param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): "");
+//        param.put("hook.on_record_ts","");
+//        param.put("hook.on_rtsp_auth","");
+//        param.put("hook.on_rtsp_realm","");
+//        param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex));
+//        param.put("hook.on_shell_login",String.format("%s/on_shell_login", hookPrex));
+//        param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex));
+//        param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
+//        param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
+//        param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));
+//        param.put("hook.timeoutSec","20");
+//        param.put("general.streamNoneReaderDelayMS","-1".equals(mediaServerItem.getStreamNoneReaderDelayMS())?"3600000":mediaServerItem.getStreamNoneReaderDelayMS() );
+//
+//        JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param);
+//
+//        if (responseJSON != null && responseJSON.getInteger("code") == 0) {
+//            if (restart) {
+//                log.info("[ ZLM:{} ]-[ {}:{} ]设置zlm成功, 开始重启以保证配置生效",
+//                        mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+//                zlmresTfulUtils.restartServer(mediaServerItem);
+//            }else {
+//                log.info("[ ZLM:{} ]-[ {}:{} ]设置zlm成功",
+//                        mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+//            }
+//
+//
+//        }else {
+//            log.info("[ ZLM:{} ]-[ {}:{} ]设置zlm失败",
+//                    mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+//        }
+//
+//
+//    }
+//
+//
+//    @Override
+//    public WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret) {
+//        WVPResult<MediaServerItem> result = new WVPResult<>();
+//        if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) {
+//            result.setCode(-1);
+//            result.setMsg("此连接已存在");
+//            return result;
+//        }
+//        MediaServerItem mediaServerItem = new MediaServerItem();
+//        mediaServerItem.setIp(ip);
+//        mediaServerItem.setHttpPort(port);
+//        mediaServerItem.setSecret(secret);
+//        JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
+//        if (responseJSON == null) {
+//            result.setCode(-1);
+//            result.setMsg("连接失败");
+//            return result;
+//        }
+//        JSONArray data = responseJSON.getJSONArray("data");
+//        ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
+//        if (zlmServerConfig == null) {
+//            result.setCode(-1);
+//            result.setMsg("读取配置失败");
+//            return result;
+//        }
+//        if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) {
+//            result.setCode(-1);
+//            result.setMsg("媒体服务ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
+//            return result;
+//        }
+//        mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort());
+//        mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort());
+//        mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
+//        mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort());
+//        mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
+//        mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
+//        mediaServerItem.setStreamIp(ip);
+//        mediaServerItem.setHookIp(sipConfig.getIp());
+//        mediaServerItem.setSdpIp(ip);
+//        mediaServerItem.setStreamNoneReaderDelayMS(zlmServerConfig.getGeneralStreamNoneReaderDelayMS());
+//        result.setCode(0);
+//        result.setMsg("成功");
+//        result.setData(mediaServerItem);
+//        return result;
+//    }
+//
+//    @Override
+//    public boolean checkMediaRecordServer(String ip, int port) {
+//        boolean result = false;
+//        OkHttpClient client = new OkHttpClient();
+//        String url = String.format("http://%s:%s/index/api/record",  ip, port);
+//
+//        FormBody.Builder builder = new FormBody.Builder();
+//
+//        Request request = new Request.Builder()
+//                .get()
+//                .url(url)
+//                .build();
+//        try {
+//            Response response = client.newCall(request).execute();
+//            if (response != null) {
+//                result = true;
+//            }
+//        } catch (Exception e) {}
+//
+//        return result;
+//    }
+//
+//    @Override
+//    public void delete(String id) {
+//        redisUtil.zRemove(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetup.getServerId(), id);
+//        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + id;
+//        redisUtil.del(key);
+//    }
+//
+
+    public Mono<Void> updateMediaServerKeepalive(String mediaServerId, JSONObject data) {
+        return this.findById(mediaServerId)
+            .doOnNext(mediaServerItem -> {
+                String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX +serverId + "_" + mediaServerId;
+                int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2;
+                redisUtil.set(key, data, hookAliveInterval);
+            })
+            .then();
+    }
+}

+ 1 - 1
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/service/LocalPlayService.java

@@ -27,7 +27,7 @@
 //import gov.nist.javax.sip.stack.SIPDialog;
 //import lombok.AllArgsConstructor;
 //import lombok.extern.slf4j.Slf4j;
-//import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+//import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 //import org.redisson.api.RedissonClient;
 //import org.slf4j.Logger;
 //import org.slf4j.LoggerFactory;

+ 3 - 3
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/sip/SipRequestProcessorParent.java

@@ -11,7 +11,7 @@ import org.dom4j.Element;
 import org.dom4j.io.SAXReader;
 import org.jetlinks.community.media.core.DigestServerAuthenticationHelper2016;
 import org.jetlinks.community.media.entity.SipServerConfig;
-import org.jetlinks.community.media.event.request.ISipRequestProcessor;
+import org.jetlinks.community.media.event.AbstractSipProcessor;
 import javax.sip.*;
 import javax.sip.address.Address;
 import javax.sip.address.AddressFactory;
@@ -29,10 +29,10 @@ import java.text.ParseException;
 /**
  * @description:处理接收IPCamera发来的SIP协议请求消息
  * @author: songww
- * @date:   2020年5月3日 下午4:42:22     
+ * @date:   2020年5月3日 下午4:42:22
  */
 @Slf4j
-public abstract class SipRequestProcessorParent extends ISipRequestProcessor {
+public abstract class SipRequestProcessorParent extends AbstractSipProcessor {
 
 
 

+ 2 - 2
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/sip/SipServerHelper.java

@@ -17,7 +17,7 @@ import org.jetlinks.community.media.event.request.message.notify.KeepaliveNotify
 import org.jetlinks.community.media.sip.processor.SipProcessorObserver;
 import org.jetlinks.community.media.transmit.SIPRequestHeaderProvider;
 import org.jetlinks.community.media.transmit.cmd.SipCommander;
-import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 import org.springframework.stereotype.Component;
 import reactor.core.publisher.Flux;
@@ -79,7 +79,7 @@ public class SipServerHelper implements BeanPostProcessor {
         RegisterRequestProcessor registerRequestProcessor = new RegisterRequestProcessor(null);
         registerRequestProcessor.observer=sipProcessorObserver;
         registerRequestProcessor.init();
-        InviteRequestProcessor inviteRequestProcessor = new InviteRequestProcessor();
+        InviteRequestProcessor inviteRequestProcessor = new InviteRequestProcessor(null,null);
         inviteRequestProcessor.observer=sipProcessorObserver;
         inviteRequestProcessor.init();
         MessageRequestProcessor messageRequestProcessor = new MessageRequestProcessor();

+ 0 - 210
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/storage/IRedisCatchStorage.java

@@ -1,210 +0,0 @@
-package org.jetlinks.community.media.storage;
-
-import com.alibaba.fastjson.JSONObject;
-import org.jetlinks.community.media.bean.StreamInfo;
-import org.jetlinks.community.media.entity.MediaDevice;
-import org.jetlinks.community.media.entity.ParentPlatform;
-import org.jetlinks.community.media.zlm.dto.MediaItem;
-
-import java.util.List;
-import java.util.Map;
-
-public interface IRedisCatchStorage {
-
-    /**
-     * 计数器。为cseq进行计数
-     *
-     * @param method sip 方法
-     * @return
-     */
-    Long getCSEQ(String method);
-
-    /**
-     * 开始播放时将流存入
-     *
-     * @param stream 流信息
-     * @return
-     */
-    boolean startPlay(StreamInfo stream);
-
-
-    /**
-     * 停止播放时删除
-     *
-     * @return
-     */
-    boolean stopPlay(StreamInfo streamInfo);
-
-    /**
-     * 查询播放列表
-     * @return
-     */
-    StreamInfo queryPlay(StreamInfo streamInfo);
-
-    StreamInfo queryPlayByStreamId(String steamId);
-
-    StreamInfo queryPlaybackByStreamId(String steamId);
-
-    StreamInfo queryPlayByDevice(String deviceId, String channelId);
-
-    Map<String, StreamInfo> queryPlayByDeviceId(String deviceId);
-
-    boolean startPlayback(StreamInfo stream);
-
-    boolean stopPlayback(StreamInfo streamInfo);
-
-    StreamInfo queryPlaybackByDevice(String deviceId, String code);
-
-//    void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch);
-//
-//    ParentPlatformCatch queryPlatformCatchInfo(String platformGbId);
-
-    void delPlatformCatchInfo(String platformGbId);
-
-    void updatePlatformKeepalive(ParentPlatform parentPlatform);
-
-    void delPlatformKeepalive(String platformGbId);
-
-    void updatePlatformRegister(ParentPlatform parentPlatform);
-
-    void delPlatformRegister(String platformGbId);
-
-    void updatePlatformRegisterInfo(String callId, String platformGbId);
-
-    String queryPlatformRegisterInfo(String callId);
-
-    void delPlatformRegisterInfo(String callId);
-
-    void cleanPlatformRegisterInfos();
-
-//    void updateSendRTPSever(SendRtpItem sendRtpItem);
-
-    /**
-     * 查询RTP推送信息缓存
-     * @param platformGbId
-     * @param channelId
-     * @return sendRtpItem
-     */
-//    SendRtpItem querySendRTPServer(String platformGbId, String channelId);
-//
-//    List<SendRtpItem> querySendRTPServer(String platformGbId);
-
-    /**
-     * 删除RTP推送信息缓存
-     * @param platformGbId
-     * @param channelId
-     */
-    void deleteSendRTPServer(String platformGbId, String channelId);
-
-    /**
-     * 查询某个通道是否存在上级点播(RTP推送)
-     * @param channelId
-     */
-    boolean isChannelSendingRTP(String channelId);
-
-    /**
-     * 清空某个设备的所有缓存
-     * @param deviceId 设备ID
-     */
-    void clearCatchByDeviceId(String deviceId);
-
-    /**
-     * 获取mediaServer节点
-     * @param mediaServerId
-     * @return
-     */
-//    MediaServerItem getMediaInfo(String mediaServerId);
-
-    /**
-     * 设置所有设备离线
-     */
-    void outlineForAll();
-
-    /**
-     * 获取所有在线的
-     */
-    List<String> getOnlineForAll();
-
-    /**
-     * 在redis添加wvp的信息
-     */
-    void updateWVPInfo(JSONObject jsonObject, int time);
-
-    /**
-     * 发送推流生成与推流消失消息
-     * @param jsonObject 消息内容
-     */
-    void sendStreamChangeMsg(String type, JSONObject jsonObject);
-
-    /**
-     * 添加流信息到redis
-     * @param mediaServerItem
-     * @param app
-     * @param streamId
-     */
-//    void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem item);
-
-    /**
-     * 移除流信息从redis
-     * @param mediaServerId
-     * @param app
-     * @param streamId
-     */
-    void removeStream(String mediaServerId, String type, String app, String streamId);
-
-
-    /**
-     * 移除流信息从redis
-     * @param mediaServerId
-     */
-    void removeStream(String mediaServerId, String type);
-
-    /**
-     * 开始下载录像时存入
-     * @param streamInfo
-     */
-    boolean startDownload(StreamInfo streamInfo);
-
-    StreamInfo queryDownloadByStreamId(String streamId);
-
-//    /**
-//     * 查找第三方系统留下的国标预设值
-//     * @param queryKey
-//     * @return
-//     */
-//    ThirdPartyGB queryMemberNoGBId(String queryKey);
-
-    List<MediaItem> getStreams(String mediaServerId, String pull);
-
-    /**
-     * 将device信息写入redis
-     * @param device
-     */
-    void updateDevice(MediaDevice device);
-
-    void removeDevice(String deviceId);
-
-    /**
-     * 获取Device
-     */
-    MediaDevice getDevice(String deviceId);
-
-    void resetAllCSEQ();
-
-//    void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo);
-
-//    GPSMsgInfo getGpsMsgInfo(String gbId);
-//    List<GPSMsgInfo> getAllGpsMsgInfo();
-
-    Long getSN(String method);
-
-    void resetAllSN();
-
-//    void updateSubscribe(String key, SubscribeInfo subscribeInfo);
-
-//    SubscribeInfo getSubscribe(String key);
-
-    void delSubscribe(String key);
-
-    MediaItem getStreamInfo(String app, String streamId, String mediaServerId);
-}

+ 461 - 453
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/storage/impl/RedisCatchStorageImpl.java

@@ -1,32 +1,43 @@
-//package org.jetlinks.community.media.storage.impl;
-//
-//import com.alibaba.fastjson.JSONObject;
-//import lombok.extern.slf4j.Slf4j;
-//import org.jetlinks.community.media.bean.StreamInfo;
-//import org.jetlinks.community.media.contanst.VideoManagerConstants;
-//import org.jetlinks.community.media.entity.DeviceChannel;
-//import org.jetlinks.community.media.entity.MediaDevice;
-//import org.jetlinks.community.media.entity.ParentPlatform;
-//import org.jetlinks.community.media.storage.IRedisCatchStorage;
-//import org.jetlinks.community.media.zlm.dto.MediaItem;
-//import org.jetlinks.community.media.zlm.dto.MediaServerItem;
-//import org.jetlinks.community.utils.RedisUtil;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Component;
-//
-//import java.text.SimpleDateFormat;
-//import java.util.ArrayList;
-//import java.util.HashMap;
-//import java.util.List;
-//import java.util.Map;
-//
-//@SuppressWarnings("rawtypes")
-//@Component
-//@Slf4j
-//public class RedisCatchStorageImpl implements IRedisCatchStorage {
-//
-//
-//    @Autowired
+package org.jetlinks.community.media.storage.impl;
+
+import cn.hutool.json.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.jetlinks.community.media.bean.SendRtpItem;
+import org.jetlinks.community.media.bean.StreamInfo;
+import org.jetlinks.community.media.contanst.VideoManagerConstants;
+import org.jetlinks.community.media.entity.MediaDevice;
+import org.jetlinks.community.media.entity.ParentPlatform;
+import org.jetlinks.community.media.zlm.dto.MediaItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
+import org.jetlinks.community.utils.RedisUtil;
+import org.jetlinks.core.cluster.ClusterManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("rawtypes")
+@Component
+@Slf4j
+public class RedisCatchStorageImpl {
+
+    private final RedisUtil redis;
+
+    private final String serverId;
+
+    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    @Autowired
+    public RedisCatchStorageImpl(RedisUtil redis,
+                                 ClusterManager clusterManager) {
+        this.redis = redis;
+        this.serverId=clusterManager.getCurrentServerId();
+    }
+
+    //    @Autowired
 //	private final RedisUtil redis;
 //
 //    @Autowired
@@ -34,152 +45,145 @@
 //
 //    @Autowired
 //    private final UserSetup userSetup;
-//
-//    @Autowired
-//    public RedisCatchStorageImpl(RedisUtil redis, DeviceChannelMapper deviceChannelMapper, UserSetup userSetup) {
-//        this.redis = redis;
-//        this.deviceChannelMapper = deviceChannelMapper;
-//        this.userSetup = userSetup;
-//    }
-//
-//    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-//
-//    @Override
-//    public Long getCSEQ(String method) {
-//        String key = VideoManagerConstants.SIP_CSEQ_PREFIX  + userSetup.getServerId() + "_" +  method;
-//
-//        long result =  redis.incr(key, 1L);
-//        if (result > Integer.MAX_VALUE) {
-//            redis.set(key, 1);
-//            result = 1;
-//        }
-//        return result;
-//    }
-//
-//    @Override
-//    public Long getSN(String method) {
-//        String key = VideoManagerConstants.SIP_SN_PREFIX  + userSetup.getServerId() + "_" +  method;
-//
-//        long result =  redis.incr(key, 1L);
-//        if (result > Integer.MAX_VALUE) {
-//            redis.set(key, 1);
-//            result = 1;
-//        }
-//        return result;
-//    }
-//
-//    @Override
-//    public void resetAllCSEQ() {
-//        String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX  + userSetup.getServerId() + "_*";
-//        List<Object> keys = redis.scan(scanKey);
-//        for (int i = 0; i < keys.size(); i++) {
-//            String key = (String) keys.get(i);
-//            redis.set(key, 1);
-//        }
-//    }
-//
-//    @Override
-//    public void resetAllSN() {
-//        String scanKey = VideoManagerConstants.SIP_SN_PREFIX  + userSetup.getServerId() + "_*";
-//        List<Object> keys = redis.scan(scanKey);
-//        for (int i = 0; i < keys.size(); i++) {
-//            String key = (String) keys.get(i);
-//            redis.set(key, 1);
-//        }
-//    }
-//
-//    /**
-//     * 开始播放时将流存入redis
-//     *
-//     * @return
-//     */
-//    @Override
-//    public boolean startPlay(StreamInfo stream) {
-//        return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()),
-//                stream);
-//    }
-//
-//    /**
-//     * 停止播放时从redis删除
-//     *
-//     * @return
-//     */
-//    @Override
-//    public boolean stopPlay(StreamInfo streamInfo) {
-//        if (streamInfo == null) return false;
-//        return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
-//                userSetup.getServerId(),
-//                streamInfo.getStreamId(),
-//                streamInfo.getDeviceID(),
-//                streamInfo.getChannelId()));
-//    }
-//
-//    /**
-//     * 查询播放列表
-//     * @return
-//     */
-//    @Override
-//    public StreamInfo queryPlay(StreamInfo streamInfo) {
-//        return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s",
-//                VideoManagerConstants.PLAYER_PREFIX,
-//                userSetup.getServerId(),
-//                streamInfo.getStreamId(),
-//                streamInfo.getDeviceID(),
-//                streamInfo.getChannelId()));
-//    }
-//    @Override
-//    public StreamInfo queryPlayByStreamId(String streamId) {
-//        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), streamId));
-//        if (playLeys == null || playLeys.size() == 0) return null;
-//        return (StreamInfo)redis.get(playLeys.get(0).toString());
-//    }
-//
-//    @Override
-//    public StreamInfo queryPlaybackByStreamId(String streamId) {
-//        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),  streamId));
-//        if (playLeys == null || playLeys.size() == 0) return null;
-//        return (StreamInfo)redis.get(playLeys.get(0).toString());
-//    }
-//
-//    @Override
-//    public StreamInfo queryPlayByDevice(String deviceId, String channelId) {
-////		List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
-//        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
-//                userSetup.getServerId(),
-//                deviceId,
-//                channelId));
-//        if (playLeys == null || playLeys.size() == 0) return null;
-//        return (StreamInfo)redis.get(playLeys.get(0).toString());
-//    }
-//
-//    @Override
-//    public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
-//        Map<String, StreamInfo> streamInfos = new HashMap<>();
-////		List<Object> playLeys = redis.keys(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
-//        List<Object> players = redis.scan(String.format("%S_%s_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(),deviceId));
-//        if (players.size() == 0) return streamInfos;
-//        for (int i = 0; i < players.size(); i++) {
-//            String key = (String) players.get(i);
-//            StreamInfo streamInfo = (StreamInfo)redis.get(key);
-//            streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getChannelId(), streamInfo);
-//        }
-//        return streamInfos;
-//    }
-//
-//
-//    @Override
-//    public boolean startPlayback(StreamInfo stream) {
-//        return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),stream.getStreamId(),
-//                        stream.getDeviceID(), stream.getChannelId()), stream);
-//    }
-//
-//    @Override
-//    public boolean startDownload(StreamInfo streamInfo) {
-//        return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),streamInfo.getStreamId(),
-//                        streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
-//    }
-//
-//    @Override
+
+    public Long getCSEQ(String method) {
+        String key = VideoManagerConstants.SIP_CSEQ_PREFIX  +serverId + "_" +  method;
+        long result =  redis.incr(key, 1L);
+        if (result > Integer.MAX_VALUE) {
+            redis.set(key, 1);
+            result = 1;
+        }
+        return result;
+    }
+
+
+    public Long getSN(String method) {
+        String key = VideoManagerConstants.SIP_SN_PREFIX  +serverId+ "_" +  method;
+
+        long result =  redis.incr(key, 1L);
+        if (result > Integer.MAX_VALUE) {
+            redis.set(key, 1);
+            result = 1;
+        }
+        return result;
+    }
+
+
+    public void resetAllCSEQ() {
+        String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX  +serverId + "_*";
+        List<Object> keys = redis.scan(scanKey);
+        for (int i = 0; i < keys.size(); i++) {
+            String key = (String) keys.get(i);
+            redis.set(key, 1);
+        }
+    }
+
+    public void resetAllSN() {
+        String scanKey = VideoManagerConstants.SIP_SN_PREFIX  + serverId+ "_*";
+        List<Object> keys = redis.scan(scanKey);
+        for (int i = 0; i < keys.size(); i++) {
+            String key = (String) keys.get(i);
+            redis.set(key, 1);
+        }
+    }
+
+    /**
+     * 开始播放时将流存入redis
+     *
+     * @return
+     */
+    public boolean startPlay(StreamInfo stream) {
+        return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,serverId, stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()),
+                stream);
+    }
+
+    /**
+     * 停止播放时从redis删除
+     *
+     * @return
+     */
+    public boolean stopPlay(StreamInfo streamInfo) {
+        if (streamInfo == null) {
+            return false;
+        }
+        return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
+            serverId,
+                streamInfo.getStreamId(),
+                streamInfo.getDeviceID(),
+                streamInfo.getChannelId()));
+    }
+
+    /**
+     * 查询播放列表
+     * @return
+     */
+
+    public StreamInfo queryPlay(StreamInfo streamInfo) {
+        return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s",
+                VideoManagerConstants.PLAYER_PREFIX,
+                serverId,
+                streamInfo.getStreamId(),
+                streamInfo.getDeviceID(),
+                streamInfo.getChannelId()));
+    }
+
+    public StreamInfo queryPlayByStreamId(String streamId) {
+        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, serverId, streamId));
+        if (playLeys == null || playLeys.size() == 0) {
+            return null;
+        }
+        return (StreamInfo)redis.get(playLeys.get(0).toString());
+    }
+
+
+    public StreamInfo queryPlaybackByStreamId(String streamId) {
+        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, serverId,  streamId));
+        if (playLeys == null || playLeys.size() == 0) {
+            return null;
+        }
+        return (StreamInfo)redis.get(playLeys.get(0).toString());
+    }
+
+
+    public StreamInfo queryPlayByDevice(String deviceId, String channelId) {
+        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
+            serverId,
+                deviceId,
+                channelId));
+        if (playLeys == null || playLeys.size() == 0){
+            return null;
+        }
+        return (StreamInfo)redis.get(playLeys.get(0).toString());
+    }
+
+
+    public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
+        Map<String, StreamInfo> streamInfos = new HashMap<>();
+        List<Object> players = redis.scan(String.format("%S_%s_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, serverId,deviceId));
+        if (players.size() == 0) {
+            return streamInfos;
+        }
+        for (int i = 0; i < players.size(); i++) {
+            String key = (String) players.get(i);
+            StreamInfo streamInfo = (StreamInfo)redis.get(key);
+            streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getChannelId(), streamInfo);
+        }
+        return streamInfos;
+    }
+
+
+    public boolean startPlayback(StreamInfo stream) {
+        return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,serverId,stream.getStreamId(),
+                        stream.getDeviceID(), stream.getChannelId()), stream);
+    }
+
+
+    public boolean startDownload(StreamInfo streamInfo) {
+        return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, serverId,streamInfo.getStreamId(),
+                        streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
+    }
+
+
 //    public boolean stopPlayback(StreamInfo streamInfo) {
 //        if (streamInfo == null) return false;
 //        DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(streamInfo.getDeviceID(), streamInfo.getChannelId());
@@ -189,304 +193,307 @@
 //            deviceChannelMapper.update(deviceChannel);
 //        }
 //        return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
-//                userSetup.getServerId(),
+//            serverId,
 //                streamInfo.getStreamId(),
 //                streamInfo.getDeviceID(),
 //                streamInfo.getChannelId()));
 //    }
-//
-//    @Override
-//    public StreamInfo queryPlaybackByDevice(String deviceId, String code) {
-//        // String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
-//        //         deviceId,
-//        //         code);
-//        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
-//                userSetup.getServerId(),
-//                deviceId,
-//                code));
-//        if (playLeys == null || playLeys.size() == 0) {
-//            playLeys = redis.scan(String.format("%S_%s_*_*_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
-//                    userSetup.getServerId(),
-//                    deviceId));
-//        }
-//        if (playLeys == null || playLeys.size() == 0) return null;
-//        return (StreamInfo)redis.get(playLeys.get(0).toString());
-//    }
-//
-//    @Override
+
+
+    public StreamInfo queryPlaybackByDevice(String deviceId, String code) {
+        // String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
+        //         deviceId,
+        //         code);
+        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
+            serverId,
+                deviceId,
+                code));
+        if (playLeys == null || playLeys.size() == 0) {
+            playLeys = redis.scan(String.format("%S_%s_*_*_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
+                serverId,
+                    deviceId));
+        }
+        if (playLeys == null || playLeys.size() == 0) {
+            return null;
+        }
+        return (StreamInfo)redis.get(playLeys.get(0).toString());
+    }
+
 //    public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) {
-//        String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX  + userSetup.getServerId() + "_" +  parentPlatformCatch.getId();
+//        String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX  + serverId + "_" +  parentPlatformCatch.getId();
 //        redis.set(key, parentPlatformCatch);
 //    }
+
+
+    public void updatePlatformKeepalive(ParentPlatform parentPlatform) {
+        String key = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX  + serverId + "_" + parentPlatform.getServerGBId();
+        redis.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
+    }
+
+
+    public void updatePlatformRegister(ParentPlatform parentPlatform) {
+        String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + serverId + "_" + parentPlatform.getServerGBId();
+        redis.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
+    }
+
 //
-//    @Override
-//    public void updatePlatformKeepalive(ParentPlatform parentPlatform) {
-//        String key = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX  + userSetup.getServerId() + "_" + parentPlatform.getServerGBId();
-//        redis.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
-//    }
-//
-//    @Override
-//    public void updatePlatformRegister(ParentPlatform parentPlatform) {
-//        String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetup.getServerId() + "_" + parentPlatform.getServerGBId();
-//        redis.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
-//    }
-//
-//    @Override
 //    public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) {
-//        return (ParentPlatformCatch)redis.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetup.getServerId() + "_" + platformGbId);
-//    }
-//
-//    @Override
-//    public void delPlatformCatchInfo(String platformGbId) {
-//        redis.del(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetup.getServerId() + "_" + platformGbId);
-//    }
-//
-//    @Override
-//    public void delPlatformKeepalive(String platformGbId) {
-//        redis.del(VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetup.getServerId() + "_" + platformGbId);
-//    }
-//
-//    @Override
-//    public void delPlatformRegister(String platformGbId) {
-//        redis.del(VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetup.getServerId() + "_" + platformGbId);
-//    }
-//
-//
-//    @Override
-//    public void updatePlatformRegisterInfo(String callId, String platformGbId) {
-//        String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetup.getServerId() + "_" + callId;
-//        redis.set(key, platformGbId);
-//    }
-//
-//
-//    @Override
-//    public String queryPlatformRegisterInfo(String callId) {
-//        return (String)redis.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetup.getServerId() + "_" + callId);
-//    }
-//
-//    @Override
-//    public void delPlatformRegisterInfo(String callId) {
-//        redis.del(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetup.getServerId() + "_" + callId);
-//    }
-//
-//    @Override
-//    public void cleanPlatformRegisterInfos() {
-//        List regInfos = redis.scan(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetup.getServerId() + "_" + "*");
-//        for (Object key : regInfos) {
-//            redis.del(key.toString());
-//        }
-//    }
-//
-//    @Override
-//    public void updateSendRTPSever(SendRtpItem sendRtpItem) {
-//        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetup.getServerId() + "_" + sendRtpItem.getPlatformId() + "_" + sendRtpItem.getChannelId();
-//        redis.set(key, sendRtpItem);
-//    }
-//
-//    @Override
-//    public SendRtpItem querySendRTPServer(String platformGbId, String channelId) {
-//        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetup.getServerId() + "_" + platformGbId + "_" + channelId;
-//        return (SendRtpItem)redis.get(key);
-//    }
-//
-//    @Override
-//    public List<SendRtpItem> querySendRTPServer(String platformGbId) {
-//        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetup.getServerId() + "_" + platformGbId + "_*";
-//        List<Object> queryResult = redis.scan(key);
-//        List<SendRtpItem> result= new ArrayList<>();
-//
-//        for (int i = 0; i < queryResult.size(); i++) {
-//            String keyItem = (String) queryResult.get(i);
-//            result.add((SendRtpItem)redis.get(keyItem));
-//        }
-//
-//        return result;
-//    }
-//
-//    /**
-//     * 删除RTP推送信息缓存
-//     * @param platformGbId
-//     * @param channelId
-//     */
-//    @Override
-//    public void deleteSendRTPServer(String platformGbId, String channelId) {
-//        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetup.getServerId() + "_" + platformGbId + "_" + channelId;
-//        redis.del(key);
-//    }
-//
-//    /**
-//     * 查询某个通道是否存在上级点播(RTP推送)
-//     * @param channelId
-//     */
-//    @Override
-//    public boolean isChannelSendingRTP(String channelId) {
-//        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetup.getServerId() + "_" + "*_" + channelId;
-//        List<Object> RtpStreams = redis.scan(key);
-//        if (RtpStreams.size() > 0) {
-//            return true;
-//        } else {
-//            return false;
-//        }
-//    }
-//
-//    @Override
-//    public void clearCatchByDeviceId(String deviceId) {
-//        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX,
-//                userSetup.getServerId(),
-//                deviceId));
-//        if (playLeys.size() > 0) {
-//            for (Object key : playLeys) {
-//                redis.del(key.toString());
-//            }
-//        }
-//
-//        List<Object> playBackers = redis.scan(String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX,
-//                userSetup.getServerId(),
-//                deviceId));
-//        if (playBackers.size() > 0) {
-//            for (Object key : playBackers) {
-//                redis.del(key.toString());
-//            }
-//        }
-//
-//        List<Object> deviceCache = redis.scan(String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX,
-//                userSetup.getServerId(),
-//                deviceId));
-//        if (deviceCache.size() > 0) {
-//            for (Object key : deviceCache) {
-//                redis.del(key.toString());
-//            }
-//        }
-//    }
-//
-//    @Override
-//    public void outlineForAll() {
-//        List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_" + "*" );
-//        for (int i = 0; i < onlineDevices.size(); i++) {
-//            String key = (String) onlineDevices.get(i);
-//            redis.del(key);
-//        }
-//    }
-//
-//    @Override
-//    public List<String> getOnlineForAll() {
-//        List<String> result = new ArrayList<>();
-//        List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_"  + "*" );
-//        for (int i = 0; i < onlineDevices.size(); i++) {
-//            String key = (String) onlineDevices.get(i);
-//            result.add((String) redis.get(key));
-//        }
-//        return result;
-//    }
-//
-//    @Override
-//    public void updateWVPInfo(JSONObject jsonObject, int time) {
-//        String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetup.getServerId();
-//        redis.set(key, jsonObject, time);
-//    }
-//
-//    @Override
-//    public void sendStreamChangeMsg(String type, JSONObject jsonObject) {
-//        String key = VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + type;
-//        log.debug("[redis 流变化事件] {}: {}", key, jsonObject.toString());
-//        redis.convertAndSend(key, jsonObject);
-//    }
-//
-//    @Override
-//    public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) {
-//        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + userSetup.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
-//        redis.set(key, mediaItem);
-//    }
-//
-//    @Override
-//    public void removeStream(String mediaServerId, String type, String app, String streamId) {
-//        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_"  + app + "_" + streamId + "_" + mediaServerId;
-//        redis.del(key);
-//    }
-//
-//    @Override
-//    public StreamInfo queryDownloadByStreamId(String streamId) {
-//        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(), streamId));
-//        if (playLeys == null || playLeys.size() == 0) return null;
-//        return (StreamInfo)redis.get(playLeys.get(0).toString());
-//    }
-//
-//    @Override
+//        return (ParentPlatformCatch)redis.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + serverId + "_" + platformGbId);
+//    }
+
+
+    public void delPlatformCatchInfo(String platformGbId) {
+        redis.del(VideoManagerConstants.PLATFORM_CATCH_PREFIX + serverId + "_" + platformGbId);
+    }
+
+
+    public void delPlatformKeepalive(String platformGbId) {
+        redis.del(VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + serverId + "_" + platformGbId);
+    }
+
+
+    public void delPlatformRegister(String platformGbId) {
+        redis.del(VideoManagerConstants.PLATFORM_REGISTER_PREFIX + serverId + "_" + platformGbId);
+    }
+
+
+
+    public void updatePlatformRegisterInfo(String callId, String platformGbId) {
+        String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + serverId + "_" + callId;
+        redis.set(key, platformGbId);
+    }
+
+
+
+    public String queryPlatformRegisterInfo(String callId) {
+        return (String)redis.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + serverId + "_" + callId);
+    }
+
+
+    public void delPlatformRegisterInfo(String callId) {
+        redis.del(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + serverId + "_" + callId);
+    }
+
+
+    public void cleanPlatformRegisterInfos() {
+        List regInfos = redis.scan(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + serverId + "_" + "*");
+        for (Object key : regInfos) {
+            redis.del(key.toString());
+        }
+    }
+
+
+    public void updateSendRTPSever(SendRtpItem sendRtpItem) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + serverId + "_" + sendRtpItem.getPlatformId() + "_" + sendRtpItem.getChannelId();
+        redis.set(key, sendRtpItem);
+    }
+
+
+    public SendRtpItem querySendRTPServer(String platformGbId, String channelId) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + serverId + "_" + platformGbId + "_" + channelId;
+        return (SendRtpItem)redis.get(key);
+    }
+
+
+    public List<SendRtpItem> querySendRTPServer(String platformGbId) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + serverId + "_" + platformGbId + "_*";
+        List<Object> queryResult = redis.scan(key);
+        List<SendRtpItem> result= new ArrayList<>();
+
+        for (int i = 0; i < queryResult.size(); i++) {
+            String keyItem = (String) queryResult.get(i);
+            result.add((SendRtpItem)redis.get(keyItem));
+        }
+
+        return result;
+    }
+
+    /**
+     * 删除RTP推送信息缓存
+     * @param platformGbId
+     * @param channelId
+     */
+
+    public void deleteSendRTPServer(String platformGbId, String channelId) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + serverId + "_" + platformGbId + "_" + channelId;
+        redis.del(key);
+    }
+
+    /**
+     * 查询某个通道是否存在上级点播(RTP推送)
+     * @param channelId
+     */
+
+    public boolean isChannelSendingRTP(String channelId) {
+        String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + serverId + "_" + "*_" + channelId;
+        List<Object> RtpStreams = redis.scan(key);
+        if (RtpStreams.size() > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    public void clearCatchByDeviceId(String deviceId) {
+        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX,
+                serverId,
+                deviceId));
+        if (playLeys.size() > 0) {
+            for (Object key : playLeys) {
+                redis.del(key.toString());
+            }
+        }
+
+        List<Object> playBackers = redis.scan(String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX,
+                serverId,
+                deviceId));
+        if (playBackers.size() > 0) {
+            for (Object key : playBackers) {
+                redis.del(key.toString());
+            }
+        }
+
+        List<Object> deviceCache = redis.scan(String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX,
+                serverId,
+                deviceId));
+        if (deviceCache.size() > 0) {
+            for (Object key : deviceCache) {
+                redis.del(key.toString());
+            }
+        }
+    }
+
+
+    public void outlineForAll() {
+        List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + serverId + "_" + "*" );
+        for (int i = 0; i < onlineDevices.size(); i++) {
+            String key = (String) onlineDevices.get(i);
+            redis.del(key);
+        }
+    }
+
+
+    public List<String> getOnlineForAll() {
+        List<String> result = new ArrayList<>();
+        List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + serverId + "_"  + "*" );
+        for (int i = 0; i < onlineDevices.size(); i++) {
+            String key = (String) onlineDevices.get(i);
+            result.add((String) redis.get(key));
+        }
+        return result;
+    }
+
+
+    public void updateWVPInfo(JSONObject jsonObject, int time) {
+        String key = VideoManagerConstants.WVP_SERVER_PREFIX + serverId;
+        redis.set(key, jsonObject, time);
+    }
+
+
+    public void sendStreamChangeMsg(String type, JSONObject jsonObject) {
+        String key = VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + type;
+        log.debug("[redis 流变化事件] {}: {}", key, jsonObject.toString());
+        redis.convertAndSend(key, jsonObject);
+    }
+
+
+    public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) {
+        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + serverId + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
+        redis.set(key, mediaItem);
+    }
+
+
+    public void removeStream(String mediaServerId, String type, String app, String streamId) {
+        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + serverId + "_" + type + "_"  + app + "_" + streamId + "_" + mediaServerId;
+        redis.del(key);
+    }
+
+
+    public StreamInfo queryDownloadByStreamId(String streamId) {
+        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.DOWNLOAD_PREFIX, serverId, streamId));
+        if (playLeys == null || playLeys.size() == 0) {
+            return null;
+        }
+        return (StreamInfo)redis.get(playLeys.get(0).toString());
+    }
+
+
 //    public ThirdPartyGB queryMemberNoGBId(String queryKey) {
 //        String key = VideoManagerConstants.WVP_STREAM_GB_ID_PREFIX + queryKey;
 //        JSONObject jsonObject = (JSONObject)redis.get(key);
 //        return  JSONObject.toJavaObject(jsonObject, ThirdPartyGB.class);
 //    }
-//
-//    @Override
-//    public void removeStream(String mediaServerId, String type) {
-//        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_*_*_" + mediaServerId;
-//        List<Object> streams = redis.scan(key);
-//        for (Object stream : streams) {
-//            redis.del((String) stream);
-//        }
-//    }
-//
-//    @Override
-//    public List<MediaItem> getStreams(String mediaServerId, String type) {
-//        List<MediaItem> result = new ArrayList<>();
-//        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_*_*_" + mediaServerId;
-//        List<Object> streams = redis.scan(key);
-//        for (Object stream : streams) {
-//            MediaItem mediaItem = (MediaItem)redis.get((String) stream);
-//            result.add(mediaItem);
-//        }
-//        return result;
-//    }
-//
-//    @Override
-//    public void updateDevice(MediaDevice device) {
-//        String key = VideoManagerConstants.DEVICE_PREFIX + userSetup.getServerId() + "_" + device.getId();
-//        redis.set(key, device);
-//    }
-//
-//    @Override
-//    public void removeDevice(String deviceId) {
-//        String key = VideoManagerConstants.DEVICE_PREFIX + userSetup.getServerId() + "_" + deviceId;
-//        redis.del(key);
-//    }
-//
-//    @Override
-//    public MediaDevice getDevice(String deviceId) {
-//        String key = VideoManagerConstants.DEVICE_PREFIX + userSetup.getServerId() + "_" + deviceId;
-//        return (MediaDevice)redis.get(key);
-//    }
-//
-//    @Override
+
+
+    public void removeStream(String mediaServerId, String type) {
+        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + serverId + "_" + type + "_*_*_" + mediaServerId;
+        List<Object> streams = redis.scan(key);
+        for (Object stream : streams) {
+            redis.del((String) stream);
+        }
+    }
+
+
+    public List<MediaItem> getStreams(String mediaServerId, String type) {
+        List<MediaItem> result = new ArrayList<>();
+        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + serverId + "_" + type + "_*_*_" + mediaServerId;
+        List<Object> streams = redis.scan(key);
+        for (Object stream : streams) {
+            MediaItem mediaItem = (MediaItem)redis.get((String) stream);
+            result.add(mediaItem);
+        }
+        return result;
+    }
+
+
+    public void updateDevice(MediaDevice device) {
+        String key = VideoManagerConstants.DEVICE_PREFIX + serverId + "_" + device.getId();
+        redis.set(key, device);
+    }
+
+
+    public void removeDevice(String deviceId) {
+        String key = VideoManagerConstants.DEVICE_PREFIX + serverId + "_" + deviceId;
+        redis.del(key);
+    }
+
+
+    public MediaDevice getDevice(String deviceId) {
+        String key = VideoManagerConstants.DEVICE_PREFIX + serverId + "_" + deviceId;
+        return (MediaDevice)redis.get(key);
+    }
+
+
 //    public void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo) {
-//        String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetup.getServerId() + "_" + gpsMsgInfo.getId();
+//        String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + serverId + "_" + gpsMsgInfo.getId();
 //        redis.set(key, gpsMsgInfo, 60); // 默认GPS消息保存1分钟
 //    }
 //
-//    @Override
+//
 //    public GPSMsgInfo getGpsMsgInfo(String gbId) {
-//        String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetup.getServerId() + "_" + gbId;
+//        String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + serverId + "_" + gbId;
 //        return (GPSMsgInfo)redis.get(key);
 //    }
 //
-//    @Override
+//
 //    public void updateSubscribe(String key, SubscribeInfo subscribeInfo) {
 //        redis.set(key, subscribeInfo, subscribeInfo.getExpires());
 //    }
 //
-//    @Override
+//
 //    public SubscribeInfo getSubscribe(String key) {
 //        return (SubscribeInfo)redis.get(key);
 //    }
 //
-//    @Override
+//
 //    public void delSubscribe(String key) {
 //        redis.del(key);
 //    }
 //
-//    @Override
+//
 //    public List<GPSMsgInfo> getAllGpsMsgInfo() {
-//        String scanKey = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetup.getServerId() + "_*";
+//        String scanKey = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + serverId + "_*";
 //        List<GPSMsgInfo> result = new ArrayList<>();
 //        List<Object> keys = redis.scan(scanKey);
 //        for (int i = 0; i < keys.size(); i++) {
@@ -499,18 +506,19 @@
 //
 //        return result;
 //    }
-//
-//    @Override
-//    public MediaItem getStreamInfo(String app, String streamId, String mediaServerId) {
-//        String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + userSetup.getServerId() + "_*_" + app + "_" + streamId + "_" + mediaServerId;
-//
-//        MediaItem result = null;
-//        List<Object> keys = redis.scan(scanKey);
-//        if (keys.size() > 0) {
-//            String key = (String) keys.get(0);
-//            result = (MediaItem)redis.get(key);
-//        }
-//
-//        return result;
-//    }
-//}
+
+
+    public MediaItem getStreamInfo(String app, String streamId, String mediaServerId) {
+        String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + serverId + "_*_" + app + "_" + streamId + "_" + mediaServerId;
+
+        MediaItem result = null;
+        List<Object> keys = redis.scan(scanKey);
+        if (keys.size() > 0) {
+            String key = (String) keys.get(0);
+            result = (MediaItem)redis.get(key);
+        }
+
+        return result;
+    }
+
+}

+ 10 - 17
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/transmit/SIPRequestHeaderProvider.java

@@ -2,16 +2,12 @@ package org.jetlinks.community.media.transmit;
 
 
 import gov.nist.javax.sip.header.SIPDateHeader;
-import lombok.AllArgsConstructor;
 import org.jetlinks.community.media.bean.StreamInfo;
 import org.jetlinks.community.media.entity.MediaDevice;
 import org.jetlinks.community.media.entity.SipServerConfig;
 import org.jetlinks.community.media.entity.WvpSipDate;
 import org.jetlinks.community.media.sip.SipContext;
-import org.jetlinks.community.media.storage.IRedisCatchStorage;
-import org.jetlinks.community.utils.RedisUtil;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.RedisTemplate;
+import org.jetlinks.community.media.storage.impl.RedisCatchStorageImpl;
 import org.springframework.stereotype.Component;
 
 import javax.sip.Dialog;
@@ -38,7 +34,7 @@ public class SIPRequestHeaderProvider {
 
 
 
-	private IRedisCatchStorage redisCatchStorage;
+	private RedisCatchStorageImpl redisCatchStorage;
 
 //	@Autowired
 //	private VideoStreamSessionManager streamSession;
@@ -75,14 +71,13 @@ public class SIPRequestHeaderProvider {
 		request.setContent(content, contentTypeHeader);
 		return request;
 	}
-	int count=1;
+
 	public Request createInviteRequest(MediaDevice device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
         SipServerConfig sipConfig=SipContext.getConfig();
         SipFactory sipFactory=SipContext.getSipFactory();
 		Request request = null;
 		//请求行
 		SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
-//        SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
 		//via
 		ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
 		ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getHost(), sipConfig.getPort(), device.getTransport(), viaTag);
@@ -92,7 +87,6 @@ public class SIPRequestHeaderProvider {
 
 		//from
 		SipURI fromSipUrl = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
-//        SipURI fromSipUrl = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getHost()+":"+sipConfig.getPort());
 		Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipUrl);
 		FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
 		//必须要有标记,否则无法创建会话,无法回应ack
@@ -100,16 +94,15 @@ public class SIPRequestHeaderProvider {
 		SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,sipConfig.getDomain());
 		Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
 		ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null);
-		
+
 		//Forwards
 		MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
 
 
         //ceq
-//		CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.INVITE), Request.INVITE);
-        CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(++count, Request.INVITE);
+		CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.INVITE), Request.INVITE);
 		request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
-		
+
 		Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getHost()+":"+sipConfig.getPort()));
         request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
 		// Subject    媒体流发送者设备编码:发送端媒体流序列号,媒体流接收者设备编码:接收端媒体流序列号
@@ -131,7 +124,7 @@ public class SIPRequestHeaderProvider {
 		request.setContent(content, contentTypeHeader);
 		return request;
 	}
-	
+
 	public Request createPlaybackInviteRequest(MediaDevice device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
         SipServerConfig sipConfig=SipContext.getConfig();
         SipFactory sipFactory=SipContext.getSipFactory();
@@ -151,14 +144,14 @@ public class SIPRequestHeaderProvider {
 		SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId, sipConfig.getDomain());
 		Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
 		ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,null);
-		
+
 		//Forwards
 		MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
-		
+
 		//ceq
 		CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.INVITE), Request.INVITE);
 		request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
-		
+
 		Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getHost()+":"+sipConfig.getPort()));
 		// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
 		request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));

+ 1 - 5
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/transmit/cmd/SipCommander.java

@@ -8,8 +8,7 @@ import org.jetlinks.community.media.entity.MediaDevice;
 import org.jetlinks.community.media.entity.SipServerConfig;
 import org.jetlinks.community.media.sip.SipContext;
 import org.jetlinks.community.media.transmit.SIPRequestHeaderProvider;
-import org.jetlinks.community.media.zlm.ZLMHttpHookSubscribe;
-import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 import org.springframework.stereotype.Service;
 import reactor.core.publisher.*;
 
@@ -20,7 +19,6 @@ import java.text.ParseException;
 import java.time.Duration;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Consumer;
 
 /**
  * @author lifang
@@ -65,10 +63,8 @@ public class SipCommander {
             StringBuffer content = new StringBuffer(200);
             content.append("v=0\r\n");
             content.append("o="+ sipConfig.getId()+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
-//            content.append("o=34020000002000000001 0 0 IN IP4 192.168.104.244 \r\n");
             content.append("s=Play\r\n");
             content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
-//            content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
             content.append("t=0 0\r\n");
 
             //是否需要扩展sdp

+ 140 - 179
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMHttpHookListener.java

@@ -1,77 +1,38 @@
-//package org.jetlinks.community.media.zlm;
-//
-//import com.alibaba.fastjson.JSON;
-//import com.alibaba.fastjson.JSONObject;
-//import com.genersoft.iot.vmp.common.StreamInfo;
-//import com.genersoft.iot.vmp.conf.MediaConfig;
-//import com.genersoft.iot.vmp.conf.UserSetup;
-//import com.genersoft.iot.vmp.gb28181.bean.Device;
-//import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
-//import com.genersoft.iot.vmp.media.zlm.dto.*;
-//import com.genersoft.iot.vmp.service.*;
-//import com.genersoft.iot.vmp.service.bean.SSRCInfo;
-//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.http.HttpStatus;
-//import org.springframework.http.ResponseEntity;
-//import org.springframework.web.bind.annotation.*;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import java.util.List;
-//import java.util.UUID;
-//
-///**
-// * @description:针对 ZLMediaServer的hook事件监听
-// * @author: swwheihei
-// * @date:   2020年5月8日 上午10:46:48
-// */
-//@RestController
-//@RequestMapping("/index/hook")
-//public class ZLMHttpHookListener {
-//
-//	private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
-//
-//	@Autowired
-//	private SIPCommander cmder;
-//
-//	@Autowired
-//	private IPlayService playService;
-//
-//	@Autowired
-//	private IVideoManagerStorager storager;
-//
-//	@Autowired
-//	private IRedisCatchStorage redisCatchStorage;
-//
-//	@Autowired
-//	private IMediaServerService mediaServerService;
-//
-//	@Autowired
-//	private IStreamProxyService streamProxyService;
-//
-//	@Autowired
-//	private IStreamPushService streamPushService;
-//
-//	@Autowired
-//	private IMediaService mediaService;
-//
-//	@Autowired
-//	private ZLMRESTfulUtils zlmresTfulUtils;
-//
-//	 @Autowired
-//	 private ZLMMediaListManager zlmMediaListManager;
-//
-//	@Autowired
-//	private ZLMHttpHookSubscribe subscribe;
-//
-//	@Autowired
-//	private UserSetup userSetup;
-//
-//	@Autowired
-//	private MediaConfig mediaConfig;
+package org.jetlinks.community.media.zlm;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.authorization.annotation.Authorize;
+import org.jetlinks.community.media.bean.StreamInfo;
+import org.jetlinks.community.media.service.LocalMediaServerItemServiceImpl;
+import org.jetlinks.community.media.storage.impl.RedisCatchStorageImpl;
+import org.jetlinks.community.media.zlm.dto.MediaItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
+import org.jetlinks.community.media.zlm.dto.OriginType;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Mono;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * @description:针对 ZLMediaServer的hook事件监听
+ * @author: swwheihei
+ * @date:   2020年5月8日 上午10:46:48
+ */
+@RestController
+@RequestMapping("/index/hook")
+@Slf4j
+@Authorize(ignore = true)
+@AllArgsConstructor
+public class ZLMHttpHookListener {
+    private final LocalMediaServerItemServiceImpl mediaServerItemService;
+    private final RedisCatchStorageImpl redisCatchStorage;
+    private final ZLMHttpHookSubscribe subscribe;
 //
 //	/**
 //	 * 服务器定时上报时间,上报间隔可配置,默认10s上报一次
@@ -288,86 +249,91 @@
 //		return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
 //	}
 //
-//	/**
-//	 * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
-//	 *
-//	 */
+    /**
+     * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
+     *
+     */
 //	@ResponseBody
-//	@PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
-//	public ResponseEntity<String> onStreamChanged(@RequestBody MediaItem item){
-//
-//		if (logger.isDebugEnabled()) {
-//			logger.debug("[ ZLM HOOK ]on_stream_changed API调用,参数:" + JSONObject.toJSONString(item));
-//		}
-//		String mediaServerId = item.getMediaServerId();
-//		JSONObject json = (JSONObject) JSON.toJSON(item);
-//		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
-//		if (subscribe != null ) {
-//			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
-//			if (mediaInfo != null) {
-//				subscribe.response(mediaInfo, json);
-//			}
-//
-//		}
-//		// 流消失移除redis play
-//		String app = item.getApp();
-//		String streamId = item.getStream();
-//		String schema = item.getSchema();
-//		List<MediaItem.MediaTrack> tracks = item.getTracks();
-//		boolean regist = item.isRegist();
-//		if ("rtmp".equals(schema)){
-//			logger.info("on_stream_changed:注册->{}, app->{}, stream->{}", regist, app, streamId);
-//			if (regist) {
-//				mediaServerService.addCount(mediaServerId);
-//			}else {
-//				mediaServerService.removeCount(mediaServerId);
-//			}
-//			if ("rtp".equals(app) && !regist ) {
-//				StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
-//				if (streamInfo!=null){
-//					redisCatchStorage.stopPlay(streamInfo);
-//					storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
-//				}else{
-//					streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
-//					redisCatchStorage.stopPlayback(streamInfo);
-//				}
-//			}else {
-//				if (!"rtp".equals(app)){
-//					String type = OriginType.values()[item.getOriginType()].getType();
-//					MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
-//					if (mediaServerItem != null){
-//						if (regist) {
-//							redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
-//							if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
-//									|| item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
-//									|| item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) {
-//								zlmMediaListManager.addPush(item);
-//							}
-//						}else {
-//							// 兼容流注销时类型从redis记录获取
-//							MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, streamId, mediaServerId);
-//							type = OriginType.values()[mediaItem.getOriginType()].getType();
-//							zlmMediaListManager.removeMedia(app, streamId);
-//							redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId);
-//						}
-//						// 发送流变化redis消息
-//						JSONObject jsonObject = new JSONObject();
-//						jsonObject.put("serverId", userSetup.getServerId());
-//						jsonObject.put("app", app);
-//						jsonObject.put("stream", streamId);
-//						jsonObject.put("register", regist);
-//						jsonObject.put("mediaServerId", mediaServerId);
-//						redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
-//					}
-//				}
-//			}
-//		}
-//
-//		JSONObject ret = new JSONObject();
-//		ret.put("code", 0);
-//		ret.put("msg", "success");
-//		return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
-//	}
+    @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
+    public Mono<ResponseEntity<String>> onStreamChanged(@RequestBody MediaItem item){
+        if (log.isDebugEnabled()) {
+            log.debug("[ ZLM HOOK ]on_stream_changed API调用,参数:" + JSONUtil.toJsonStr(item));
+        }
+        String mediaServerId = item.getMediaServerId();
+        JSONObject json = JSONUtil.parseObj(item);
+        Mono<ResponseEntity<String>> result=null;
+        //todo 这里订阅/发布采用eventBus 模式进行
+//        ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
+//        if (subscribe != null ) {
+//            MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+//            if (mediaInfo != null) {
+//                subscribe.response(mediaInfo, json);
+//            }
+//        }
+        // 流消失移除redis play
+        //获取流应用名
+        String app = item.getApp();
+        //获取流ID
+        String streamId = item.getStream();
+        //rtsp或rtmp
+        String schema = item.getSchema();
+        //音频轨道
+        List<MediaItem.MediaTrack> tracks = item.getTracks();
+        boolean regist = item.isRegist();
+        if ("rtmp".equals(schema)){
+            log.info("on_stream_changed:注册(true)/注销(false)->{}, app->{}, stream->{}", regist, app, streamId);
+            if (regist) {
+                result=mediaServerItemService.addCount(mediaServerId).then(Mono.empty());
+            }else {
+                result=mediaServerItemService.removeCount(mediaServerId).then(Mono.empty());
+            }
+            if ("rtp".equals(app) && !regist ) {
+                StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
+                if (streamInfo!=null){
+                    redisCatchStorage.stopPlay(streamInfo);
+//                    storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
+                }else{
+                    streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
+//                    redisCatchStorage.stopPlayback(streamInfo);
+                }
+            }else {
+                if (!"rtp".equals(app)){
+                    String type = OriginType.values()[item.getOriginType()].getType();
+//                    MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+                    MediaServerItem mediaServerItem =null;
+                    if (mediaServerItem != null){
+                        if (regist) {
+                            redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
+                            if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
+                                || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
+                                || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) {
+//                                zlmMediaListManager.addPush(item);
+                            }
+                        }else {
+                            // 兼容流注销时类型从redis记录获取
+                            MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, streamId, mediaServerId);
+                            type = OriginType.values()[mediaItem.getOriginType()].getType();
+//                            zlmMediaListManager.removeMedia(app, streamId);
+                            redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId);
+                        }
+                        // 发送流变化redis消息
+                        JSONObject jsonObject = new JSONObject()
+                            .append("serverId", mediaServerId)
+                            .append("app", app)
+                            .append("stream", streamId)
+                            .append("register", regist)
+                            .append("mediaServerId", mediaServerId);
+                        redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
+                    }
+                }
+            }
+        }
+        JSONObject ret = new JSONObject()
+            .append("code", 0)
+            .append("msg", "success");
+        return result==null?Mono.just(ResponseEntity.ok(ret.toString())):result.thenReturn(ResponseEntity.ok(ret.toString()));
+//        return Mono.just(ResponseEntity.ok(ret.toString()));
+    }
 //
 //	/**
 //	 * 流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流。
@@ -474,29 +440,24 @@
 //		ret.put("msg", "success");
 //		return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
 //	}
-//
-//	/**
-//	 * 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。
-//	 *
-//	 */
-//	@ResponseBody
-//	@PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
-//	public ResponseEntity<String> onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
-//
-//		if (logger.isDebugEnabled()) {
-//			logger.debug("[ ZLM HOOK ]on_server_started API调用,参数:" + jsonObject.toString());
-//		}
-//		String remoteAddr = request.getRemoteAddr();
-//		jsonObject.put("ip", remoteAddr);
-//		List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started);
-//		if (subscribes != null  && subscribes.size() > 0) {
-//			for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
-//				subscribe.response(null, jsonObject);
-//			}
-//		}
-//		JSONObject ret = new JSONObject();
-//		ret.put("code", 0);
-//		ret.put("msg", "success");
-//		return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
-//	}
-//}
+
+    /**
+     * 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。
+     *
+     */
+    @ResponseBody
+    @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
+    public Mono<ResponseEntity<String>> onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){
+        if (log.isDebugEnabled()) {
+            log.debug("[ ZLM HOOK ]on_server_started API调用,参数:" + jsonObject.toString());
+        }
+
+        String remoteAddr = request.getRemoteAddr();
+        jsonObject.append("ip", remoteAddr);
+        subscribe.publish(ZLMHttpHookSubscribe.HookType.on_server_started,null,jsonObject);
+        JSONObject ret = new JSONObject()
+            .append("code", 0)
+            .append("msg", "success");
+        return Mono.just(ResponseEntity.ok(ret.toString()));
+    }
+}

+ 31 - 19
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMHttpHookSubscribe.java

@@ -1,11 +1,12 @@
 package org.jetlinks.community.media.zlm;
 
-import com.alibaba.fastjson.JSONObject;
-import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+import cn.hutool.json.JSONObject;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 import org.springframework.stereotype.Component;
 
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiFunction;
 
 /**
  * @description:针对 ZLMediaServer的hook事件订阅
@@ -31,19 +32,17 @@ public class ZLMHttpHookSubscribe {
         on_server_keepalive
     }
 
-    public interface Event{
-        void response(MediaServerItem mediaServerItem, JSONObject response);
+    public interface Event extends BiFunction<MediaServerItem, JSONObject,Void>{
+
     }
 
-    private Map<HookType, Map<JSONObject, Event>> allSubscribes = new ConcurrentHashMap<>();
+    private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
+
 
     public void addSubscribe(HookType type, JSONObject hookResponse, ZLMHttpHookSubscribe.Event event) {
-        Map<JSONObject, Event> eventMap = allSubscribes.get(type);
-        if (eventMap == null) {
-            eventMap = new HashMap<JSONObject, Event>();
-            allSubscribes.put(type,eventMap);
-        }
-        eventMap.put(hookResponse, event);
+         allSubscribes
+             .computeIfAbsent(type,k->new HashMap<>())
+             .put(hookResponse,event);
     }
 
     public ZLMHttpHookSubscribe.Event getSubscribe(HookType type, JSONObject hookResponse) {
@@ -56,12 +55,12 @@ public class ZLMHttpHookSubscribe {
             Boolean result = null;
             for (String s : key.keySet()) {
                 if (result == null) {
-                    result = key.getString(s).equals(hookResponse.getString(s));
+                    result = key.getStr(s).equals(hookResponse.getStr(s));
                 }else {
-                    if (key.getString(s) == null) {
+                    if (key.getStr(s) == null) {
                         continue;
                     }
-                    result = result && key.getString(s).equals(hookResponse.getString(s));
+                    result = result && key.getStr(s).equals(hookResponse.getStr(s));
                 }
 
             }
@@ -84,10 +83,12 @@ public class ZLMHttpHookSubscribe {
             Boolean result = null;
             for (String s : key.keySet()) {
                 if (result == null) {
-                    result = key.getString(s).equals(hookResponse.getString(s));
+                    result = key.getStr(s).equals(hookResponse.getStr(s));
                 }else {
-                    if (key.getString(s) == null) continue;
-                    result = result && key.getString(s).equals(hookResponse.getString(s));
+                    if (key.getStr(s) == null) {
+                        continue;
+                    }
+                    result = result && key.getStr(s).equals(hookResponse.getStr(s));
                 }
             }
             if (null != result && result){
@@ -101,18 +102,29 @@ public class ZLMHttpHookSubscribe {
      * @param type
      * @return
      */
-    public List<Event> getSubscribes(HookType type) {
+    public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) {
         // ZLMHttpHookSubscribe.Event event= null;
         Map<JSONObject, Event> eventMap = allSubscribes.get(type);
         if (eventMap == null) {
             return null;
         }
-        List<Event> result = new ArrayList<>();
+        List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>();
         for (JSONObject key : eventMap.keySet()) {
             result.add(eventMap.get(key));
         }
         return result;
     }
 
+    /**
+     * 向订阅进行发布
+     * @param type
+     * @return
+     */
+    public void publish(HookType type,MediaServerItem item,JSONObject object) {
+        Optional
+            .ofNullable(getSubscribes(type))
+            .orElse(new ArrayList<>())
+            .forEach(subscribe->subscribe.apply(item,object));
+    }
 
 }

+ 5 - 5
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMRESTfulUtils.java

@@ -1,10 +1,10 @@
 package org.jetlinks.community.media.zlm;
 
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.*;
-import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 import org.springframework.stereotype.Component;
 
 import javax.validation.constraints.NotNull;
@@ -55,7 +55,7 @@ public class ZLMRESTfulUtils {
                         ResponseBody responseBody = response.body();
                         if (responseBody != null) {
                             String responseStr = responseBody.string();
-                            responseJSON = JSON.parseObject(responseStr);
+                            responseJSON = JSONUtil.parseObj(responseStr);
                         }
                     }else {
                         response.close();
@@ -75,7 +75,7 @@ public class ZLMRESTfulUtils {
                         if (response.isSuccessful()) {
                             try {
                                 String responseStr = Objects.requireNonNull(response.body()).string();
-                                callback.run(JSON.parseObject(responseStr));
+                                callback.run(JSONUtil.parseObj(responseStr));
                             } catch (IOException e) {
                                 log.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));
                             }

+ 18 - 18
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMRTPServerFactory.java

@@ -1,11 +1,11 @@
 package org.jetlinks.community.media.zlm;
 
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.jetlinks.community.media.bean.SendRtpItem;
-import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 import org.springframework.stereotype.Component;
 import org.springframework.util.StringUtils;
 
@@ -29,7 +29,7 @@ public class ZLMRTPServerFactory {
             if (data != null) {
                 for (int i = 0; i < data.size(); i++) {
                     JSONObject dataItem = data.getJSONObject(i);
-                    currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
+                    currentStreams.put(dataItem.getStr("stream_id"), dataItem.getInt("port"));
                 }
             }
         }
@@ -57,9 +57,9 @@ public class ZLMRTPServerFactory {
         JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
 
         if (openRtpServerResultJson != null) {
-            switch (openRtpServerResultJson.getInteger("code")){
+            switch (openRtpServerResultJson.getInt("code")){
                 case 0:
-                    result= openRtpServerResultJson.getInteger("port");
+                    result= openRtpServerResultJson.getInt("port");
                     break;
                 case -300: // id已经存在, 可能已经在其他端口推流
                     Map<String, Object> closeRtpServerParam = new HashMap<>();
@@ -71,7 +71,7 @@ public class ZLMRTPServerFactory {
                     result= createRTPServer(mediaServerItem, streamId);
                     break;
                 default:
-                    log.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"),  param.get("port"));
+                    log.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getStr("msg"),  param.get("port"));
                     break;
             }
         }else {
@@ -88,10 +88,10 @@ public class ZLMRTPServerFactory {
             param.put("stream_id", streamId);
             JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param);
             if (jsonObject != null ) {
-                if (jsonObject.getInteger("code") == 0) {
-                    result = jsonObject.getInteger("hit") == 1;
+                if (jsonObject.getInt("code") == 0) {
+                    result = jsonObject.getInt("hit") == 1;
                 }else {
-                    log.error("关闭RTP Server 失败: " + jsonObject.getString("msg"));
+                    log.error("关闭RTP Server 失败: " + jsonObject.getStr("msg"));
                 }
             }else {
                 //  检查ZLM状态
@@ -208,11 +208,11 @@ public class ZLMRTPServerFactory {
         JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
         if (jsonObject == null) {
             log.error("RTP推流失败: 请检查ZLM服务");
-        } else if (jsonObject.getInteger("code") == 0) {
+        } else if (jsonObject.getInt("code") == 0) {
             result= true;
-            log.info("RTP推流[ {}/{} ]请求成功,本地推流端口:{}" ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"));
+            log.info("RTP推流[ {}/{} ]请求成功,本地推流端口:{}" ,param.get("app"), param.get("stream"), jsonObject.getStr("local_port"));
         } else {
-            log.error("RTP推流失败: " + jsonObject.getString("msg"));
+            log.error("RTP推流失败: " + jsonObject.getStr("msg"));
         }
         return result;
     }
@@ -222,7 +222,7 @@ public class ZLMRTPServerFactory {
      */
     public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) {
         JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtmp", streamId);
-        return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
+        return (mediaInfo.getInt("code") == 0 && mediaInfo.getBool("online"));
     }
 
     /**
@@ -230,7 +230,7 @@ public class ZLMRTPServerFactory {
      */
     public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
         JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
-        return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
+        return (mediaInfo.getInt("code") == 0 && mediaInfo.getBool("online"));
     }
 
     /**
@@ -243,7 +243,7 @@ public class ZLMRTPServerFactory {
         if (mediaInfo == null) {
             return 0;
         }
-        return mediaInfo.getInteger("totalReaderCount");
+        return mediaInfo.getInt("totalReaderCount");
     }
 
     /**
@@ -254,11 +254,11 @@ public class ZLMRTPServerFactory {
         JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
         if (jsonObject == null) {
             log.error("停止RTP推流失败: 请检查ZLM服务");
-        } else if (jsonObject.getInteger("code") == 0) {
+        } else if (jsonObject.getInt("code") == 0) {
             result= true;
             log.info("停止RTP推流成功");
         } else {
-            log.error("停止RTP推流失败: " + jsonObject.getString("msg"));
+            log.error("停止RTP推流失败: " + jsonObject.getStr("msg"));
         }
         return result;
     }

+ 230 - 195
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/ZLMRunner.java

@@ -1,200 +1,235 @@
-//package org.jetlinks.community.media.zlm;
-//
-//import com.alibaba.fastjson.JSON;
-//import com.alibaba.fastjson.JSONArray;
-//import com.alibaba.fastjson.JSONObject;
-//import com.genersoft.iot.vmp.conf.MediaConfig;
-//import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
-//import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
-//import com.genersoft.iot.vmp.service.IMediaServerService;
-//import com.genersoft.iot.vmp.service.IStreamProxyService;
-//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.beans.factory.annotation.Qualifier;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.core.annotation.Order;
-//import org.springframework.scheduling.annotation.Async;
-//import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-//import org.springframework.stereotype.Component;
-//import org.springframework.util.StringUtils;
-//
-//import java.util.*;
-//
-//@Component
-//@Order(value=1)
-//public class ZLMRunner implements CommandLineRunner {
-//
-//    private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class);
-//
-//    private Map<String, Boolean> startGetMedia;
-//
-//    @Autowired
-//    private ZLMRESTfulUtils zlmresTfulUtils;
-//
-//    @Autowired
-//    private ZLMHttpHookSubscribe hookSubscribe;
-//
-//    @Autowired
-//    private IStreamProxyService streamProxyService;
-//
+package org.jetlinks.community.media.zlm;
+
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.jetlinks.community.media.config.MediaConfig;
+import org.jetlinks.community.media.service.LocalMediaServerItemServiceImpl;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
+import java.time.Duration;
+import java.util.*;
+
+@Component
+@Slf4j
+@AllArgsConstructor
+@EnableConfigurationProperties(MediaConfig.class)
+public class ZLMRunner implements CommandLineRunner {
+
+    private Map<String, Boolean> startGetMedia;
+
+
+    private final ZLMRESTfulUtils zlmresTfulUtils;
+
+
+    private final ZLMHttpHookSubscribe hookSubscribe;
+
 //    @Autowired
 //    private EventPublisher publisher;
-//
-//    @Autowired
-//    private IMediaServerService mediaServerService;
-//
-//    @Autowired
-//    private IRedisCatchStorage redisCatchStorage;
-//
-//    @Autowired
-//    private MediaConfig mediaConfig;
-//
-//    @Qualifier("taskExecutor")
-//    @Autowired
-//    private ThreadPoolTaskExecutor taskExecutor;
-//
-//    @Override
-//    public void run(String... strings) throws Exception {
-//        mediaServerService.clearMediaServerForOnline();
-//        MediaServerItem defaultMediaServer = mediaServerService.getDefaultMediaServer();
-//        if (defaultMediaServer == null) {
-//            mediaServerService.addToDatabase(mediaConfig.getMediaSerItem());
-//        }else {
-//            MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
-//            mediaSerItem.setId(defaultMediaServer.getId());
-//            mediaServerService.updateToDatabase(mediaSerItem);
-//        }
-//
-//        // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
-//        hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
-//                (MediaServerItem mediaServerItem, JSONObject response)->{
-//            ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
-//            if (zlmServerConfig !=null ) {
-//                if (startGetMedia != null) {
-//                    startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
-//                }
-//                mediaServerService.zlmServerOnline(zlmServerConfig);
+
+    private final LocalMediaServerItemServiceImpl mediaServerItemService;
+
+    private final MediaConfig mediaConfig;
+
+
+    @Override
+    public void run(String... strings)  {
+        mediaServerItemService.clearMediaServerForOnline()
+            //获取默认服务器配置
+            .flatMap(ignore-> mediaServerItemService.getDefaultMediaServer())
+            //更新默认服务器配置
+            .flatMap(defaultMediaServer->{
+                MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
+                mediaSerItem.setId(defaultMediaServer.getId());
+                return mediaServerItemService.updateToDatabase(mediaSerItem);
+            })
+            //添加默认媒体服务器配置
+            .switchIfEmpty(mediaServerItemService.addToDatabase(mediaConfig.getMediaSerItem()).then(Mono.empty()))
+            //订阅 zlm启动事件
+            .flatMap(ignore->subscribeOnServerStarted())
+            //订阅 zlm保活事件
+            .flatMap(ignore->subscribeOnServerKeepalive())
+            .log()
+            //获取所有的zlm, 并开启主动连接
+            .flatMap(ignore->startAllConnection())
+
+            //20s进行超时处理
+            .delayElement(Duration.ofSeconds(20))
+
+            .flatMap(ignore->timeOutHandle())
+
+            .subscribe();
+    }
+
+    /**
+     * 连接超时处理
+     * @return  Mono
+     */
+    private Mono<Void> timeOutHandle(){
+        if (startGetMedia != null) {
+            Set<String> allZlmId = startGetMedia.keySet();
+            for (String id : allZlmId) {
+                log.error("[ {} ]]主动连接失败,不再主动连接", id);
+            }
+            startGetMedia = null;
+            //  TODO 清理数据库中与redis不匹配的zlm
+        }
+        return Mono.empty();
+    }
+    /**
+     * 订阅 zlm启动事件, 新的zlm也会从这里进入系统
+     * @return Mono
+     */
+    private Mono<Void> subscribeOnServerStarted(){
+        return Mono.fromRunnable(()->{
+            hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
+                (MediaServerItem mediaServerItem, JSONObject response)->{
+                    ZLMServerConfig zlmServerConfig = JSONUtil.toBean(response, ZLMServerConfig.class);
+                    if (zlmServerConfig !=null ) {
+                        if (startGetMedia != null) {
+                            startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
+                        }
+                        mediaServerItemService.zlmServerOnline(zlmServerConfig)
+                            .subscribe();
+                    }
+                    return null;
+                });
+        });
+    }
+
+    /**
+     * 订阅 zlm保活事件, 当zlm离线时做业务的处理
+     * @return Mono
+     */
+    private Mono<Void> subscribeOnServerKeepalive(){
+        return Mono.fromRunnable(()->{
+            // 订阅 zlm保活事件, 当zlm离线时做业务的处理
+            hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_keepalive,null,
+                (MediaServerItem mediaServerItem, JSONObject response)->{
+                    String mediaServerId = response.getStr("mediaServerId");
+                    if (mediaServerId !=null ) {
+                        mediaServerItemService
+                            .updateMediaServerKeepalive(mediaServerId, response.getJSONObject("data"))
+                            .subscribe();
+                    }
+                    return null;
+                });
+        });
+    }
+
+    /**
+     * 获取所有zlm 并开启主动连接
+     * @return  Mono
+     */
+    private Mono<Void> startAllConnection(){
+        return  mediaServerItemService
+            .createQuery()
+            .fetch()
+            .defaultIfEmpty(mediaConfig.getMediaSerItem())
+            .doOnNext(mediaServerItem ->{
+                //将媒体服务器进行标记
+                startGetMedia=Optional.ofNullable(startGetMedia).orElse(new HashMap<>());
+                startGetMedia.put(mediaServerItem.getId(), true);
+            })
+            .parallel()
+            .runOn(Schedulers.parallel())
+            .flatMap(this::connectZlmServer)
+            .then();
+
+    }
+
+
+
+    /**
+     * 连接服务器
+     * @param mediaServerItem
+     * @return  Mono
+     */
+    private Mono<Void> connectZlmServer(MediaServerItem mediaServerItem){
+        return getMediaServerConfig(mediaServerItem, 1)
+            .doOnNext(zlmServerConfig ->{
+                zlmServerConfig.setIp(mediaServerItem.getIp());
+                zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
+                startGetMedia.remove(mediaServerItem.getId());
+            } )
+            .flatMap(mediaServerItemService::zlmServerOnline);
+    }
+
+    private Mono<ZLMServerConfig> getMediaServerConfig(MediaServerItem mediaServerItem, Integer index) {
+        if (startGetMedia == null) { return Mono.empty();}
+
+        if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) {
+            return Mono.empty();
+        }
+        final int pos=index;
+        return  mediaServerItemService
+            .findById(mediaServerItem.getId())
+            .filter(ignore->Boolean.TRUE.equals(mediaServerItem.isDefaultServer()))
+            .flatMap(ignore->Mono.just( zlmresTfulUtils.getMediaServerConfig(mediaServerItem)))
+            .flatMap(responseJson->{
+                ZLMServerConfig zlmServerConfig=null;
+                JSONArray data = responseJson.getJSONArray("data");
+                if (data != null && data.size() > 0) {
+                    zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
+                    zlmServerConfig.setIp(mediaServerItem.getIp());
+                }
+                return Mono.just(zlmServerConfig);
+            })
+            //响应配置不存在,使用默认配置
+            .switchIfEmpty(Mono.just(mediaServerItem)
+                .doOnNext(serverItem->{
+                    log.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试",
+                        mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), pos);
+                    if (pos == 1 && !StringUtils.isEmpty(mediaServerItem.getId())) {
+                        log.info("[ {} ]-[ {}:{} ]第{}次主动连接失败, 开始清理相关资源",
+                            mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), pos);
+                        //todo
+//                    publisher.zlmOfflineEventPublish(mediaServerItem.getId());
+                    }
+                })
+                .delayElement(Duration.ofSeconds(2))
+                .flatMap(serverItem->getMediaServerConfig(serverItem,pos+1)))
+            ;
+
+    }
+
+    /**
+     * zlm 连接成功或者zlm重启后
+     */
+//    private void zLmRunning(ZLMServerConfig zlmServerConfig){
+//        logger.info( "[ id: " + zlmServerConfig.getGeneralMediaServerId() + "] zlm接入成功...");
+//        // 关闭循环获取zlm配置
+//        startGetMedia = false;
+//        MediaServerItem mediaServerItem = new MediaServerItem(zlmServerConfig, sipIp);
+//        storager.updateMediaServer(mediaServerItem);
+//
+//        if (mediaServerItem.isAutoConfig()) setZLMConfig(mediaServerItem);
+//        zlmServerManger.updateServerCatchFromHook(zlmServerConfig);
+//
+//        // 清空所有session
+////        zlmMediaListManager.clearAllSessions();
+//
+//        // 更新流列表
+//        zlmMediaListManager.updateMediaList(mediaServerItem);
+//        // 恢复流代理, 只查找这个这个流媒体
+//        List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer(
+//                mediaServerItem.getId(), true);
+//        for (StreamProxyItem streamProxyDto : streamProxyListForEnable) {
+//            logger.info("恢复流代理," + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
+//            JSONObject jsonObject = streamProxyService.addStreamProxyToZlm(streamProxyDto);
+//            if (jsonObject == null) {
+//                // 设置为未启用
+//                logger.info("恢复流代理失败,请检查流地址后重新启用" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
+//                streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream());
 //            }
-//        });
-//
-//        // 订阅 zlm保活事件, 当zlm离线时做业务的处理
-//        hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_keepalive,null,
-//                (MediaServerItem mediaServerItem, JSONObject response)->{
-//                    String mediaServerId = response.getString("mediaServerId");
-//                    if (mediaServerId !=null ) {
-//                        mediaServerService.updateMediaServerKeepalive(mediaServerId, response.getJSONObject("data"));
-//                    }
-//                });
-//
-//        // 获取zlm信息
-//        logger.info("[zlm接入]等待默认zlm中...");
-//
-//        // 获取所有的zlm, 并开启主动连接
-//        List<MediaServerItem> all = mediaServerService.getAllFromDatabase();
-//        if (all.size() == 0) {
-//            all.add(mediaConfig.getMediaSerItem());
-//        }
-//        for (MediaServerItem mediaServerItem : all) {
-//            if (startGetMedia == null) startGetMedia = new HashMap<>();
-//            startGetMedia.put(mediaServerItem.getId(), true);
-//            taskExecutor.execute(()->{
-//                connectZlmServer(mediaServerItem);
-//            });
-//        }
-//        Timer timer = new Timer();
-//        // 10分钟后未连接到则不再去主动连接, TODO 并对重启前使用此在zlm的通道发送bye
-//        timer.schedule(new TimerTask() {
-//            @Override
-//            public void run() {
-//            if (startGetMedia != null) {
-//                Set<String> allZlmId = startGetMedia.keySet();
-//                for (String id : allZlmId) {
-//                    logger.error("[ {} ]]主动连接失败,不再主动连接", id);
-//                }
-//                startGetMedia = null;
-//            }
-//            //  TODO 清理数据库中与redis不匹配的zlm
-//            }
-//        }, 60 * 1000 * 10);
-//    }
-//
-//    @Async
-//    public void connectZlmServer(MediaServerItem mediaServerItem){
-//        ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem, 1);
-//        if (zlmServerConfig != null) {
-//            zlmServerConfig.setIp(mediaServerItem.getIp());
-//            zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
-//            startGetMedia.remove(mediaServerItem.getId());
-//            mediaServerService.zlmServerOnline(zlmServerConfig);
 //        }
 //    }
-//
-//    public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem, int index) {
-//        if (startGetMedia == null) { return null;}
-//        if (!mediaServerItem.isDefaultServer() && mediaServerService.getOne(mediaServerItem.getId()) == null) {
-//            return null;
-//        }
-//        if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) {
-//            return null;
-//        }
-//        JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
-//        ZLMServerConfig ZLMServerConfig = null;
-//        if (responseJSON != null) {
-//            JSONArray data = responseJSON.getJSONArray("data");
-//            if (data != null && data.size() > 0) {
-//                ZLMServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
-//                ZLMServerConfig.setIp(mediaServerItem.getIp());
-//            }
-//        } else {
-//            logger.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试",
-//                    mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index);
-//            if (index == 1 && !StringUtils.isEmpty(mediaServerItem.getId())) {
-//                logger.info("[ {} ]-[ {}:{} ]第{}次主动连接失败, 开始清理相关资源",
-//                        mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index);
-//                publisher.zlmOfflineEventPublish(mediaServerItem.getId());
-//            }
-//            try {
-//                Thread.sleep(2000);
-//            } catch (InterruptedException e) {
-//                e.printStackTrace();
-//            }
-//            ZLMServerConfig = getMediaServerConfig(mediaServerItem, index += 1);
-//        }
-//        return ZLMServerConfig;
-//
-//    }
-//
-//    /**
-//     * zlm 连接成功或者zlm重启后
-//     */
-////    private void zLmRunning(ZLMServerConfig zlmServerConfig){
-////        logger.info( "[ id: " + zlmServerConfig.getGeneralMediaServerId() + "] zlm接入成功...");
-////        // 关闭循环获取zlm配置
-////        startGetMedia = false;
-////        MediaServerItem mediaServerItem = new MediaServerItem(zlmServerConfig, sipIp);
-////        storager.updateMediaServer(mediaServerItem);
-////
-////        if (mediaServerItem.isAutoConfig()) setZLMConfig(mediaServerItem);
-////        zlmServerManger.updateServerCatchFromHook(zlmServerConfig);
-////
-////        // 清空所有session
-//////        zlmMediaListManager.clearAllSessions();
-////
-////        // 更新流列表
-////        zlmMediaListManager.updateMediaList(mediaServerItem);
-////        // 恢复流代理, 只查找这个这个流媒体
-////        List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer(
-////                mediaServerItem.getId(), true);
-////        for (StreamProxyItem streamProxyDto : streamProxyListForEnable) {
-////            logger.info("恢复流代理," + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
-////            JSONObject jsonObject = streamProxyService.addStreamProxyToZlm(streamProxyDto);
-////            if (jsonObject == null) {
-////                // 设置为未启用
-////                logger.info("恢复流代理失败,请检查流地址后重新启用" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
-////                streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream());
-////            }
-////        }
-////    }
-//}
+}

+ 23 - 269
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/dto/MediaItem.java

@@ -1,7 +1,10 @@
 package org.jetlinks.community.media.zlm.dto;
 
+import lombok.Data;
+
 import java.util.List;
 
+@Data
 public class MediaItem {
 
     /**
@@ -9,11 +12,31 @@ public class MediaItem {
      */
     private boolean regist;
 
+    /**
+     * 存活时间,单位秒
+     */
+    private Long aliveSecond;
+
+    /**
+     * 服务器id
+     */
+    private String mediaServerId;
+
     /**
      * 应用名
      */
     private String app;
 
+    /**
+     * 数据产生速度,单位byte/s
+     */
+    private Long bytesSpeed;
+
+    /**
+     * GMT unix系统时间戳,单位秒
+     */
+    private Long createStamp;
+
     /**
      * 流id
      */
@@ -58,26 +81,6 @@ public class MediaItem {
      */
     private String originUrl;
 
-    /**
-     * 服务器id
-     */
-    private String mediaServerId;
-
-    /**
-     * GMT unix系统时间戳,单位秒
-     */
-    private Long createStamp;
-
-    /**
-     * 存活时间,单位秒
-     */
-    private Long aliveSecond;
-
-    /**
-     * 数据产生速度,单位byte/s
-     */
-    private Long bytesSpeed;
-
     /**
      * 音视频轨道
      */
@@ -88,14 +91,6 @@ public class MediaItem {
      */
     private String vhost;
 
-    public boolean isRegist() {
-        return regist;
-    }
-
-    public void setRegist(boolean regist) {
-        this.regist = regist;
-    }
-
     /**
      * 是否是docker部署, docker部署不会自动更新zlm使用的端口,需要自己手动修改
      */
@@ -152,85 +147,6 @@ public class MediaItem {
          */
         private int width;
 
-        public int getChannels() {
-            return channels;
-        }
-
-        public void setChannels(int channels) {
-            this.channels = channels;
-        }
-
-        public int getCodecId() {
-            return codecId;
-        }
-
-        public void setCodecId(int codecId) {
-            this.codecId = codecId;
-        }
-
-        public String getCodecIdName() {
-            return codecIdName;
-        }
-
-        public void setCodecIdName(String codecIdName) {
-            this.codecIdName = codecIdName;
-        }
-
-        public int getCodecType() {
-            return codecType;
-        }
-
-        public void setCodecType(int codecType) {
-            this.codecType = codecType;
-        }
-
-        public boolean isReady() {
-            return ready;
-        }
-
-        public void setReady(boolean ready) {
-            this.ready = ready;
-        }
-
-        public int getSampleBit() {
-            return sampleBit;
-        }
-
-        public void setSampleBit(int sampleBit) {
-            this.sampleBit = sampleBit;
-        }
-
-        public int getSampleRate() {
-            return sampleRate;
-        }
-
-        public void setSampleRate(int sampleRate) {
-            this.sampleRate = sampleRate;
-        }
-
-        public int getFps() {
-            return fps;
-        }
-
-        public void setFps(int fps) {
-            this.fps = fps;
-        }
-
-        public int getHeight() {
-            return height;
-        }
-
-        public void setHeight(int height) {
-            this.height = height;
-        }
-
-        public int getWidth() {
-            return width;
-        }
-
-        public void setWidth(int width) {
-            this.width = width;
-        }
     }
 
     public static class OriginSock{
@@ -239,167 +155,5 @@ public class MediaItem {
         private int local_port;
         private String peer_ip;
         private int peer_port;
-
-        public String getIdentifier() {
-            return identifier;
-        }
-
-        public void setIdentifier(String identifier) {
-            this.identifier = identifier;
-        }
-
-        public String getLocal_ip() {
-            return local_ip;
-        }
-
-        public void setLocal_ip(String local_ip) {
-            this.local_ip = local_ip;
-        }
-
-        public int getLocal_port() {
-            return local_port;
-        }
-
-        public void setLocal_port(int local_port) {
-            this.local_port = local_port;
-        }
-
-        public String getPeer_ip() {
-            return peer_ip;
-        }
-
-        public void setPeer_ip(String peer_ip) {
-            this.peer_ip = peer_ip;
-        }
-
-        public int getPeer_port() {
-            return peer_port;
-        }
-
-        public void setPeer_port(int peer_port) {
-            this.peer_port = peer_port;
-        }
-    }
-
-    public String getApp() {
-        return app;
-    }
-
-    public void setApp(String app) {
-        this.app = app;
-    }
-
-    public String getStream() {
-        return stream;
-    }
-
-    public void setStream(String stream) {
-        this.stream = stream;
-    }
-
-    public String getTotalReaderCount() {
-        return totalReaderCount;
-    }
-
-    public void setTotalReaderCount(String totalReaderCount) {
-        this.totalReaderCount = totalReaderCount;
-    }
-
-
-    public int getOriginType() {
-        return originType;
-    }
-
-    public void setOriginType(int originType) {
-        this.originType = originType;
-    }
-
-
-    public String getOriginTypeStr() {
-        return originTypeStr;
-    }
-
-    public void setOriginTypeStr(String originTypeStr) {
-        this.originTypeStr = originTypeStr;
-    }
-
-    public String getOriginUrl() {
-        return originUrl;
-    }
-
-    public void setOriginUrl(String originUrl) {
-        this.originUrl = originUrl;
-    }
-
-    public Long getCreateStamp() {
-        return createStamp;
-    }
-
-    public void setCreateStamp(Long createStamp) {
-        this.createStamp = createStamp;
-    }
-
-    public Long getAliveSecond() {
-        return aliveSecond;
-    }
-
-    public void setAliveSecond(Long aliveSecond) {
-        this.aliveSecond = aliveSecond;
-    }
-
-    public List<MediaTrack> getTracks() {
-        return tracks;
-    }
-
-    public void setTracks(List<MediaTrack> tracks) {
-        this.tracks = tracks;
-    }
-
-    public String getSchema() {
-        return schema;
-    }
-
-    public void setSchema(String schema) {
-        this.schema = schema;
-    }
-
-    public void setOriginSock(OriginSock originSock) {
-        this.originSock = originSock;
-    }
-
-    public Long getBytesSpeed() {
-        return bytesSpeed;
-    }
-
-    public void setBytesSpeed(Long bytesSpeed) {
-        this.bytesSpeed = bytesSpeed;
-    }
-
-    public String getVhost() {
-        return vhost;
-    }
-
-    public void setVhost(String vhost) {
-        this.vhost = vhost;
-    }
-
-    public OriginSock getOriginSock() {
-        return originSock;
-    }
-
-    public boolean isDocker() {
-        return docker;
-    }
-
-    public void setDocker(boolean docker) {
-        this.docker = docker;
-    }
-
-    public String getMediaServerId() {
-        return mediaServerId;
-    }
-
-    public void setMediaServerId(String mediaServerId) {
-        this.mediaServerId = mediaServerId;
     }
 }

+ 11 - 8
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/dto/MediaServerItem.java → jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/media/zlm/entity/MediaServerItem.java

@@ -1,17 +1,21 @@
-package org.jetlinks.community.media.zlm.dto;
+package org.jetlinks.community.media.zlm.entity;
 
 
 import lombok.Data;
 //import org.jetlinks.community.media.zlm.ZLMServerConfig;
-import org.jetlinks.community.media.session.SsrcConfig;
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.api.crud.entity.GenericEntity;
+import org.jetlinks.community.media.bean.SsrcConfig;
 import org.jetlinks.community.media.zlm.ZLMServerConfig;
 import org.springframework.util.StringUtils;
 
-import java.util.HashMap;
-@Data
-public class MediaServerItem{
+import javax.persistence.Index;
+import javax.persistence.Table;
 
-    private String id;
+@Data
+@Table(name = "media_server_item")
+public class MediaServerItem extends GenericEntity<String> {
 
     private String ip;
 
@@ -76,7 +80,7 @@ public class MediaServerItem{
     }
 
     public MediaServerItem(ZLMServerConfig zlmServerConfig, String sipIp) {
-        id = zlmServerConfig.getGeneralMediaServerId();
+        this.setId( zlmServerConfig.getGeneralMediaServerId());
         ip = zlmServerConfig.getIp();
         hookIp = StringUtils.isEmpty(zlmServerConfig.getHookIp())? sipIp: zlmServerConfig.getHookIp();
         sdpIp = StringUtils.isEmpty(zlmServerConfig.getSdpIp())? zlmServerConfig.getIp(): zlmServerConfig.getSdpIp();
@@ -96,6 +100,5 @@ public class MediaServerItem{
         rtpPortRange = "30000,30500"; // 默认使用30000,30500作为级联时发送流的端口号
         sendRtpPortRange = "30000,30500"; // 默认使用30000,30500作为级联时发送流的端口号
         recordAssistPort = 0; // 默认关闭
-
     }
 }

+ 11 - 11
jetlinks-manager/media-manager/src/main/java/org/jetlinks/community/utils/RedisUtil.java

@@ -1,7 +1,7 @@
 package org.jetlinks.community.utils;
 
-import com.alibaba.fastjson.JSONObject;
-import org.springframework.beans.factory.annotation.Autowired;
+import cn.hutool.json.JSONObject;
+import lombok.AllArgsConstructor;
 import org.springframework.data.redis.core.*;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
@@ -9,19 +9,19 @@ import org.springframework.util.CollectionUtils;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
-/**    
+/**
  * @description:Redis工具类
  * @author: swwheihei
- * @date:   2020年5月6日 下午8:27:29     
+ * @date:   2020年5月6日 下午8:27:29
  */
 @Component
+@AllArgsConstructor
 @SuppressWarnings(value = {"rawtypes", "unchecked"})
 public class RedisUtil {
 
-	@Autowired
-    private RedisTemplate redisTemplate;
-	
-	/**
+    private final RedisTemplate redisTemplate;
+
+    /**
      * 指定缓存失效时间
      * @param key 键
      * @param time 时间(秒)
@@ -68,8 +68,8 @@ public class RedisUtil {
      * @param key 键(一个或者多个)
      */
     public boolean del(String... key) {
-    	try {
-    		if (key != null && key.length > 0) {
+        try {
+            if (key != null && key.length > 0) {
                 if (key.length == 1) {
                     redisTemplate.delete(key[0]);
                 } else {
@@ -706,6 +706,7 @@ public class RedisUtil {
      * @return
      */
     public List<Object> scan(String query) {
+        //todo 仅能scan一次,此问题有待解决
         Set<String> keys = (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
             Set<String> keysTmp = new HashSet<>();
             Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(query).count(1000).build());
@@ -734,7 +735,6 @@ public class RedisUtil {
     public void convertAndSend(String channel, JSONObject msg) {
 //        redisTemplate.convertAndSend(channel, msg);
         redisTemplate.convertAndSend(channel, msg);
-
     }
 
 }

+ 3 - 1
jetlinks-standalone/pom.xml

@@ -226,7 +226,9 @@
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
-            <version>RELEASE</version>
+            <version>
+                ${servlet.version}
+            </version>
         </dependency>
 
         <dependency>

+ 4 - 1
jetlinks-standalone/src/main/java/org/jetlinks/community/standalone/JetLinksApplication.java

@@ -6,9 +6,12 @@ import org.hswebframework.web.authorization.events.AuthorizingHandleBeforeEvent;
 import org.hswebframework.web.crud.annotation.EnableEasyormRepository;
 import org.hswebframework.web.logging.aop.EnableAccessLogger;
 import org.hswebframework.web.logging.events.AccessLoggerAfterEvent;
+import org.jetlinks.community.media.config.MediaConfig;
 import org.redisson.spring.starter.RedissonAutoConfiguration;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.cache.annotation.EnableCaching;
 import org.springframework.context.annotation.Profile;
 import org.springframework.context.event.EventListener;
@@ -20,7 +23,7 @@ import javax.annotation.PostConstruct;
     RedissonAutoConfiguration.class
 })
 @EnableCaching
-@EnableEasyormRepository("org.jetlinks.community.**.entity")
+@EnableEasyormRepository({"org.jetlinks.community.**.entity","org.jetlinks.community.media.**.entity"})
 @EnableAopAuthorize
 @EnableAccessLogger
 @Slf4j

+ 3 - 1
jetlinks-standalone/src/main/java/org/jetlinks/community/standalone/configuration/CroConfiguration.java

@@ -2,6 +2,7 @@ package org.jetlinks.community.standalone.configuration;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
 import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 import org.springframework.web.filter.CorsFilter;
@@ -15,10 +16,11 @@ import java.io.FileOutputStream;
  * @Description TODO
  * @createTime 2021年10月18日 16:47:00
  */
+@Primary
 @Configuration
 public class CroConfiguration{
     @Bean
-    public CorsFilter corsFilter() {
+    public CorsFilter jetLinksCorsFilter() {
         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
 
         CorsConfiguration config = new CorsConfiguration();

+ 13 - 7
jetlinks-standalone/src/main/resources/application.yml

@@ -16,9 +16,9 @@ spring:
   resources:
     static-locations: file:./static/,/,classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/, classpath:/public/
   redis:
-    host: 192.168.104.114
+    host: 1.15.89.83
 #    host: 1.15.89.83
-    port: 6379
+    port: 9736
     password: 6E6985E1F7CB40F24A\.
     lettuce:
       pool:
@@ -26,10 +26,11 @@ spring:
         max-idle: 8
     timeout: 20s
     serializer: jdk # 设置fst时,redis key使用string序列化,value使用 fst序列化.
+    database: 3
   #    database: 3
   #        max-wait: 10s
   r2dbc:
-    url: r2dbc:postgresql://192.168.104.114:5432/jetlinks?stringtype=unspecified
+    url: r2dbc:postgresql://1.15.89.83:5432/jetlinks?stringtype=unspecified
 #    url: r2dbc:mysql://192.168.100.32:3306/jetlinks
 #    username: root
 #    password: 123456
@@ -44,7 +45,7 @@ spring:
     elasticsearch:
       client:
         reactive:
-          endpoints: 192.168.104.114:9200
+          endpoints: 1.15.89.83:9200
           max-in-memory-size: 100MB
           socket-timeout: 1000
           connection-timeout: 10000
@@ -56,9 +57,9 @@ elasticsearch:
     enabled: false # 为true时使用内嵌的elasticsearch,不建议在生产环境中使用
     data-path: ./data/elasticsearch
     port: 9200
-    host: 192.168.104.114
+    host: 1.15.89.83
   client:
-    host: 192.168.100.114
+    host: 1.15.89.83
     port: 9200
     max-conn-total: 128
     connect-timeout: 5000
@@ -213,10 +214,15 @@ springdoc:
       paths-to-match:
         - /visualization/**
         - /visualization/catalog/**
+    - group: GB28181接口
+      packages-to-scan:
+        - org.jetlinks.community.media
+      paths-to-match:
+        - /index/hook
   cache:
     disabled: true
 visual:
   base-path: "http://127.0.0.1:8844"
   urls:
     big-screen-path: "http://192.168.104.115:9022/"
-    vis-configuration: "http://192.168.104.115:9022/"
+    vis-configuration: "http://192.168.104.115:9022/"

+ 5 - 17
jetlinks-standalone/src/test/java/org/jetlinks/community/BridgeTest.java

@@ -1,24 +1,15 @@
 package org.jetlinks.community;
 
-import cn.hutool.core.lang.Pair;
-import cn.hutool.core.map.MapUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.jetlinks.community.bridge.entity.AliIotBridgeDeviceConfig;
-import org.jetlinks.community.bridge.entity.AliIotBridgeEntity;
-import org.jetlinks.community.bridge.server.aliyun.AliBridgeGateway;
-import org.jetlinks.community.media.bean.EventResult;
 import org.jetlinks.community.media.bean.SSRCInfo;
-import org.jetlinks.community.media.entity.MediaDevice;
 import org.jetlinks.community.media.entity.SipServerConfig;
 import org.jetlinks.community.media.service.LocalMediaDeviceService;
 import org.jetlinks.community.media.sip.SipServerHelper;
 import org.jetlinks.community.media.transmit.cmd.SipCommander;
-import org.jetlinks.community.media.zlm.dto.MediaServerItem;
+import org.jetlinks.community.media.zlm.entity.MediaServerItem;
 import org.jetlinks.community.standalone.JetLinksApplication;
 import org.jetlinks.core.device.DeviceRegistry;
 import org.jetlinks.core.event.EventBus;
-import org.jetlinks.core.message.DeviceOnlineMessage;
-import org.jetlinks.core.message.property.ReportPropertyMessage;
 import org.jetlinks.supports.server.DecodedClientMessageHandler;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -26,11 +17,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
-import java.util.Arrays;
-
 /**
  * @author lifang
  * @version 1.0.0
@@ -59,12 +47,12 @@ public class BridgeTest {
 //
     @Test
     public void init() throws InterruptedException {
-        serverHelper.createSip( SipServerConfig.of("34020000002000000001","192.168.104.244", 7001,"udp","340200000","utf-8","12345678",10L,"1")).subscribe();
-        Thread.sleep(6000);
+        serverHelper.createSip( SipServerConfig.of("34020000002000000001","192.168.10.100", 7001,"udp","340200000","utf-8","12345678",10L,"1")).subscribe();
+        Thread.sleep(3000);
         System.out.println("开始调用invite方法");
-        SSRCInfo ssrcInfo = SSRCInfo.of(5003,"1000",null);
+        SSRCInfo ssrcInfo = SSRCInfo.of(10000,"1000",null);
         MediaServerItem mediaServerItem = new MediaServerItem();
-        mediaServerItem.setSdpIp("192.168.104.244");
+        mediaServerItem.setSdpIp("1.15.89.83");
         mediaDeviceService.findById("34020000001320000003")
             .flatMap(device->{
                     device.setStreamMode("udp");

+ 1 - 0
pom.xml

@@ -37,6 +37,7 @@
         <redisson.version>3.13.6</redisson.version>
         <sip.version>1.3.0-91</sip.version>
         <californium.version>2.2.3</californium.version>
+        <servlet.version>3.0-alpha-1</servlet.version>
     </properties>