648540858
2024-02-27 509d9b3cbba7ba8fdc7466c34e46db70d41517a8
Merge branch 'wvp-28181-2.0' into main-dev

# Conflicts:
# src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
# src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
# src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
# src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
26个文件已修改
6个文件已添加
1357 ■■■■ 已修改文件
README.md 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbSteamIdentification.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/session/CommonSessionManager.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java 99 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/channelList.vue 96 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/dialog/deviceEdit.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/初始化-mysql-2.7.0.sql 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/初始化-postgresql-kingbase-2.7.0.sql 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/更新-mysql-2.7.0.sql 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/更新-postgresql-kingbase-2.7.0.sql 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -49,6 +49,7 @@
- [X] æ”¯æŒç”µå­åœ°å›¾ï¼Œæ”¯æŒæŽ¥å…¥WGS84和GCJ02两种坐标系,并且自动转化为合适的坐标系进行展示和分发
- [X] æŽ¥å…¥è®¾å¤‡
  - [X] è§†é¢‘预览
  - [X] æ”¯æŒä¸»ç æµå­ç æµåˆ‡æ¢
  - [X] æ— é™åˆ¶æŽ¥å…¥è·¯æ•°ï¼Œèƒ½æŽ¥å…¥å¤šå°‘设备只取决于你的服务器性能
  - [X] äº‘台控制,控制设备转向,拉近,拉远
  - [X] é¢„置位查询,使用与设置
src/main/java/com/genersoft/iot/vmp/common/InviteInfo.java
@@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.common;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import io.swagger.v3.oas.annotations.media.Schema;
/**
 * è®°å½•每次发送invite消息的状态
@@ -124,21 +123,5 @@
    public void setStreamMode(String streamMode) {
        this.streamMode = streamMode;
    }
    /*=========================设备主子码流逻辑START====================*/
    @Schema(description = "是否为子码流(true-是,false-主码流)")
    private boolean subStream;
    public boolean isSubStream() {
        return subStream;
    }
    public void setSubStream(boolean subStream) {
        this.subStream = subStream;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
@@ -452,27 +452,11 @@
    public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
        this.sipTransactionInfo = sipTransactionInfo;
    }
    public boolean isBroadcastPushAfterAck() {
        return broadcastPushAfterAck;
    }
    /*======================设备主子码流逻辑START=========================*/
    @Schema(description = "开启主子码流切换的开关(false-不开启,true-开启)")
    private boolean switchPrimarySubStream;
    public boolean isSwitchPrimarySubStream() {
        return switchPrimarySubStream;
    }
    public void setSwitchPrimarySubStream(boolean switchPrimarySubStream) {
        this.switchPrimarySubStream = switchPrimarySubStream;
    }
    /*======================设备主子码流逻辑END=========================*/
    public boolean isBroadcastPushAfterAck() {
        return broadcastPushAfterAck;
    }
    public void setBroadcastPushAfterAck(boolean broadcastPushAfterAck) {
        this.broadcastPushAfterAck = broadcastPushAfterAck;
    }
    public void setBroadcastPushAfterAck(boolean broadcastPushAfterAck) {
        this.broadcastPushAfterAck = broadcastPushAfterAck;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
@@ -246,6 +246,10 @@
    @Schema(description = "GPS的更新时间")
    private String gpsTime;
    @Schema(description = "码流标识,优先级高于设备中码流标识," +
            "用于选择码流时组成码流标识。默认为null,不设置。可选值: stream/streamnumber/streamprofile/streamMode")
    private String streamIdentification;
    public int getId() {
        return id;
    }
@@ -574,4 +578,12 @@
    public void setGpsTime(String gpsTime) {
        this.gpsTime = gpsTime;
    }
    public String getStreamIdentification() {
        return streamIdentification;
    }
    public void setStreamIdentification(String streamIdentification) {
        this.streamIdentification = streamIdentification;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbSteamIdentification.java
New file
@@ -0,0 +1,44 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
 * ç æµç´¢å¼•标识
 */
public enum GbSteamIdentification {
    /**
     * ä¸»ç æµ stream:0
     * å­ç æµ stream:1s
     */
    streamMain("stream", new String[]{"0","1"}),
    /**
     * å›½æ ‡28181-2022定义的方式
     * ä¸»ç æµ streamnumber:0
     * å­ç æµ streamnumber:1
     */
    streamnumber("streamnumber", new String[]{"0","1"}),
    /**
     * ä¸»ç æµ streamprofile:0
     * å­ç æµ streamprofile:1
     */
    streamprofile("streamprofile", new String[]{"0","1"}),
    /**
     * é€‚用的品牌: TP-LINK
     */
    streamMode("streamMode", new String[]{"main","sub"}),
    ;
    GbSteamIdentification(String value, String[] indexArray) {
        this.value = value;
        this.indexArray = indexArray;
    }
    private String value;
    private String[] indexArray;
    public String getValue() {
        return value;
    }
    public String[] getIndexArray() {
        return indexArray;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
@@ -52,7 +52,7 @@
        Runnable runnable = dynamicTask.get(taskOverdueKey);
        if (runnable instanceof ISubscribeTask) {
            ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
            subscribeTask.stop();
            subscribeTask.stop(null);
        }
        // æ·»åŠ ä»»åŠ¡å¤„ç†è®¢é˜…è¿‡æœŸ
        dynamicTask.stop(taskOverdueKey);
@@ -87,7 +87,7 @@
        Runnable runnable = dynamicTask.get(taskOverdueKey);
        if (runnable instanceof ISubscribeTask) {
            ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
            subscribeTask.stop();
            subscribeTask.stop(null);
        }
        // æ·»åŠ ä»»åŠ¡å¤„ç†è®¢é˜…è¿‡æœŸ
        dynamicTask.stop(taskOverdueKey);
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
@@ -2,6 +2,8 @@
import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
@@ -11,8 +13,7 @@
import javax.sip.ResponseEvent;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Response;
import javax.sip.header.WarningHeader;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -97,14 +98,27 @@
            this.event = event;
            if (event instanceof ResponseEvent) {
                ResponseEvent responseEvent = (ResponseEvent)event;
                Response response = responseEvent.getResponse();
                SIPResponse response = (SIPResponse)responseEvent.getResponse();
                this.type = EventResultType.response;
                if (response != null) {
                    this.msg = response.getReasonPhrase();
                    WarningHeader warningHeader = (WarningHeader)response.getHeader(WarningHeader.NAME);
                    if (warningHeader != null && !ObjectUtils.isEmpty(warningHeader.getText())) {
                        this.msg = "";
                        if (warningHeader.getCode() > 0) {
                            this.msg += warningHeader.getCode() + ":";
                        }
                        if (warningHeader.getAgent() != null) {
                            this.msg += warningHeader.getCode() + ":";
                        }
                        if (warningHeader.getText() != null) {
                            this.msg += warningHeader.getText();
                        }
                    }else {
                        this.msg = response.getReasonPhrase();
                    }
                    this.statusCode = response.getStatusCode();
                    this.callId = response.getCallIdHeader().getCallId();
                }
                this.callId = ((CallIdHeader)response.getHeader(CallIdHeader.NAME)).getCallId();
            }else if (event instanceof TimeoutEvent) {
                TimeoutEvent timeoutEvent = (TimeoutEvent)event;
                this.type = EventResultType.timeout;
src/main/java/com/genersoft/iot/vmp/gb28181/session/CommonSessionManager.java
New file
@@ -0,0 +1,86 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.common.CommonCallback;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * é€šç”¨å›žè°ƒç®¡ç†
 */
@Component
public class CommonSessionManager {
    public static Map<String, CommonSession> callbackMap = new ConcurrentHashMap<>();
    /**
     * å­˜å‚¨å›žè°ƒç›¸å…³çš„信息
     */
    class CommonSession{
        public String session;
        public long createTime;
        public int timeout;
        public CommonCallback<Object> callback;
        public CommonCallback<String> timeoutCallback;
    }
    /**
     * æ·»åŠ å›žè°ƒ
     * @param sessionId å”¯ä¸€æ ‡è¯†
     * @param callback å›žè°ƒ
     * @param timeout è¶…æ—¶æ—¶é—´, å•位分钟
     */
    public void add(String sessionId, CommonCallback<Object> callback, CommonCallback<String> timeoutCallback,
                    Integer timeout) {
        CommonSession commonSession = new CommonSession();
        commonSession.session = sessionId;
        commonSession.callback = callback;
        commonSession.createTime = System.currentTimeMillis();
        if (timeoutCallback != null) {
            commonSession.timeoutCallback = timeoutCallback;
        }
        if (timeout != null) {
            commonSession.timeout = timeout;
        }
        callbackMap.put(sessionId, commonSession);
    }
    public void add(String sessionId, CommonCallback<Object> callback) {
        add(sessionId, callback, null, 1);
    }
    public CommonCallback<Object> get(String sessionId, boolean destroy) {
        CommonSession commonSession = callbackMap.get(sessionId);
        if (destroy) {
            callbackMap.remove(sessionId);
        }
        return commonSession.callback;
    }
    public CommonCallback<Object> get(String sessionId) {
        return get(sessionId, false);
    }
    public void delete(String sessionID) {
        callbackMap.remove(sessionID);
    }
    @Scheduled(fixedRate= 60)   //每分钟执行一次
    public void execute(){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, -1);
        for (String session : callbackMap.keySet()) {
            if (callbackMap.get(session).createTime < cal.getTimeInMillis()) {
                // è¶…æ—¶
                if (callbackMap.get(session).timeoutCallback != null) {
                    callbackMap.get(session).timeoutCallback.run("timeout");
                }
                callbackMap.remove(session);
            }
        }
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
@@ -1,10 +1,10 @@
package com.genersoft.iot.vmp.gb28181.task;
import javax.sip.DialogState;
import com.genersoft.iot.vmp.common.CommonCallback;
/**
 * @author lin
 */
public interface ISubscribeTask extends Runnable{
    void stop();
    void stop(CommonCallback<Boolean> callback);
}
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.task.impl;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
@@ -7,14 +8,13 @@
import gov.nist.javax.sip.message.SIPRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sip.*;
import javax.sip.DialogState;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.Timer;
import java.util.TimerTask;
/**
 * ç›®å½•订阅任务
@@ -71,7 +71,7 @@
    }
    @Override
    public void stop() {
    public void stop(CommonCallback<Boolean> callback) {
        /**
         * dialog çš„各个状态
         * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
@@ -94,6 +94,9 @@
                    // æˆåŠŸ
                    logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
                }
                if (callback != null) {
                    callback.run(event.getResponse().getRawContent() != null);
                }
            },eventResult -> {
                // å¤±è´¥
                logger.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
@@ -1,20 +1,9 @@
package com.genersoft.iot.vmp.gb28181.task.impl;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.IPlatformService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import javax.sip.DialogState;
import java.util.List;
/**
 * å‘已经订阅(移动位置)的上级发送MobilePosition消息
@@ -38,7 +27,7 @@
    }
    @Override
    public void stop() {
    public void stop(CommonCallback<Boolean> callback) {
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
@@ -1,21 +1,19 @@
package com.genersoft.iot.vmp.gb28181.task.impl;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import javax.sip.*;
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.Timer;
import java.util.TimerTask;
/**
 * ç§»åŠ¨ä½ç½®è®¢é˜…çš„å®šæ—¶æ›´æ–°
@@ -70,7 +68,7 @@
    }
    @Override
    public void stop() {
    public void stop(CommonCallback<Boolean> callback) {
        /**
         * dialog çš„各个状态
         * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
@@ -92,6 +90,9 @@
                    // æˆåŠŸ
                    logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
                }
                if (callback != null) {
                    callback.run(event.getResponse().getRawContent() != null);
                }
            },eventResult -> {
                // å¤±è´¥
                logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -5,6 +5,7 @@
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -97,9 +98,9 @@
    /**
     * è¯·æ±‚预览视频流
     * @param device  è§†é¢‘设备
     * @param channelId  é¢„览通道
     * @param channel  é¢„览通道
     */
    void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    /**
     * è¯·æ±‚回放视频流
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -7,6 +7,10 @@
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
@@ -266,12 +270,12 @@
     * è¯·æ±‚预览视频流
     *
     * @param device     è§†é¢‘设备
     * @param channelId  é¢„览通道
     * @param channel  é¢„览通道
     * @param event      hook订阅
     * @param errorEvent sip错误订阅
     */
    @Override
    public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
    public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
                              ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
        String stream = ssrcInfo.getStream();
@@ -295,7 +299,7 @@
        }
        StringBuffer content = new StringBuffer(200);
        content.append("v=0\r\n");
        content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n");
        content.append("o=" + channel.getChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n");
        content.append("s=Play\r\n");
        content.append("c=IN IP4 " + sdpIp + "\r\n");
        content.append("t=0 0\r\n");
@@ -346,20 +350,8 @@
            }
        }
        if( device.isSwitchPrimarySubStream() ){
            if("TP-LINK".equals(device.getManufacturer())){
                if (device.isSwitchPrimarySubStream()){
                    content.append("a=streamMode:sub\r\n");
                }else {
                    content.append("a=streamMode:main\r\n");
                }
            }else {
                if (device.isSwitchPrimarySubStream()){
                    content.append("a=streamprofile:1\r\n");
                }else {
                    content.append("a=streamprofile:0\r\n");
                }
            }
        if (!ObjectUtils.isEmpty(channel.getStreamIdentification())) {
            content.append("a=" + channel.getStreamIdentification() + "\r\n");
        }
        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
@@ -368,16 +360,16 @@
        Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
        Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
        sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
            streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
            streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
            mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
            errorEvent.response(e);
        }), e -> {
            ResponseEvent responseEvent = (ResponseEvent) e.event;
            SIPResponse response = (SIPResponse) responseEvent.getResponse();
            String callId = response.getCallIdHeader().getCallId();
            streamSession.put(device.getDeviceId(), channelId, callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
            streamSession.put(device.getDeviceId(), channel.getChannelId(), callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
                    InviteSessionType.PLAY);
            okEvent.response(e);
        });
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -6,7 +6,6 @@
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
@@ -38,7 +37,6 @@
import javax.sip.header.FromHeader;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -222,7 +220,6 @@
                    mobilePosition.getLongitude(), mobilePosition.getLatitude());
            mobilePosition.setReportSource("Mobile Position");
            // æ›´æ–°device channel çš„经纬度
            DeviceChannel deviceChannel = new DeviceChannel();
            deviceChannel.setDeviceId(device.getDeviceId());
@@ -242,6 +239,8 @@
            }
            storager.updateChannelPosition(deviceChannel);
            // å‘关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息
            // å‘送redis消息。 é€šçŸ¥ä½ç½®ä¿¡æ¯çš„变化
            JSONObject jsonObject = new JSONObject();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -82,8 +82,9 @@
            device.setIp(remoteAddressInfo.getIp());
            // è®¾å¤‡åœ°å€å˜åŒ–会引起目录订阅任务失效,需要重新添加
            if (device.getSubscribeCycleForCatalog() > 0) {
                deviceService.removeCatalogSubscribe(device);
                deviceService.addCatalogSubscribe(device);
                deviceService.removeCatalogSubscribe(device, result->{
                    deviceService.addCatalogSubscribe(device);
                });
            }
        }
        if (device.getKeepaliveTime() == null) {
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
@@ -87,4 +87,9 @@
     * ç›´æŽ¥æ‰¹é‡æ·»åŠ 
     */
    void batchAddChannel(List<DeviceChannel> deviceChannels);
    /**
     * ä¿®æ”¹é€šé“的码流类型
     */
    void updateChannelStreamIdentification(DeviceChannel channel);
}
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
@@ -39,7 +40,7 @@
     * @param device è®¾å¤‡ä¿¡æ¯
     * @return å¸ƒå°”
     */
    boolean removeCatalogSubscribe(Device device);
    boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback);
    /**
     * æ·»åŠ ç§»åŠ¨ä½ç½®è®¢é˜…
@@ -53,7 +54,7 @@
     * @param device è®¾å¤‡ä¿¡æ¯
     * @return å¸ƒå°”
     */
    boolean removeMobilePositionSubscribe(Device device);
    boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback);
    /**
     * ç§»é™¤ç§»åŠ¨ä½ç½®è®¢é˜…
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
@@ -25,7 +26,7 @@
 */
public interface IPlayService {
    void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
    void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId,
              ErrorCallback<Object> callback);
    SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback);
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
@@ -18,6 +18,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.HashMap;
@@ -267,5 +268,16 @@
        }
    }
    @Override
    public void updateChannelStreamIdentification(DeviceChannel channel) {
        assert !ObjectUtils.isEmpty(channel.getDeviceId());
        assert !ObjectUtils.isEmpty(channel.getStreamIdentification());
        if (ObjectUtils.isEmpty(channel.getStreamIdentification())) {
            logger.info("[重置通道码流类型] è®¾å¤‡: {}, ç æµï¼š {}", channel.getDeviceId(), channel.getStreamIdentification());
        }else {
            logger.info("[更新通道码流类型] è®¾å¤‡: {}, é€šé“:{}, ç æµï¼š {}", channel.getDeviceId(), channel.getChannelId(),
                    channel.getStreamIdentification());
        }
        channelMapper.updateChannelStreamIdentification(channel);
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -1,10 +1,10 @@
package com.genersoft.iot.vmp.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -145,10 +145,6 @@
            }
            sync(device);
        }else {
            if (deviceInDb != null) {
                device.setSwitchPrimarySubStream(deviceInDb.isSwitchPrimarySubStream());
            }
            if(!device.isOnLine()){
                device.setOnLine(true);
                device.setCreateTime(now);
@@ -238,12 +234,8 @@
            }
        }
        // ç§»é™¤è®¢é˜…
        removeCatalogSubscribe(device);
        removeMobilePositionSubscribe(device);
        if (userSetting.getDeviceStatusNotify()) {
            // å‘送redis消息
            redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
        }
        removeCatalogSubscribe(device, null);
        removeMobilePositionSubscribe(device, null);
        List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId);
        if (audioBroadcastCatches.size() > 0) {
@@ -281,7 +273,7 @@
    }
    @Override
    public boolean removeCatalogSubscribe(Device device) {
    public boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback) {
        if (device == null || device.getSubscribeCycleForCatalog() < 0) {
            return false;
        }
@@ -291,7 +283,7 @@
            Runnable runnable = dynamicTask.get(taskKey);
            if (runnable instanceof ISubscribeTask) {
                ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
                subscribeTask.stop();
                subscribeTask.stop(callback);
            }
        }
        dynamicTask.stop(taskKey);
@@ -314,7 +306,7 @@
    }
    @Override
    public boolean removeMobilePositionSubscribe(Device device) {
    public boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback) {
        if (device == null || device.getSubscribeCycleForCatalog() < 0) {
            return false;
        }
@@ -324,7 +316,7 @@
            Runnable runnable = dynamicTask.get(taskKey);
            if (runnable instanceof ISubscribeTask) {
                ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
                subscribeTask.stop();
                subscribeTask.stop(callback);
            }
        }
        dynamicTask.stop(taskKey);
@@ -515,21 +507,6 @@
            logger.warn("更新设备时未找到设备信息");
            return;
        }
        if(deviceInStore.isSwitchPrimarySubStream() != device.isSwitchPrimarySubStream()){
            //当修改设备的主子码流开关时,需要校验是否存在流,如果存在流则直接关闭
            List<SsrcTransaction> ssrcTransactionForAll = streamSession.getSsrcTransactionForAll(device.getDeviceId(), null, null, null);
            if(ssrcTransactionForAll != null){
                for (SsrcTransaction ssrcTransaction: ssrcTransactionForAll) {
                    try {
                        cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), ssrcTransaction.getStream(), null, null);
                    } catch (InvalidArgumentException | SsrcTransactionNotFoundException | ParseException | SipException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            deviceChannelMapper.clearPlay(device.getDeviceId());
            inviteStreamService.clearInviteInfo(device.getDeviceId());
        }
        if (!ObjectUtils.isEmpty(device.getName())) {
            deviceInStore.setName(device.getName());
@@ -552,39 +529,54 @@
        if (!ObjectUtils.isEmpty(device.getStreamMode())) {
            deviceInStore.setStreamMode(device.getStreamMode());
        }
        //  ç›®å½•订阅相关的信息
        if (deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
            if (device.getSubscribeCycleForCatalog() > 0) {
                // è‹¥å·²å¼€å¯è®¢é˜…,但订阅周期不同,则先取消
                if (deviceInStore.getSubscribeCycleForCatalog() != 0) {
                    removeCatalogSubscribe(deviceInStore);
                    removeCatalogSubscribe(deviceInStore, result->{
                        // å¼€å¯è®¢é˜…
                        deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
                        addCatalogSubscribe(deviceInStore);
                        // å› ä¸ºæ˜¯å¼‚步执行,需要在这里更新下数据
                        deviceMapper.updateCustom(deviceInStore);
                        redisCatchStorage.updateDevice(deviceInStore);
                    });
                }else {
                    // å¼€å¯è®¢é˜…
                    deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
                    addCatalogSubscribe(deviceInStore);
                }
                // å¼€å¯è®¢é˜…
                deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
                addCatalogSubscribe(deviceInStore);
            }else if (device.getSubscribeCycleForCatalog() == 0) {
                // å–消订阅
                deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
                removeCatalogSubscribe(deviceInStore);
                deviceInStore.setSubscribeCycleForCatalog(0);
                removeCatalogSubscribe(deviceInStore, null);
            }
        }
        // ç§»åŠ¨ä½ç½®è®¢é˜…ç›¸å…³çš„ä¿¡æ¯
        if (device.getSubscribeCycleForMobilePosition() > 0) {
            if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
                deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
                deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
                // å¼€å¯è®¢é˜…
                addMobilePositionSubscribe(deviceInStore);
            }
        }else if (device.getSubscribeCycleForMobilePosition() == 0) {
            if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
                deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
                deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
        if (deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
            if (device.getSubscribeCycleForMobilePosition() > 0) {
                // è‹¥å·²å¼€å¯è®¢é˜…,但订阅周期不同,则先取消
                if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
                    removeMobilePositionSubscribe(deviceInStore, result->{
                        // å¼€å¯è®¢é˜…
                        deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
                        addMobilePositionSubscribe(deviceInStore);
                        // å› ä¸ºæ˜¯å¼‚步执行,需要在这里更新下数据
                        deviceMapper.updateCustom(deviceInStore);
                        redisCatchStorage.updateDevice(deviceInStore);
                    });
                }else {
                    // å¼€å¯è®¢é˜…
                    deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
                    addMobilePositionSubscribe(deviceInStore);
                }
            }else if (device.getSubscribeCycleForMobilePosition() == 0) {
                // å–消订阅
                removeMobilePositionSubscribe(deviceInStore);
                deviceInStore.setSubscribeCycleForCatalog(0);
                removeCatalogSubscribe(deviceInStore, null);
            }
        }
        if (deviceInStore.getGeoCoordSys() != null) {
@@ -603,10 +595,9 @@
        deviceInStore.setSsrcCheck(device.isSsrcCheck());
        //作为消息通道
        deviceInStore.setAsMessageChannel(device.isAsMessageChannel());
        // æ›´æ–°redis
        deviceMapper.updateCustom(deviceInStore);
        redisCatchStorage.removeDevice(deviceInStore.getDeviceId());
        redisCatchStorage.updateDevice(deviceInStore);
    }
    @Override
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -20,6 +20,8 @@
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
@@ -27,6 +29,10 @@
import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.media.zlm.*;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRecordMp4;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
@@ -39,9 +45,12 @@
import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
@@ -80,7 +89,7 @@
    private IVideoManagerStorage storager;
    @Autowired
    private SIPCommander cmder;
    private ISIPCommander cmder;
    @Autowired
    private AudioBroadcastManager audioBroadcastManager;
@@ -120,6 +129,9 @@
    @Autowired
    private UserSetting userSetting;
    @Autowired
    private IDeviceChannelService channelService;
    @Autowired
    private SipConfig sipConfig;
@@ -162,6 +174,11 @@
        if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && !mediaServerItem.isRtpEnable()) {
            logger.warn("[点播] å•端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流");
        }
        DeviceChannel channel = channelService.getOne(deviceId, channelId);
        if (channel == null) {
            logger.warn("[点播] æœªæ‰¾åˆ°é€šé“ deviceId: {},channelId:{}", deviceId, channelId);
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到通道");
        }
        InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
        if (inviteInfo != null ) {
@@ -211,7 +228,7 @@
                    null);
            return null;
        }
        play(mediaServerItem, ssrcInfo, device, channelId, callback);
        play(mediaServerItem, ssrcInfo, device, channel, callback);
        return ssrcInfo;
    }
@@ -358,7 +375,7 @@
    @Override
    public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
    public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
                     ErrorCallback<Object> callback) {
        if (mediaServerItem == null || ssrcInfo == null) {
@@ -367,111 +384,109 @@
                    null);
            return;
        }
        logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, æ”¶æµç«¯å£ï¼š {}, STREAM:{}, æ”¶æµæ¨¡å¼ï¼š{}, SSRC: {}, SSRC校验:{}",
                device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流", ssrcInfo.getPort(), ssrcInfo.getStream(),
        logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, æ”¶æµç«¯å£ï¼š {}, ç æµï¼š{}, æ”¶æµæ¨¡å¼ï¼š{}, SSRC: {}, SSRC校验:{}",
                device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(), ssrcInfo.getPort(), ssrcInfo.getStream(),
                device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
        //端口获取失败的ssrcInfo æ²¡æœ‰å¿…要发送点播指令
        if (ssrcInfo.getPort() <= 0) {
            logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
            logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channel.getChannelId(), ssrcInfo);
            // é‡Šæ”¾ssrc
            mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
            streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
            streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
            callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
            inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
            inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
                    InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
            return;
        }
        // åˆå§‹åŒ–redis中的invite消息状态
        InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo,
        InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream(), ssrcInfo,
                mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY,
                InviteSessionStatus.ready);
        inviteInfo.setSubStream(device.isSwitchPrimarySubStream());
        inviteStreamService.updateInviteInfo(inviteInfo);
        // è¶…时处理
        String timeOutTaskKey = UUID.randomUUID().toString();
        dynamicTask.startDelay(timeOutTaskKey, () -> {
            // æ‰§è¡Œè¶…时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况
            InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
            InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
            if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) {
                logger.info("[点播超时] æ”¶æµè¶…æ—¶ deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
                        device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
                logger.info("[点播超时] æ”¶æµè¶…æ—¶ deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
                        device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
                        ssrcInfo.getPort(), ssrcInfo.getSsrc());
                callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
                inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
                inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
                        InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
                try {
                    cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
                } catch (InvalidArgumentException | ParseException | SipException |
                         SsrcTransactionNotFoundException e) {
                    cmder.streamByeCmd(device, channel.getChannelId(), ssrcInfo.getStream(), null);
                } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
                    logger.error("[点播超时], å‘送BYE失败 {}", e.getMessage());
                } finally {
                    mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
                    mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
                    streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
                    streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
                    mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
                    // å–消订阅消息监听
                    HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
                    subscribe.removeSubscribe(hookSubscribe);
                }
            }else {
                logger.info("[点播超时] æ”¶æµè¶…æ—¶ deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
                        device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
                logger.info("[点播超时] æ”¶æµè¶…æ—¶ deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
                        device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
                        ssrcInfo.getPort(), ssrcInfo.getSsrc());
                mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
                mediaServerService.closeRTPServer(mediaServerItem.getId(), ssrcInfo.getStream());
                streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
                streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
            }
        }, userSetting.getPlayTimeout());
        try {
            cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInuse, hookParam ) -> {
            cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channel, (mediaServerItemInuse, hookParam ) -> {
                logger.info("收到订阅消息: " + hookParam);
                dynamicTask.stop(timeOutTaskKey);
                // hook响应
                StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId);
                StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channel.getChannelId());
                if (streamInfo == null){
                    callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
                    inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
                    inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
                    return;
                }
                callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
                inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
                inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
                        InviteErrorCode.SUCCESS.getCode(),
                        InviteErrorCode.SUCCESS.getMsg(),
                        streamInfo);
                logger.info("[点播成功] deviceId: {}, channelId:{}, ç æµç±»åž‹ï¼š{}", device.getDeviceId(), channelId,
                        device.isSwitchPrimarySubStream() ? "辅码流" : "主码流");
                snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream());
                logger.info("[点播成功] deviceId: {}, channelId:{}, ç æµç±»åž‹ï¼š{}", device.getDeviceId(), channel.getChannelId(),
                        channel.getStreamIdentification());
                snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
            }, (eventResult) -> {
                // å¤„理收到200ok后的TCP主动连接以及SSRC不一致的问题
                InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
                InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel.getChannelId(),
                        timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY);
            }, (event) -> {
                logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channelId, event.statusCode, event.msg);
                logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channel.getChannelId(), event.statusCode, event.msg);
                dynamicTask.stop(timeOutTaskKey);
                mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
                // é‡Šæ”¾ssrc
                mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
                streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
                streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
                callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(),
                        String.format("点播失败, é”™è¯¯ç ï¼š %s, %s", event.statusCode, event.msg), null);
                inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
                inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
                        InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
                        String.format("点播失败, é”™è¯¯ç ï¼š %s, %s", event.statusCode, event.msg), null);
                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
            });
        } catch (InvalidArgumentException | SipException | ParseException e) {
@@ -481,15 +496,15 @@
            // é‡Šæ”¾ssrc
            mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
            streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
            streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
            callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
                    InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
            inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
            inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
                    InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
                    InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
        }
    }
@@ -626,7 +641,7 @@
    @Override
    public void playBack(String deviceId, String channelId, String startTime,
                                                          String endTime, ErrorCallback<Object> callback) {
                         String endTime, ErrorCallback<Object> callback) {
        Device device = storager.queryVideoDevice(deviceId);
        if (device == null) {
            logger.warn("[录像回放] æœªæ‰¾åˆ°è®¾å¤‡ deviceId: {},channelId:{}", deviceId, channelId);
@@ -651,8 +666,8 @@
    @Override
    public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
                                                          String deviceId, String channelId, String startTime,
                                                          String endTime, ErrorCallback<Object> callback) {
                         String deviceId, String channelId, String startTime,
                         String endTime, ErrorCallback<Object> callback) {
        if (mediaServerItem == null || ssrcInfo == null) {
            callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
                    InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
@@ -1548,16 +1563,16 @@
        MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
        play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{
           if (code == InviteErrorCode.SUCCESS.getCode()) {
               InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
               if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) {
                   getSnap(deviceId, channelId, fileName, errorCallback);
               }else {
                   errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
               }
           }else {
               errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
           }
            if (code == InviteErrorCode.SUCCESS.getCode()) {
                InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
                if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) {
                    getSnap(deviceId, channelId, fileName, errorCallback);
                }else {
                    errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
                }
            }else {
                errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
            }
        });
    }
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -20,11 +20,11 @@
    @Insert("INSERT INTO wvp_device_channel (channel_id, device_id, name, manufacture, model, owner, civil_code, block, " +
            "address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
            "ip_address, port, password, ptz_type, status, stream_id, longitude, latitude, longitude_gcj02, latitude_gcj02, " +
            "longitude_wgs84, latitude_wgs84, has_audio, create_time, update_time, business_group_id, gps_time) " +
            "longitude_wgs84, latitude_wgs84, has_audio, create_time, update_time, business_group_id, gps_time, stream_identification) " +
            "VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," +
            "#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " +
            "#{ipAddress}, #{port}, #{password}, #{PTZType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " +
            "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime})")
            "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime}, #{streamIdentification})")
    int add(DeviceChannel channel);
    @Update(value = {" <script>" +
@@ -60,6 +60,7 @@
            "<if test='latitudeWgs84 != null'>, latitude_wgs84=#{latitudeWgs84}</if>" +
            "<if test='businessGroupId != null'>, business_group_id=#{businessGroupId}</if>" +
            "<if test='gpsTime != null'>, gps_time=#{gpsTime}</if>" +
            "<if test='streamIdentification != null'>, stream_identification=#{streamIdentification}</if>" +
            "WHERE device_id=#{deviceId} AND channel_id=#{channelId}"+
            " </script>"})
    int update(DeviceChannel channel);
@@ -102,6 +103,7 @@
            "dc.longitude_wgs84, " +
            "dc.latitude_wgs84, " +
            "dc.business_group_id, " +
            "dc.stream_identification, " +
            "dc.gps_time " +
            "from " +
            "wvp_device_channel dc " +
@@ -241,7 +243,7 @@
            "(channel_id, device_id, name, manufacture, model, owner, civil_code, block, sub_count, " +
            "  address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
            "  ip_address,port,password,ptz_type,status,stream_id,longitude,latitude,longitude_gcj02,latitude_gcj02,"+
            "  longitude_wgs84,latitude_wgs84,has_audio,create_time,update_time,business_group_id,gps_time)"+
            "  longitude_wgs84,latitude_wgs84,has_audio,create_time,update_time,business_group_id,gps_time,stream_identification)"+
            "values " +
            "<foreach collection='addChannels' index='index' item='item' separator=','> " +
            "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " +
@@ -251,7 +253,7 @@
            "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " +
            "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " +
            "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " +
            "#{item.businessGroupId}, #{item.gpsTime}) " +
            "#{item.businessGroupId}, #{item.gpsTime}, #{item.streamIdentification}) " +
            "</foreach> " +
            "</script>")
    int batchAdd(@Param("addChannels") List<DeviceChannel> addChannels);
@@ -349,6 +351,7 @@
            "<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
            "<if test='item.businessGroupId != null'>, business_group_id=#{item.businessGroupId}</if>" +
            "<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
            "<if test='item.streamIdentification != null'>, stream_identification=#{item.streamIdentification}</if>" +
            "<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
            "<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" +
            "</foreach>" +
@@ -542,4 +545,9 @@
            " </script>"})
    List<DeviceChannel> getSubChannelsByDeviceId(@Param("deviceId") String deviceId, @Param("parentId") String parentId, @Param("onlyCatalog") boolean onlyCatalog);
    @Update("<script>" +
            "UPDATE wvp_device_channel SET stream_identification=#{streamIdentification} WHERE device_id=#{deviceId}" +
            " <if test='channelId != null'> and channel_id = #{channelId} </if>" +
            "</script>")
    void updateChannelStreamIdentification(DeviceChannel channel);
}
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -43,7 +43,6 @@
            "geo_coord_sys," +
            "on_line," +
            "media_server_id," +
            "switch_primary_sub_stream," +
            "broadcast_push_after_ack," +
            "(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+
            " FROM wvp_device WHERE device_id = #{deviceId}")
@@ -163,7 +162,6 @@
            "geo_coord_sys,"+
            "on_line,"+
            "media_server_id,"+
            "switch_primary_sub_stream switchPrimarySubStream,"+
            "(SELECT count(0) FROM wvp_device_channel WHERE device_id=de.device_id) as channel_count " +
            "FROM wvp_device de" +
            "<if test=\"onLine != null\"> where on_line=${onLine}</if>"+
@@ -256,7 +254,6 @@
            "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
            "<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" +
            "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
            "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +
            "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
            "WHERE device_id=#{deviceId}"+
            " </script>"})
@@ -275,8 +272,7 @@
            "broadcastPushAfterAck,"+
            "geo_coord_sys,"+
            "on_line,"+
            "media_server_id,"+
            "switch_primary_sub_stream"+
            "media_server_id"+
            ") VALUES (" +
            "#{deviceId}," +
            "#{name}," +
@@ -290,8 +286,7 @@
            "#{broadcastPushAfterAck}," +
            "#{geoCoordSys}," +
            "#{onLine}," +
            "#{mediaServerId}," +
            "#{switchPrimarySubStream}" +
            "#{mediaServerId}" +
            ")")
    void addCustomDevice(Device device);
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -153,10 +153,7 @@
        Device device = storager.queryVideoDevice(deviceId);
        device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires));
        device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
        deviceService.updateDevice(device);
        if (!deviceService.removeMobilePositionSubscribe(device)) {
            throw new ControllerException(ErrorCode.ERROR100);
        }
        deviceService.updateCustomDevice(device);
    }
    /**
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -199,7 +199,7 @@
                    Runnable runnable = dynamicTask.get(key);
                    if (runnable instanceof ISubscribeTask) {
                        ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
                        subscribeTask.stop();
                        subscribeTask.stop(null);
                    }
                    dynamicTask.stop(key);
                }
@@ -264,6 +264,14 @@
        deviceChannelService.updateChannel(deviceId, channel);
    }
    @Operation(summary = "修改通道的码流类型", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "deviceId", description = "设备国标编号", required = true)
    @Parameter(name = "channel", description = "通道信息", required = true)
    @PostMapping("/channel/stream/identification/update/")
    public void updateChannelStreamIdentification(DeviceChannel channel){
        deviceChannelService.updateChannelStreamIdentification(channel);
    }
    /**
     * ä¿®æ”¹æ•°æ®æµä¼ è¾“模式
     * @param deviceId è®¾å¤‡id
web_src/src/components/channelList.vue
@@ -13,24 +13,30 @@
                    prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
          é€šé“类型:
          <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择"
          <el-select size="mini" @change="search" style="width: 8rem; margin-right: 1rem;" v-model="channelType" placeholder="请选择"
                     default-first-option>
            <el-option label="全部" value=""></el-option>
            <el-option label="设备" value="false"></el-option>
            <el-option label="子目录" value="true"></el-option>
          </el-select>
          åœ¨çº¿çŠ¶æ€:
          <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
          <el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
                     default-first-option>
            <el-option label="全部" value=""></el-option>
            <el-option label="在线" value="true"></el-option>
            <el-option label="离线" value="false"></el-option>
          </el-select>
          æ¸…晰度:
          <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="isSubStream" placeholder="请选择"
                     default-first-option>
            <el-option label="原画" :value="false"></el-option>
            <el-option label="流畅" :value="true"></el-option>
          ç æµç±»åž‹é‡ç½®:
          <el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream"
                     placeholder="请选择码流类型" default-first-option >
            <el-option label="stream:0(主码流)" value="stream:0"></el-option>
            <el-option label="stream:1(子码流)" value="stream:1"></el-option>
            <el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
            <el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
            <el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
            <el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
            <el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
            <el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
          </el-select>
        </div>
        <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
@@ -46,11 +52,11 @@
      <el-main style="padding: 5px;">
        <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%"
                  header-row-class-name="table-header">
          <el-table-column prop="channelId" label="通道编号" min-width="200">
          <el-table-column prop="channelId" label="通道编号" min-width="180">
          </el-table-column>
          <el-table-column prop="deviceId" label="设备编号" min-width="200">
          <el-table-column prop="deviceId" label="设备编号" min-width="180">
          </el-table-column>
          <el-table-column prop="name" label="通道名称" min-width="200">
          <el-table-column prop="name" label="通道名称" min-width="180">
            <template v-slot:default="scope">
              <el-input
                v-show="scope.row.edit"
@@ -63,7 +69,7 @@
              <span v-show="!scope.row.edit">{{ scope.row.name }}</span>
            </template>
          </el-table-column>
          <el-table-column label="快照" min-width="120">
          <el-table-column label="快照" min-width="100">
            <template v-slot:default="scope">
              <el-image
                :src="getSnap(scope.row)"
@@ -77,11 +83,11 @@
              </el-image>
            </template>
          </el-table-column>
          <el-table-column prop="subCount" label="子节点数" min-width="120">
          <el-table-column prop="subCount" label="子节点数" min-width="100">
          </el-table-column>
          <el-table-column prop="manufacture" label="厂家" min-width="120">
          <el-table-column prop="manufacture" label="厂家" min-width="100">
          </el-table-column>
          <el-table-column label="位置信息" min-width="200">
          <el-table-column label="位置信息" min-width="120">
            <template v-slot:default="scope">
              <el-input
                v-show="scope.row.edit"
@@ -94,7 +100,7 @@
              <span v-show="!scope.row.edit">{{ scope.row.location }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="PTZType" label="云台类型" min-width="120">
          <el-table-column prop="PTZType" label="云台类型" min-width="100">
            <template v-slot:default="scope">
              <el-select v-show="scope.row.edit" v-model="scope.row.PTZType"
                         placeholder="云台类型" filterable>
@@ -108,13 +114,28 @@
              <div v-show="!scope.row.edit">{{ scope.row.PTZTypeText }}</div>
            </template>
          </el-table-column>
          <el-table-column label="开启音频" min-width="120">
          <el-table-column label="开启音频" min-width="100">
            <template slot-scope="scope">
              <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
              </el-switch>
            </template>
          </el-table-column>
          <el-table-column label="状态" min-width="120">
          <el-table-column label="码流类型" min-width="180">
            <template slot-scope="scope">
              <el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
                         placeholder="请选择码流类型" default-first-option >
                <el-option label="stream:0(主码流)" value="stream:0"></el-option>
                <el-option label="stream:1(子码流)" value="stream:1"></el-option>
                <el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
                <el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
                <el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
                <el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
                <el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
                <el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
              </el-select>
            </template>
          </el-table-column>
          <el-table-column label="状态" min-width="100">
            <template slot-scope="scope">
              <div slot="reference" class="name-wrapper">
                <el-tag size="medium" v-if="scope.row.status === true">在线</el-tag>
@@ -122,8 +143,6 @@
              </div>
            </template>
          </el-table-column>
          <el-table-column label="操作" min-width="340" fixed="right">
            <template slot-scope="scope">
              <el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
@@ -213,7 +232,7 @@
      searchSrt: "",
      channelType: "",
      online: "",
      isSubStream: false,
      subStream: "",
      winHeight: window.innerHeight - 200,
      currentPage: 1,
      count: 15,
@@ -495,6 +514,43 @@
        console.log(JSON.stringify(res));
      });
    },
    subStreamChange: function () {
      this.$confirm('确定重置所有通道的码流类型?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$axios({
          method: 'post',
          url: `/api/device/query/channel/stream/identification/update/`,
          params: {
            deviceId: this.deviceId,
            streamIdentification: this.subStream
          }
        }).then((res)=> {
          console.log(JSON.stringify(res));
          this.initData()
        }).finally(()=>{
          this.subStream = ""
        })
      }).catch(() => {
        this.subStream = ""
      });
    },
    channelSubStreamChange: function (row) {
      this.$axios({
        method: 'post',
        url: `/api/device/query/channel/stream/identification/update/`,
        params: {
          deviceId: this.deviceId,
          channelId: row.channelId,
          streamIdentification: row.streamIdentification
        }
      }).then(function (res) {
        console.log(JSON.stringify(res));
      });
    },
    refresh: function () {
      this.initData();
    },
web_src/src/components/dialog/deviceEdit.vue
@@ -61,12 +61,6 @@
          <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
            <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
          </el-form-item>
          <el-form-item label="主子码流开关" prop="switchPrimarySubStream" >
            <el-select v-model="form.switchPrimarySubStream" style="float: left; width: 100%" >
              <el-option key="true" label="开启" :value="true"></el-option>
              <el-option key="false" label="关闭" :value="false"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="其他选项">
            <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
            <el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox>
Êý¾Ý¿â/2.7.0/³õʼ»¯-mysql-2.7.0.sql
New file
@@ -0,0 +1,324 @@
/*建表*/
create table wvp_device (
                            id serial primary key ,
                            device_id character varying(50) not null ,
                            name character varying(255),
                            manufacturer character varying(255),
                            model character varying(255),
                            firmware character varying(255),
                            transport character varying(50),
                            stream_mode character varying(50),
                            on_line bool default false,
                            register_time character varying(50),
                            keepalive_time character varying(50),
                            ip character varying(50),
                            create_time character varying(50),
                            update_time character varying(50),
                            port integer,
                            expires integer,
                            subscribe_cycle_for_catalog integer DEFAULT 0,
                            subscribe_cycle_for_mobile_position integer DEFAULT 0,
                            mobile_position_submission_interval integer DEFAULT 5,
                            subscribe_cycle_for_alarm integer DEFAULT 0,
                            host_address character varying(50),
                            charset character varying(50),
                            ssrc_check bool default false,
                            geo_coord_sys character varying(50),
                            media_server_id character varying(50),
                            custom_name character varying(255),
                            sdp_ip character varying(50),
                            local_ip character varying(50),
                            password character varying(255),
                            as_message_channel bool default false,
                            keepalive_interval_time integer,
                            switch_primary_sub_stream bool default false,
                            broadcast_push_after_ack bool default false,
                            constraint uk_device_device unique (device_id)
);
create table wvp_device_alarm (
                                  id serial primary key ,
                                  device_id character varying(50) not null,
                                  channel_id character varying(50) not null,
                                  alarm_priority character varying(50),
                                  alarm_method character varying(50),
                                  alarm_time character varying(50),
                                  alarm_description character varying(255),
                                  longitude double precision,
                                  latitude double precision,
                                  alarm_type character varying(50),
                                  create_time character varying(50) not null
);
create table wvp_device_channel (
                                    id serial primary key ,
                                    channel_id character varying(50) not null,
                                    name character varying(255),
                                    custom_name character varying(255),
                                    manufacture character varying(50),
                                    model character varying(50),
                                    owner character varying(50),
                                    civil_code character varying(50),
                                    block character varying(50),
                                    address character varying(50),
                                    parent_id character varying(50),
                                    safety_way integer,
                                    register_way integer,
                                    cert_num character varying(50),
                                    certifiable integer,
                                    err_code integer,
                                    end_time character varying(50),
                                    secrecy character varying(50),
                                    ip_address character varying(50),
                                    port integer,
                                    password character varying(255),
                                    ptz_type integer,
                                    custom_ptz_type integer,
                                    status bool default false,
                                    longitude double precision,
                                    custom_longitude double precision,
                                    latitude double precision,
                                    custom_latitude double precision,
                                    stream_id character varying(255),
                                    device_id character varying(50) not null,
                                    parental character varying(50),
                                    has_audio bool default false,
                                    create_time character varying(50) not null,
                                    update_time character varying(50) not null,
                                    sub_count integer,
                                    longitude_gcj02 double precision,
                                    latitude_gcj02 double precision,
                                    longitude_wgs84 double precision,
                                    latitude_wgs84 double precision,
                                    business_group_id character varying(50),
                                    gps_time character varying(50),
                                    stream_identification character varying(50),
                                    constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
);
create table wvp_device_mobile_position (
                                            id serial primary key,
                                            device_id character varying(50) not null,
                                            channel_id character varying(50) not null,
                                            device_name character varying(255),
                                            time character varying(50),
                                            longitude double precision,
                                            latitude double precision,
                                            altitude double precision,
                                            speed double precision,
                                            direction double precision,
                                            report_source character varying(50),
                                            longitude_gcj02 double precision,
                                            latitude_gcj02 double precision,
                                            longitude_wgs84 double precision,
                                            latitude_wgs84 double precision,
                                            create_time character varying(50)
);
create table wvp_gb_stream (
                               gb_stream_id serial primary key,
                               app character varying(255) not null,
                               stream character varying(255) not null,
                               gb_id character varying(50) not null,
                               name character varying(255),
                               longitude double precision,
                               latitude double precision,
                               stream_type character varying(50),
                               media_server_id character varying(50),
                               create_time character varying(50),
                               constraint uk_gb_stream_unique_gb_id unique (gb_id),
                               constraint uk_gb_stream_unique_app_stream unique (app, stream)
);
create table wvp_log (
                         id serial primary key ,
                         name character varying(50),
                         type character varying(50),
                         uri character varying(200),
                         address character varying(50),
                         result character varying(50),
                         timing bigint,
                         username character varying(50),
                         create_time character varying(50)
);
create table wvp_media_server (
                                  id character varying(255) primary key ,
                                  ip character varying(50),
                                  hook_ip character varying(50),
                                  sdp_ip character varying(50),
                                  stream_ip character varying(50),
                                  http_port integer,
                                  http_ssl_port integer,
                                  rtmp_port integer,
                                  rtmp_ssl_port integer,
                                  rtp_proxy_port integer,
                                  rtsp_port integer,
                                  rtsp_ssl_port integer,
                                  auto_config bool default false,
                                  secret character varying(50),
                                  rtp_enable bool default false,
                                  rtp_port_range character varying(50),
                                  send_rtp_port_range character varying(50),
                                  record_assist_port integer,
                                  default_server bool default false,
                                  create_time character varying(50),
                                  update_time character varying(50),
                                  hook_alive_interval integer,
                                  record_path character varying(255),
                                  record_day integer default 7,
                                  constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
create table wvp_platform (
                              id serial primary key ,
                              enable bool default false,
                              name character varying(255),
                              server_gb_id character varying(50),
                              server_gb_domain character varying(50),
                              server_ip character varying(50),
                              server_port integer,
                              device_gb_id character varying(50),
                              device_ip character varying(50),
                              device_port character varying(50),
                              username character varying(255),
                              password character varying(50),
                              expires character varying(50),
                              keep_timeout character varying(50),
                              transport character varying(50),
                              character_set character varying(50),
                              catalog_id character varying(50),
                              ptz bool default false,
                              rtcp bool default false,
                              status bool default false,
                              start_offline_push bool default false,
                              administrative_division character varying(50),
                              catalog_group integer,
                              create_time character varying(50),
                              update_time character varying(50),
                              as_message_channel bool default false,
                              auto_push_channel bool default false,
                              constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
create table wvp_platform_catalog (
                                      id character varying(50),
                                      platform_id character varying(50),
                                      name character varying(255),
                                      parent_id character varying(50),
                                      civil_code character varying(50),
                                      business_group_id character varying(50),
                                      constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
);
create table wvp_platform_gb_channel (
                                         id serial primary key ,
                                         platform_id character varying(50),
                                         catalog_id character varying(50),
                                         device_channel_id integer,
                                         constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
);
create table wvp_platform_gb_stream (
                                        id serial primary key,
                                        platform_id character varying(50),
                                        catalog_id character varying(50),
                                        gb_stream_id integer,
                                        constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
);
create table wvp_stream_proxy (
                                  id serial primary key,
                                  type character varying(50),
                                  app character varying(255),
                                  stream character varying(255),
                                  url character varying(255),
                                  src_url character varying(255),
                                  dst_url character varying(255),
                                  timeout_ms integer,
                                  ffmpeg_cmd_key character varying(255),
                                  rtp_type character varying(50),
                                  media_server_id character varying(50),
                                  enable_audio bool default false,
                                  enable_mp4 bool default false,
                                  enable bool default false,
                                  status boolean,
                                  enable_remove_none_reader bool default false,
                                  create_time character varying(50),
                                  name character varying(255),
                                  update_time character varying(50),
                                  stream_key character varying(255),
                                  enable_disable_none_reader bool default false,
                                  constraint uk_stream_proxy_app_stream unique (app, stream)
);
create table wvp_stream_push (
                                 id serial primary key,
                                 app character varying(255),
                                 stream character varying(255),
                                 total_reader_count character varying(50),
                                 origin_type integer,
                                 origin_type_str character varying(50),
                                 create_time character varying(50),
                                 alive_second integer,
                                 media_server_id character varying(50),
                                 server_id character varying(50),
                                 push_time character varying(50),
                                 status bool default false,
                                 update_time character varying(50),
                                 push_ing bool default false,
                                 self bool default false,
                                 constraint uk_stream_push_app_stream unique (app, stream)
);
create table wvp_cloud_record (
                                  id serial primary key,
                                  app character varying(255),
                                  stream character varying(255),
                                  call_id character varying(255),
                                  start_time bigint,
                                  end_time bigint,
                                  media_server_id character varying(50),
                                  file_name character varying(255),
                                  folder character varying(255),
                                  file_path character varying(255),
                                  collect bool default false,
                                  file_size bigint,
                                  time_len bigint,
                                  constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
);
create table wvp_user (
                          id serial primary key,
                          username character varying(255),
                          password character varying(255),
                          role_id integer,
                          create_time character varying(50),
                          update_time character varying(50),
                          push_key character varying(50),
                          constraint uk_user_username unique (username)
);
create table wvp_user_role (
                               id serial primary key,
                               name character varying(50),
                               authority character varying(50),
                               create_time character varying(50),
                               update_time character varying(50)
);
create table wvp_resources_tree (
                                    id serial primary key ,
                                    is_catalog bool default true,
                                    device_channel_id integer ,
                                    gb_stream_id integer,
                                    name character varying(255),
                                    parentId integer,
                                    path character varying(255)
);
/*初始数据*/
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
Êý¾Ý¿â/2.7.0/³õʼ»¯-postgresql-kingbase-2.7.0.sql
New file
@@ -0,0 +1,324 @@
/*建表*/
create table wvp_device (
                            id serial primary key ,
                            device_id character varying(50) not null ,
                            name character varying(255),
                            manufacturer character varying(255),
                            model character varying(255),
                            firmware character varying(255),
                            transport character varying(50),
                            stream_mode character varying(50),
                            on_line bool default false,
                            register_time character varying(50),
                            keepalive_time character varying(50),
                            ip character varying(50),
                            create_time character varying(50),
                            update_time character varying(50),
                            port integer,
                            expires integer,
                            subscribe_cycle_for_catalog integer DEFAULT 0,
                            subscribe_cycle_for_mobile_position integer DEFAULT 0,
                            mobile_position_submission_interval integer DEFAULT 5,
                            subscribe_cycle_for_alarm integer DEFAULT 0,
                            host_address character varying(50),
                            charset character varying(50),
                            ssrc_check bool default false,
                            geo_coord_sys character varying(50),
                            media_server_id character varying(50),
                            custom_name character varying(255),
                            sdp_ip character varying(50),
                            local_ip character varying(50),
                            password character varying(255),
                            as_message_channel bool default false,
                            keepalive_interval_time integer,
                            switch_primary_sub_stream bool default false,
                            broadcast_push_after_ack bool default false,
                            constraint uk_device_device unique (device_id)
);
create table wvp_device_alarm (
                                  id serial primary key ,
                                  device_id character varying(50) not null,
                                  channel_id character varying(50) not null,
                                  alarm_priority character varying(50),
                                  alarm_method character varying(50),
                                  alarm_time character varying(50),
                                  alarm_description character varying(255),
                                  longitude double precision,
                                  latitude double precision,
                                  alarm_type character varying(50),
                                  create_time character varying(50) not null
);
create table wvp_device_channel (
                                    id serial primary key ,
                                    channel_id character varying(50) not null,
                                    name character varying(255),
                                    custom_name character varying(255),
                                    manufacture character varying(50),
                                    model character varying(50),
                                    owner character varying(50),
                                    civil_code character varying(50),
                                    block character varying(50),
                                    address character varying(50),
                                    parent_id character varying(50),
                                    safety_way integer,
                                    register_way integer,
                                    cert_num character varying(50),
                                    certifiable integer,
                                    err_code integer,
                                    end_time character varying(50),
                                    secrecy character varying(50),
                                    ip_address character varying(50),
                                    port integer,
                                    password character varying(255),
                                    ptz_type integer,
                                    custom_ptz_type integer,
                                    status bool default false,
                                    longitude double precision,
                                    custom_longitude double precision,
                                    latitude double precision,
                                    custom_latitude double precision,
                                    stream_id character varying(255),
                                    device_id character varying(50) not null,
                                    parental character varying(50),
                                    has_audio bool default false,
                                    create_time character varying(50) not null,
                                    update_time character varying(50) not null,
                                    sub_count integer,
                                    longitude_gcj02 double precision,
                                    latitude_gcj02 double precision,
                                    longitude_wgs84 double precision,
                                    latitude_wgs84 double precision,
                                    business_group_id character varying(50),
                                    gps_time character varying(50),
                                    stream_identification character varying(50),
                                    constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
);
create table wvp_device_mobile_position (
                                            id serial primary key,
                                            device_id character varying(50) not null,
                                            channel_id character varying(50) not null,
                                            device_name character varying(255),
                                            time character varying(50),
                                            longitude double precision,
                                            latitude double precision,
                                            altitude double precision,
                                            speed double precision,
                                            direction double precision,
                                            report_source character varying(50),
                                            longitude_gcj02 double precision,
                                            latitude_gcj02 double precision,
                                            longitude_wgs84 double precision,
                                            latitude_wgs84 double precision,
                                            create_time character varying(50)
);
create table wvp_gb_stream (
                               gb_stream_id serial primary key,
                               app character varying(255) not null,
                               stream character varying(255) not null,
                               gb_id character varying(50) not null,
                               name character varying(255),
                               longitude double precision,
                               latitude double precision,
                               stream_type character varying(50),
                               media_server_id character varying(50),
                               create_time character varying(50),
                               constraint uk_gb_stream_unique_gb_id unique (gb_id),
                               constraint uk_gb_stream_unique_app_stream unique (app, stream)
);
create table wvp_log (
                         id serial primary key ,
                         name character varying(50),
                         type character varying(50),
                         uri character varying(200),
                         address character varying(50),
                         result character varying(50),
                         timing bigint,
                         username character varying(50),
                         create_time character varying(50)
);
create table wvp_media_server (
                                  id character varying(255) primary key ,
                                  ip character varying(50),
                                  hook_ip character varying(50),
                                  sdp_ip character varying(50),
                                  stream_ip character varying(50),
                                  http_port integer,
                                  http_ssl_port integer,
                                  rtmp_port integer,
                                  rtmp_ssl_port integer,
                                  rtp_proxy_port integer,
                                  rtsp_port integer,
                                  rtsp_ssl_port integer,
                                  auto_config bool default false,
                                  secret character varying(50),
                                  rtp_enable bool default false,
                                  rtp_port_range character varying(50),
                                  send_rtp_port_range character varying(50),
                                  record_assist_port integer,
                                  default_server bool default false,
                                  create_time character varying(50),
                                  update_time character varying(50),
                                  hook_alive_interval integer,
                                  record_path character varying(255),
                                  record_day integer default 7,
                                  constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
create table wvp_platform (
                              id serial primary key ,
                              enable bool default false,
                              name character varying(255),
                              server_gb_id character varying(50),
                              server_gb_domain character varying(50),
                              server_ip character varying(50),
                              server_port integer,
                              device_gb_id character varying(50),
                              device_ip character varying(50),
                              device_port character varying(50),
                              username character varying(255),
                              password character varying(50),
                              expires character varying(50),
                              keep_timeout character varying(50),
                              transport character varying(50),
                              character_set character varying(50),
                              catalog_id character varying(50),
                              ptz bool default false,
                              rtcp bool default false,
                              status bool default false,
                              start_offline_push bool default false,
                              administrative_division character varying(50),
                              catalog_group integer,
                              create_time character varying(50),
                              update_time character varying(50),
                              as_message_channel bool default false,
                              auto_push_channel bool default false,
                              constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
create table wvp_platform_catalog (
                                      id character varying(50),
                                      platform_id character varying(50),
                                      name character varying(255),
                                      parent_id character varying(50),
                                      civil_code character varying(50),
                                      business_group_id character varying(50),
                                      constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
);
create table wvp_platform_gb_channel (
                                         id serial primary key ,
                                         platform_id character varying(50),
                                         catalog_id character varying(50),
                                         device_channel_id integer,
                                         constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
);
create table wvp_platform_gb_stream (
                                        id serial primary key,
                                        platform_id character varying(50),
                                        catalog_id character varying(50),
                                        gb_stream_id integer,
                                        constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
);
create table wvp_stream_proxy (
                                  id serial primary key,
                                  type character varying(50),
                                  app character varying(255),
                                  stream character varying(255),
                                  url character varying(255),
                                  src_url character varying(255),
                                  dst_url character varying(255),
                                  timeout_ms integer,
                                  ffmpeg_cmd_key character varying(255),
                                  rtp_type character varying(50),
                                  media_server_id character varying(50),
                                  enable_audio bool default false,
                                  enable_mp4 bool default false,
                                  enable bool default false,
                                  status boolean,
                                  enable_remove_none_reader bool default false,
                                  create_time character varying(50),
                                  name character varying(255),
                                  update_time character varying(50),
                                  stream_key character varying(255),
                                  enable_disable_none_reader bool default false,
                                  constraint uk_stream_proxy_app_stream unique (app, stream)
);
create table wvp_stream_push (
                                 id serial primary key,
                                 app character varying(255),
                                 stream character varying(255),
                                 total_reader_count character varying(50),
                                 origin_type integer,
                                 origin_type_str character varying(50),
                                 create_time character varying(50),
                                 alive_second integer,
                                 media_server_id character varying(50),
                                 server_id character varying(50),
                                 push_time character varying(50),
                                 status bool default false,
                                 update_time character varying(50),
                                 push_ing bool default false,
                                 self bool default false,
                                 constraint uk_stream_push_app_stream unique (app, stream)
);
create table wvp_cloud_record (
                                  id serial primary key,
                                  app character varying(255),
                                  stream character varying(255),
                                  call_id character varying(255),
                                  start_time int8,
                                  end_time int8,
                                  media_server_id character varying(50),
                                  file_name character varying(255),
                                  folder character varying(255),
                                  file_path character varying(255),
                                  collect bool default false,
                                  file_size int8,
                                  time_len int8,
                                  constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
);
create table wvp_user (
                          id serial primary key,
                          username character varying(255),
                          password character varying(255),
                          role_id integer,
                          create_time character varying(50),
                          update_time character varying(50),
                          push_key character varying(50),
                          constraint uk_user_username unique (username)
);
create table wvp_user_role (
                               id serial primary key,
                               name character varying(50),
                               authority character varying(50),
                               create_time character varying(50),
                               update_time character varying(50)
);
create table wvp_resources_tree (
                                    id serial primary key ,
                                    is_catalog bool default true,
                                    device_channel_id integer ,
                                    gb_stream_id integer,
                                    name character varying(255),
                                    parentId integer,
                                    path character varying(255)
);
/*初始数据*/
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
Êý¾Ý¿â/2.7.0/¸üÐÂ-mysql-2.7.0.sql
New file
@@ -0,0 +1,5 @@
alter table wvp_device_channel
    add stream_identification character varying(50);
alter table wvp_device
    drop switch_primary_sub_stream;
Êý¾Ý¿â/2.7.0/¸üÐÂ-postgresql-kingbase-2.7.0.sql
New file
@@ -0,0 +1,5 @@
alter table wvp_device_channel
    add stream_identification character varying(50);
alter table wvp_device
    drop switch_primary_sub_stream;