648540858
2024-05-29 764d04b497356ba6bcbb75fd42b51eca750f7223
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
old mode 100644 new mode 100755
@@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
@@ -13,12 +13,11 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.hook.Hook;
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
import com.genersoft.iot.vmp.media.event.hook.HookType;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -39,6 +38,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.header.CallIdHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
@@ -65,16 +65,13 @@
    private SipSubscribe sipSubscribe;
    @Autowired
    private ZLMRTPServerFactory zlmrtpServerFactory;
    @Autowired
    private SipLayer sipLayer;
    @Autowired
    private SIPSender sipSender;
    @Autowired
    private ZlmHttpHookSubscribe subscribe;
    private HookSubscribe subscribe;
    @Autowired
    private UserSetting userSetting;
@@ -167,13 +164,13 @@
        CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
            Request request = headerProviderPlatformProvider.createMessageRequest(
                    parentPlatform,
                    keepaliveXml.toString(),
                    SipUtils.getNewFromTag(),
                    SipUtils.getNewViaTag(),
                    callIdHeader);
            sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
        Request request = headerProviderPlatformProvider.createMessageRequest(
                parentPlatform,
                keepaliveXml.toString(),
                SipUtils.getNewFromTag(),
                SipUtils.getNewViaTag(),
                callIdHeader);
        sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
        return callIdHeader.getCallId();
    }
@@ -228,59 +225,152 @@
                // 行政区划分组只需要这两项就可以
                catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
                catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
                if (channel.getParentId() != null) {
                    // 业务分组加上这一项即可,提高兼容性,
                    catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
//                    catalogXml.append("<ParentID>" + parentPlatform.getDeviceGBId() + "/" + channel.getParentId() + "</ParentID>\r\n");
                }
                if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
                    // 虚拟组织增加BusinessGroupID字段
                    catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
                }
                if (!channel.getChannelId().equals(parentPlatform.getDeviceGBId())) {
                    catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
                    if (channel.getParental() == 0) {
                        catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
                if (channel.getChannelId().length() <= 8) {
                    catalogXml.append("</Item>\r\n");
                    continue;
                }else {
                    if (channel.getChannelId().length() != 20) {
                        catalogXml.append("</Item>\r\n");
                        logger.warn("[编号长度异常] {} 长度错误,请使用20位长度的国标编号,当前长度:{}", channel.getChannelId(), channel.getChannelId().length());
                        catalogXml.append("</Item>\r\n");
                        continue;
                    }
                }
                if (channel.getParental() == 0) {
                    // 通道项
                    catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
                    catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
                    catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
                    String civilCode = channel.getCivilCode() == null?parentPlatform.getAdministrativeDivision() : channel.getCivilCode();
                    if (channel.getChannelType() != 2) {  // 业务分组/虚拟组织/行政区划 不设置以下属性
                        catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
                        catalogXml.append("<Owner>" + parentPlatform.getDeviceGBId()+ "</Owner>\r\n");
                        catalogXml.append("<CivilCode>" + civilCode + "</CivilCode>\r\n");
                        if (channel.getAddress() == null) {
                            catalogXml.append("<Address></Address>\r\n");
                        }else {
                            catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
                        }
                        catalogXml.append("<Block>" + channel.getBlock() + "</Block>\r\n");
                        catalogXml.append("<SafetyWay>" + channel.getSafetyWay() + "</SafetyWay>\r\n");
                        catalogXml.append("<CertNum>" + channel.getCertNum() + "</CertNum>\r\n");
                        catalogXml.append("<Certifiable>" + channel.getCertifiable() + "</Certifiable>\r\n");
                        catalogXml.append("<ErrCode>" + channel.getErrCode() + "</ErrCode>\r\n");
                        catalogXml.append("<EndTime>" + channel.getEndTime() + "</EndTime>\r\n");
                        catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
                        catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
                        catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
                        catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n");
                        catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
                        catalogXml.append("<Status>" + (channel.getStatus() == 1?"ON":"OFF") + "</Status>\r\n");
                        catalogXml.append("<Longitude>" +
                                (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
                                + "</Longitude>\r\n");
                        catalogXml.append("<Latitude>" +
                                (channel.getLatitudeWgs84() != 0? channel.getLatitudeWgs84():channel.getLatitude())
                                + "</Latitude>\r\n");
                    switch (Integer.parseInt(channel.getChannelId().substring(10, 13))){
                        case 200:
//                            catalogXml.append("<Manufacturer>三永华通</Manufacturer>\r\n");
//                            GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil");
//                            String model = (gitUtil == null || gitUtil.getBuildVersion() == null)?"1.0": gitUtil.getBuildVersion();
//                            catalogXml.append("<Model>" + model + "</Manufacturer>\r\n");
//                            catalogXml.append("<Owner>三永华通</Owner>\r\n");
                             if (channel.getCivilCode() != null) {
                                 catalogXml.append("<CivilCode>"+channel.getCivilCode()+"</CivilCode>\r\n");
                             }else {
                                 catalogXml.append("<CivilCode></CivilCode>\r\n");
                             }
                            catalogXml.append("<RegisterWay>1</RegisterWay>\r\n");
                            catalogXml.append("<Secrecy>0</Secrecy>\r\n");
                            break;
                        case 215:
                            if (!ObjectUtils.isEmpty(channel.getParentId())) {
                                catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
                            }
                            break;
                        case 216:
                            if (!ObjectUtils.isEmpty(channel.getParentId())) {
                                catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
                            }else {
                                catalogXml.append("<ParentID></ParentID>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getBusinessGroupId())) {
                                catalogXml.append("<BusinessGroupID>" + channel.getBusinessGroupId() + "</BusinessGroupID>\r\n");
                            }else {
                                catalogXml.append("<BusinessGroupID></BusinessGroupID>\r\n");
                            }
                            break;
                        default:
                            // 通道项
                            if (channel.getManufacture() != null) {
                                catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
                            }else {
                                catalogXml.append("<Manufacturer></Manufacturer>\r\n");
                            }
                            if (channel.getSecrecy() != null) {
                                catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
                            }else {
                                catalogXml.append("<Secrecy></Secrecy>\r\n");
                            }
                            catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
                            if (channel.getModel() != null) {
                                catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
                            }else {
                                catalogXml.append("<Model></Model>\r\n");
                            }
                            if (channel.getOwner() != null) {
                                catalogXml.append("<Owner>" + channel.getOwner()+ "</Owner>\r\n");
                            }else {
                                catalogXml.append("<Owner></Owner>\r\n");
                            }
                            if (channel.getCivilCode() != null) {
                                catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
                            }else {
                                catalogXml.append("<CivilCode></CivilCode>\r\n");
                            }
                            if (channel.getAddress() == null) {
                                catalogXml.append("<Address></Address>\r\n");
                            }else {
                                catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getParentId())) {
                                catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
                            }else {
                                catalogXml.append("<ParentID></ParentID>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getBlock())) {
                                catalogXml.append("<Block>" + channel.getBlock() + "</Block>\r\n");
                            }else {
                                catalogXml.append("<Block></Block>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getSafetyWay())) {
                                catalogXml.append("<SafetyWay>" + channel.getSafetyWay() + "</SafetyWay>\r\n");
                            }else {
                                catalogXml.append("<SafetyWay></SafetyWay>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getCertNum())) {
                                catalogXml.append("<CertNum>" + channel.getCertNum() + "</CertNum>\r\n");
                            }else {
                                catalogXml.append("<CertNum></CertNum>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getCertifiable())) {
                                catalogXml.append("<Certifiable>" + channel.getCertifiable() + "</Certifiable>\r\n");
                            }else {
                                catalogXml.append("<Certifiable></Certifiable>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getErrCode())) {
                                catalogXml.append("<ErrCode>" + channel.getErrCode() + "</ErrCode>\r\n");
                            }else {
                                catalogXml.append("<ErrCode></ErrCode>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getEndTime())) {
                                catalogXml.append("<EndTime>" + channel.getEndTime() + "</EndTime>\r\n");
                            }else {
                                catalogXml.append("<EndTime></EndTime>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getSecrecy())) {
                                catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
                            }else {
                                catalogXml.append("<Secrecy></Secrecy>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getIpAddress())) {
                                catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
                            }else {
                                catalogXml.append("<IPAddress></IPAddress>\r\n");
                            }
                            catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
                            if (!ObjectUtils.isEmpty(channel.getPassword())) {
                                catalogXml.append("<Password>" + channel.getPassword() + "</Password>\r\n");
                            }else {
                                catalogXml.append("<Password></Password>\r\n");
                            }
                            if (!ObjectUtils.isEmpty(channel.getPtzType())) {
                                catalogXml.append("<PTZType>" + channel.getPtzType() + "</PTZType>\r\n");
                            }else {
                                catalogXml.append("<PTZType></PTZType>\r\n");
                            }
                            catalogXml.append("<Status>" + (channel.isStatus() ?"ON":"OFF") + "</Status>\r\n");
                            catalogXml.append("<Longitude>" +
                                    (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
                                    + "</Longitude>\r\n");
                            catalogXml.append("<Latitude>" +
                                    (channel.getLatitudeWgs84() != 0? channel.getLatitudeWgs84():channel.getLatitude())
                                    + "</Latitude>\r\n");
                            break;
                    }
                    catalogXml.append("</Item>\r\n");
                }
                catalogXml.append("</Item>\r\n");
            }
        }
@@ -397,11 +487,11 @@
     * @return
     */
    @Override
    public void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,int status) throws SipException, InvalidArgumentException, ParseException {
    public void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,boolean status) throws SipException, InvalidArgumentException, ParseException {
        if (parentPlatform == null) {
            return ;
        }
        String statusStr = (status==1)?"ONLINE":"OFFLINE";
        String statusStr = (status)?"ONLINE":"OFFLINE";
        String characterSet = parentPlatform.getCharacterSet();
        StringBuffer deviceStatusXml = new StringBuffer(600);
        deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
@@ -425,9 +515,7 @@
        if (parentPlatform == null) {
            return;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
        }
        logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
        String characterSet = parentPlatform.getCharacterSet();
        StringBuffer deviceStatusXml = new StringBuffer(600);
@@ -484,7 +572,7 @@
    @Override
    public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
        if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
        if (parentPlatform == null || deviceChannels == null || deviceChannels.isEmpty() || subscribeInfo == null) {
            return;
        }
        if (index == null) {
@@ -502,6 +590,8 @@
        Integer finalIndex = index;
        String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
                deviceChannels.size(), type, subscribeInfo);
        System.out.println(catalogXmlContent);
        logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
        sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
            logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
        }, (eventResult -> {
@@ -518,28 +608,27 @@
    private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
                                   SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent,  SipSubscribe.Event okEvent )
            throws SipException, ParseException, InvalidArgumentException {
        MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipLayer.getSipFactory().createMessageFactory();
        MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory();
        String characterSet = parentPlatform.getCharacterSet();
        // 设置编码, 防止中文乱码
        messageFactory.setDefaultContentEncodingCharset(characterSet);
        SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
        sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest);
        sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest, errorEvent, okEvent);
    }
    private  String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
        StringBuffer catalogXml = new StringBuffer(600);
        String characterSet = parentPlatform.getCharacterSet();
        catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
                .append("<Notify>\r\n")
                .append("<CmdType>Catalog</CmdType>\r\n")
                .append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n")
                .append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
                .append("<SumNum>1</SumNum>\r\n")
                .append("<SumNum>"+ sumNum +"</SumNum>\r\n")
                .append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
        if (channels.size() > 0) {
        if (!channels.isEmpty()) {
            for (DeviceChannel channel : channels) {
                if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
                    channel.setParentId(parentPlatform.getDeviceGBId());
@@ -562,13 +651,15 @@
                    catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n")
                            .append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n")
                            .append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n")
                            .append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
                            .append("<Status>" + (channel.isStatus() ? "ON" : "OFF") + "</Status>\r\n");
                    if (channel.getChannelType() != 2) {  // 业务分组/虚拟组织/行政区划 不设置以下属性
                        catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n")
                                .append("<Owner> " + channel.getOwner()+ "</Owner>\r\n")
                                .append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n")
                                .append("<Address>" + channel.getAddress() + "</Address>\r\n");
                        catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
                        catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
                    }
                    if (!"presence".equals(subscribeInfo.getEventType())) {
                        catalogXml.append("<Event>" + type + "</Event>\r\n");
@@ -606,6 +697,7 @@
        }else {
            channels = deviceChannels.subList(index, deviceChannels.size());
        }
        logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
        Integer finalIndex = index;
        String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
        sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
@@ -652,13 +744,14 @@
        if ( parentPlatform ==null) {
            return ;
        }
        logger.info("[国标级联] 发送录像数据通道: {}", recordInfo.getChannelId());
        String characterSet = parentPlatform.getCharacterSet();
        StringBuffer recordXml = new StringBuffer(600);
        recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
                .append("<Response>\r\n")
                .append("<CmdType>RecordInfo</CmdType>\r\n")
                .append("<SN>" +recordInfo.getSn() + "</SN>\r\n")
                .append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n")
                .append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n")
                .append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
        if (recordInfo.getRecordList() == null ) {
            recordXml.append("<RecordList Num=\"0\">\r\n");
@@ -668,7 +761,7 @@
                for (RecordItem recordItem : recordInfo.getRecordList()) {
                    recordXml.append("<Item>\r\n");
                    if (deviceChannel != null) {
                        recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n")
                        recordXml.append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n")
                                .append("<Name>" + recordItem.getName() + "</Name>\r\n")
                                .append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n")
                                .append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n")
@@ -688,12 +781,14 @@
        recordXml.append("</RecordList>\r\n")
                .append("</Response>\r\n");
        logger.info("[国标级联] 发送录像数据通道:{}, 内容: {}", recordInfo.getChannelId(), recordXml);
        // callid
        CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
        Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
        sipSender.transmitRequest(parentPlatform.getDeviceIp(), request);
        sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, eventResult -> {
            logger.info("[国标级联] 发送录像数据通道:{}, 发送成功", recordInfo.getChannelId());
        });
    }
@@ -744,10 +839,10 @@
        }
        logger.info("[向上级发送BYE], {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId());
        String mediaServerId = sendRtpItem.getMediaServerId();
        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
        if (mediaServerItem != null) {
            mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
            zlmrtpServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStream());
            mediaServerService.closeRTPServer(mediaServerItem, sendRtpItem.getStream());
        }
        SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
        if (byeRequest == null) {
@@ -795,8 +890,8 @@
    }
    @Override
    public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem,
                                   SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent,
    public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServer mediaServerItem,
                                   SSRCInfo ssrcInfo, HookSubscribe.Event event, SipSubscribe.Event okEvent,
                                   SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException {
        String stream = ssrcInfo.getStream();
@@ -805,11 +900,11 @@
        }
        logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
        Hook hook = Hook.getInstance(HookType.on_media_arrival, "rtp", stream, mediaServerItem.getId());
        subscribe.addSubscribe(hook, (hookData) -> {
            if (event != null) {
                event.response(mediaServerItemInUse, json);
                subscribe.removeSubscribe(hookSubscribe);
                event.response(hookData);
                subscribe.removeSubscribe(hook);
            }
        });
        String sdpIp = mediaServerItem.getSdpIp();
@@ -849,12 +944,12 @@
        sipSender.transmitRequest(sipLayer.getLocalIp(platform.getDeviceIp()), request, (e -> {
            streamSession.remove(platform.getServerGBId(), channelId, ssrcInfo.getStream());
            mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
            subscribe.removeSubscribe(hookSubscribe);
            subscribe.removeSubscribe(hook);
            errorEvent.response(e);
        }), e -> {
            ResponseEvent responseEvent = (ResponseEvent) e.event;
            SIPResponse response = (SIPResponse) responseEvent.getResponse();
            streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(),  stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.broadcast);
            streamSession.put(platform.getServerGBId(), channelId, callIdHeader.getCallId(),  stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.BROADCAST);
            okEvent.response(e);
        });
    }