648540858
2024-04-09 b1b6fae22c5ab3013d73df1a43cd42f7fe0fa347
Merge branch 'master' into dev/zlm

# Conflicts:
# src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
# src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
# src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
# src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java
# src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java
18个文件已修改
245 ■■■■■ 已修改文件
README.md 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java 98 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/dialog/platformEdit.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/初始化-mysql-2.7.0.sql 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/初始化-postgresql-kingbase-2.7.0.sql 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/更新-mysql-2.7.0.sql 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
数据库/2.7.0/更新-postgresql-kingbase-2.7.0.sql 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -136,12 +136,6 @@
[ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666)
[mk1990](https://github.com/mk1990) [SaltFish001](https://github.com/SaltFish001)
同时感谢JetBrains对开源项目的支持,本项目使用IntelliJ IDEA开发与调试:
ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1  -f rtsp rtsp://192.168.1.3:30554/broadcast/34020000001320000101_34020000001310000001
ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1  -f rtsp rtsp://192.168.1.3:30554/talk/34020000001320000011_34020000001370000001
ffmpeg -re -i 123.mp3 -acodec pcm_alaw -ar 8000 -ac 1  -f rtsp rtsp://192.168.1.3:30554/talk/34020000001320000101_34020000001310000001
![JetBrains](https://resources.jetbrains.com/storage/products/company/brand/logos/IntelliJ_IDEA_icon.svg?_ga=2.143694769.529214288.1712023294-439039083.1711422571&_gl=1*102dv9n*_ga*NDM5MDM5MDgzLjE3MTE0MjI1NzE.*_ga_9J976DJZ68*MTcxMjEyNjg4NC45LjEuMTcxMjEyNzc2My4zMy4wLjA.)
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -189,6 +189,9 @@
    @Schema(description = "是否作为消息通道")
    private boolean autoPushChannel;
    @Schema(description = "点播回复200OK使用次IP")
    private String sendStreamIp;
    public Integer getId() {
        return id;
    }
@@ -436,4 +439,12 @@
    public void setAutoPushChannel(boolean autoPushChannel) {
        this.autoPushChannel = autoPushChannel;
    }
    public String getSendStreamIp() {
        return sendStreamIp;
    }
    public void setSendStreamIp(String sendStreamIp) {
        this.sendStreamIp = sendStreamIp;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
@@ -305,4 +305,33 @@
    public void setReceiveStream(String receiveStream) {
        this.receiveStream = receiveStream;
    }
    @Override
    public String toString() {
        return "SendRtpItem{" +
                "ip='" + ip + '\'' +
                ", port=" + port +
                ", ssrc='" + ssrc + '\'' +
                ", platformId='" + platformId + '\'' +
                ", deviceId='" + deviceId + '\'' +
                ", app='" + app + '\'' +
                ", channelId='" + channelId + '\'' +
                ", status=" + status +
                ", stream='" + stream + '\'' +
                ", tcp=" + tcp +
                ", tcpActive=" + tcpActive +
                ", localPort=" + localPort +
                ", mediaServerId='" + mediaServerId + '\'' +
                ", serverId='" + serverId + '\'' +
                ", CallId='" + CallId + '\'' +
                ", fromTag='" + fromTag + '\'' +
                ", toTag='" + toTag + '\'' +
                ", pt=" + pt +
                ", usePs=" + usePs +
                ", onlyAudio=" + onlyAudio +
                ", rtcp=" + rtcp +
                ", playType=" + playType +
                ", receiveStream='" + receiveStream + '\'' +
                '}';
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -116,7 +116,7 @@
        if (parentPlatform != null) {
            Map<String, Object> param = getSendRtpParam(sendRtpItem);
            if (mediaInfo == null) {
            if (!userSetting.getServerId().equals(sendRtpItem.getServerId())) {
                RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
                        sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(),
                        sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(),
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -41,6 +41,7 @@
import gov.nist.javax.sdp.fields.URIField;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -407,12 +408,15 @@
                        //     * 2 æŽ¨æµä¸­
                        sendRtpItem.setStatus(1);
                        redisCatchStorage.updateSendRTPSever(sendRtpItem);
                        String sdpIp = mediaServerItemInUSe.getSdpIp();
                        if (!ObjectUtils.isEmpty(platform.getSendStreamIp())) {
                            sdpIp = platform.getSendStreamIp();
                        }
                        StringBuffer content = new StringBuffer(200);
                        content.append("v=0\r\n");
                        content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
                        content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n");
                        content.append("s=" + sessionName + "\r\n");
                        content.append("c=IN IP4 " + mediaServerItemInUSe.getSdpIp() + "\r\n");
                        content.append("c=IN IP4 " + sdpIp + "\r\n");
                        if ("Playback".equalsIgnoreCase(sessionName)) {
                            content.append("t=" + finalStartTime + " " + finalStopTime + "\r\n");
                        } else {
@@ -578,14 +582,20 @@
                    }
                    if ("push".equals(gbStream.getStreamType())) {
                        if (streamPushItem != null && streamPushItem.isPushIng()) {
                            // æŽ¨æµçŠ¶æ€
                            pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        } else {
                            // æœªæŽ¨æµ æ‹‰èµ·
                            notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                        if (streamPushItem != null) {
                            // ä»Žredis查询是否正在接收这个推流
                            OnStreamChangedHookParam pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream());
                            if (pushListItem != null) {
                                StreamPushItem transform = streamPushService.transform(pushListItem);
                                transform.setSelf(userSetting.getServerId().equals(pushListItem.getSeverId()));
                                // æŽ¨æµçŠ¶æ€
                                pushStream(evt, request, gbStream, transform, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                            }else {
                                // æœªæŽ¨æµ æ‹‰èµ·
                                notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
                            }
                        }
                    } else if ("proxy".equals(gbStream.getStreamType())) {
                        if (null != proxyByAppAndStream) {
@@ -903,11 +913,15 @@
    public SIPResponse sendStreamAck(MediaServer mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
        String sdpIp = mediaServerItem.getSdpIp();
        if (!ObjectUtils.isEmpty(platform.getSendStreamIp())) {
            sdpIp = platform.getSendStreamIp();
        }
        StringBuffer content = new StringBuffer(200);
        content.append("v=0\r\n");
        content.append("o=" + sendRtpItem.getChannelId() + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
        content.append("o=" + sendRtpItem.getChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n");
        content.append("s=Play\r\n");
        content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
        content.append("c=IN IP4 " + sdpIp + "\r\n");
        content.append("t=0 0\r\n");
        // éžä¸¥æ ¼æ¨¡å¼ç«¯å£ä¸ç»Ÿä¸€, å¢žåŠ å…¼å®¹æ€§ï¼Œä¿®æ”¹ä¸ºä¸€ä¸ªä¸ä¸º0的端口
        int localPort = sendRtpItem.getLocalPort();
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -1275,7 +1275,7 @@
            dynamicTask.startDelay(key, ()->{
                logger.info("[语音广播]等待invite消息超时:{}/{}", device.getDeviceId(), channelId);
                stopAudioBroadcast(device.getDeviceId(), channelId);
            }, 2000);
            }, 10*1000);
        }, eventResultForError -> {
            // å‘送失败
            logger.error("语音广播发送失败: {}:{}", channelId, eventResultForError.msg);
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
@@ -2,7 +2,6 @@
import com.alibaba.fastjson2.JSON;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
@@ -25,7 +24,6 @@
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java
@@ -1,11 +1,7 @@
package com.genersoft.iot.vmp.service.redisMsg;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,52 +37,52 @@
    @Override
    public void onMessage(Message message, byte[] bytes) {
        boolean isEmpty = taskQueue.isEmpty();
        taskQueue.offer(message);
        if (isEmpty) {
            taskExecutor.execute(() -> {
                while (!taskQueue.isEmpty()) {
                    Message msg = taskQueue.poll();
                    try {
                        JSONObject steamMsgJson = JSON.parseObject(msg.getBody(), JSONObject.class);
                        if (steamMsgJson == null) {
                            logger.warn("[收到redis æµå˜åŒ–]消息解析失败");
                            continue;
                        }
                        String serverId = steamMsgJson.getString("serverId");
                        if (userSetting.getServerId().equals(serverId)) {
                            // è‡ªå·±å‘送的消息忽略即可
                            continue;
                        }
                        logger.info("[收到redis æµå˜åŒ–]: {}", new String(message.getBody()));
                        String app = steamMsgJson.getString("app");
                        String stream = steamMsgJson.getString("stream");
                        boolean register = steamMsgJson.getBoolean("register");
                        String mediaServerId = steamMsgJson.getString("mediaServerId");
                        OnStreamChangedHookParam onStreamChangedHookParam = new OnStreamChangedHookParam();
                        onStreamChangedHookParam.setSeverId(serverId);
                        onStreamChangedHookParam.setApp(app);
                        onStreamChangedHookParam.setStream(stream);
                        onStreamChangedHookParam.setRegist(register);
                        onStreamChangedHookParam.setMediaServerId(mediaServerId);
                        onStreamChangedHookParam.setCreateStamp(System.currentTimeMillis()/1000);
                        onStreamChangedHookParam.setAliveSecond(0L);
                        onStreamChangedHookParam.setTotalReaderCount(0);
                        onStreamChangedHookParam.setOriginType(0);
                        onStreamChangedHookParam.setOriginTypeStr("0");
                        onStreamChangedHookParam.setOriginTypeStr("unknown");
                        if (register) {
                            zlmMediaListManager.addPush(onStreamChangedHookParam);
                        }else {
                            zlmMediaListManager.removeMedia(app, stream);
                        }
                    }catch (Exception e) {
                        logger.warn("[REDIS消息-流变化] å‘现未处理的异常, \r\n{}", JSON.toJSONString(message));
                        logger.error("[REDIS消息-流变化] å¼‚常内容: ", e);
                    }
                }
            });
        }
//        boolean isEmpty = taskQueue.isEmpty();
//        taskQueue.offer(message);
//        if (isEmpty) {
//            taskExecutor.execute(() -> {
//                while (!taskQueue.isEmpty()) {
//                    Message msg = taskQueue.poll();
//                    try {
//                        JSONObject steamMsgJson = JSON.parseObject(msg.getBody(), JSONObject.class);
//                        if (steamMsgJson == null) {
//                            logger.warn("[收到redis æµå˜åŒ–]消息解析失败");
//                            continue;
//                        }
//                        String serverId = steamMsgJson.getString("serverId");
//
//                        if (userSetting.getServerId().equals(serverId)) {
//                            // è‡ªå·±å‘送的消息忽略即可
//                            continue;
//                        }
//                        logger.info("[收到redis æµå˜åŒ–]: {}", new String(message.getBody()));
//                        String app = steamMsgJson.getString("app");
//                        String stream = steamMsgJson.getString("stream");
//                        boolean register = steamMsgJson.getBoolean("register");
//                        String mediaServerId = steamMsgJson.getString("mediaServerId");
//                        OnStreamChangedHookParam onStreamChangedHookParam = new OnStreamChangedHookParam();
//                        onStreamChangedHookParam.setSeverId(serverId);
//                        onStreamChangedHookParam.setApp(app);
//                        onStreamChangedHookParam.setStream(stream);
//                        onStreamChangedHookParam.setRegist(register);
//                        onStreamChangedHookParam.setMediaServerId(mediaServerId);
//                        onStreamChangedHookParam.setCreateStamp(System.currentTimeMillis()/1000);
//                        onStreamChangedHookParam.setAliveSecond(0L);
//                        onStreamChangedHookParam.setTotalReaderCount("0");
//                        onStreamChangedHookParam.setOriginType(0);
//                        onStreamChangedHookParam.setOriginTypeStr("0");
//                        onStreamChangedHookParam.setOriginTypeStr("unknown");
//                        if (register) {
//                            zlmMediaListManager.addPush(onStreamChangedHookParam);
//                        }else {
//                            zlmMediaListManager.removeMedia(app, stream);
//                        }
//                    }catch (Exception e) {
//                        logger.warn("[REDIS消息-流变化] å‘现未处理的异常, \r\n{}", JSON.toJSONString(message));
//                        logger.error("[REDIS消息-流变化] å¼‚常内容: ", e);
//                    }
//                }
//            });
//        }
    }
}
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -212,5 +212,10 @@
    void addPushListItem(String app, String stream, MediaArrivalEvent param);
    OnStreamChangedHookParam getPushListItem(String app, String stream);
    void removePushListItem(String app, String stream, String mediaServerId);
    void sendPushStreamClose(MessageForPushChannel messageForPushChannel);
}
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
@@ -17,10 +17,10 @@
    @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+
            "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,auto_push_channel,"+
            "status,start_offline_push,catalog_id,administrative_division,catalog_group,create_time,update_time) " +
            "status,start_offline_push,catalog_id,administrative_division,catalog_group,create_time,update_time,send_stream_ip) " +
            "            VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
            "            #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, #{autoPushChannel}, " +
            "            #{status},  #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})")
            "            #{status},  #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{sendStreamIp})")
    int addParentPlatform(ParentPlatform parentPlatform);
    @Update("UPDATE wvp_platform " +
@@ -49,6 +49,7 @@
            "administrative_division=#{administrativeDivision}, " +
            "create_time=#{createTime}, " +
            "update_time=#{updateTime}, " +
            "send_stream_ip=#{sendStreamIp}, " +
            "catalog_id=#{catalogId} " +
            "WHERE id=#{id}")
    int updateParentPlatform(ParentPlatform parentPlatform);
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -659,6 +659,12 @@
    }
    @Override
    public OnStreamChangedHookParam getPushListItem(String app, String stream) {
        String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
        return (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key);
    }
    @Override
    public void removePushListItem(String app, String stream, String mediaServerId) {
        String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
        OnStreamChangedHookParam param = (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key);
@@ -667,4 +673,11 @@
        }
    }
    @Override
    public void sendPushStreamClose(MessageForPushChannel msg) {
        String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE_REQUESTED;
        logger.info("[redis发送通知] å‘送 åœæ­¢å‘上级推流 {}: {}/{}->{}", key, msg.getApp(), msg.getStream(), msg.getPlatFormId());
        redisTemplate.convertAndSend(key, JSON.toJSON(msg));
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java
@@ -4,6 +4,7 @@
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.ICloudRecordService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -139,7 +139,8 @@
                wvpResult.setMsg(msg);
            }
            requestMessage.setData(wvpResult);
            resultHolder.invokeResult(requestMessage);
            // æ­¤å¤„必须释放所有请求
            resultHolder.invokeAllResult(requestMessage);
        });
        return result;
    }
web_src/src/components/dialog/platformEdit.vue
@@ -37,8 +37,8 @@
              <el-form-item label="本地端口" prop="devicePort">
                <el-input v-model="platform.devicePort" :disabled="true" type="number"></el-input>
              </el-form-item>
              <el-form-item label="SIP认证用户名" prop="username">
                <el-input v-model="platform.username"></el-input>
              <el-form-item label="SDP发流IP" prop="sendStreamIp">
                <el-input v-model="platform.sendStreamIp"></el-input>
              </el-form-item>
            </el-form>
          </el-col>
@@ -46,6 +46,9 @@
            <el-form ref="platform2" :rules="rules" :model="platform" label-width="160px">
              <el-form-item label="行政区划" prop="administrativeDivision">
                <el-input v-model="platform.administrativeDivision" clearable></el-input>
              </el-form-item>
              <el-form-item label="SIP认证用户名" prop="username">
                <el-input v-model="platform.username"></el-input>
              </el-form-item>
              <el-form-item label="SIP认证密码" prop="password">
                <el-input v-model="platform.password" ></el-input>
@@ -159,7 +162,8 @@
        characterSet: "GB2312",
        startOfflinePush: false,
        catalogGroup: 1,
        administrativeDivision: null,
        administrativeDivision: "",
        sendStreamIp: null,
      },
      rules: {
        name: [{ required: true, message: "请输入平台名称", trigger: "blur" }],
@@ -198,6 +202,7 @@
            that.platform.devicePort = res.data.data.devicePort;
            that.platform.username = res.data.data.username;
            that.platform.password = res.data.data.password;
            that.platform.sendStreamIp = res.data.data.sendStreamIp;
            that.platform.administrativeDivision = res.data.data.username.substr(0, 6);
          }
@@ -228,6 +233,7 @@
        this.platform.catalogId = platform.catalogId;
        this.platform.startOfflinePush = platform.startOfflinePush;
        this.platform.catalogGroup = platform.catalogGroup;
        this.platform.sendStreamIp = platform.sendStreamIp;
        this.platform.administrativeDivision = platform.administrativeDivision;
        this.onSubmit_text = "保存";
        this.saveUrl = "/api/platform/save";
Êý¾Ý¿â/2.7.0/³õʼ»¯-mysql-2.7.0.sql
@@ -198,6 +198,7 @@
                              update_time character varying(50),
                              as_message_channel bool default false,
                              auto_push_channel bool default false,
                              send_stream_ip character varying(50),
                              constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
Êý¾Ý¿â/2.7.0/³õʼ»¯-postgresql-kingbase-2.7.0.sql
@@ -198,6 +198,7 @@
                              update_time character varying(50),
                              as_message_channel bool default false,
                              auto_push_channel bool default false,
                              send_stream_ip character varying(50),
                              constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
Êý¾Ý¿â/2.7.0/¸üÐÂ-mysql-2.7.0.sql
@@ -2,4 +2,7 @@
    add stream_identification character varying(50);
alter table wvp_device
    drop switch_primary_sub_stream;
    drop switch_primary_sub_stream;
alter table wvp_platform
    add send_stream_ip character varying(50);
Êý¾Ý¿â/2.7.0/¸üÐÂ-postgresql-kingbase-2.7.0.sql
@@ -2,4 +2,7 @@
    add stream_identification character varying(50);
alter table wvp_device
    drop switch_primary_sub_stream;
    drop switch_primary_sub_stream;
alter table wvp_platform
    add send_stream_ip character varying(50);