diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ApplicationCheckRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/ApplicationCheckRunner.java index faa9ef12..108b434b 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ApplicationCheckRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ApplicationCheckRunner.java @@ -55,7 +55,7 @@ public class ApplicationCheckRunner implements CommandLineRunner { System.exit(1); } - if (mediaIp.equals("localhost") || mediaIp.equals("127.0.0.1")) { + if (mediaIp.equals("localhost") || (mediaIp.equals("127.0.0.1") && mediaWanIp == null)) { logger.warn("mediaIp.ip使用 {} ,将无法收到网络内其他设备的推流!!!", mediaIp ); } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java new file mode 100644 index 00000000..fbe07c7f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java @@ -0,0 +1,33 @@ +package com.genersoft.iot.vmp.conf; + +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 系统启动时控制设备离线 + */ +@Component +@Order(value=4) +public class SipDeviceRunner implements CommandLineRunner { + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Override + public void run(String... args) throws Exception { + // 设置所有设备离线 + storager.outlineForAll(); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java index 35862078..41b68cc0 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.conf; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,10 @@ public class SipPlatformRunner implements CommandLineRunner { @Autowired private EventPublisher publisher; + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + @Override public void run(String... args) throws Exception { // 设置所有平台离线 @@ -36,6 +41,9 @@ public class SipPlatformRunner implements CommandLineRunner { // 清理所有平台注册缓存 redisCatchStorage.cleanPlatformRegisterInfos(); + // 停止所有推流 +// zlmrtpServerFactory.closeAllSendRtpStream(); + List parentPlatforms = storager.queryEnableParentPlatformList(true); for (ParentPlatform parentPlatform : parentPlatforms) { diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java index aa642c6d..c6e77cab 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java @@ -111,7 +111,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { http.headers().contentTypeOptions().disable(); http.authorizeRequests() // 放行接口 - .antMatchers("/api/user/login","/index/hook/**").permitAll() + .antMatchers("/#/**", "/api/user/login","/index/hook/**").permitAll() // 除上面外的所有请求全部需要鉴权认证 .anyRequest().authenticated() // 异常处理(权限拒绝、登录失效等) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java index 13ed98a7..09997365 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java @@ -39,8 +39,8 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa // 获取失效的key String expiredKey = message.toString(); logger.info(expiredKey); - if(!expiredKey.startsWith(VideoManagerConstants.PLATFORM_PREFIX)){ - logger.info("收到redis过期监听,但开头不是"+VideoManagerConstants.PLATFORM_PREFIX+",忽略"); + if(!expiredKey.startsWith(VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX)){ + logger.debug("收到redis过期监听,但开头不是"+VideoManagerConstants.PLATFORM_KEEPLIVEKEY_PREFIX+",忽略"); return; } // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线 @@ -49,7 +49,6 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa publisher.platformKeepaliveExpireEventPublish(platformGBId); }else if (expiredKey.startsWith(VideoManagerConstants.PLATFORM_REGISTER_PREFIX)) { - logger.info("11111111111111"); String platformGBId = expiredKey.substring(VideoManagerConstants.PLATFORM_REGISTER_PREFIX.length(),expiredKey.length()); publisher.platformNotRegisterEventPublish(platformGBId); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java index 27ced6cb..cc871ef0 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java @@ -38,7 +38,7 @@ public class KeepliveTimeoutListener extends KeyExpirationEventMessageListener { // 获取失效的key String expiredKey = message.toString(); if(!expiredKey.startsWith(VideoManagerConstants.KEEPLIVEKEY_PREFIX)){ - logger.info("收到redis过期监听,但开头不是"+VideoManagerConstants.KEEPLIVEKEY_PREFIX+",忽略"); + logger.debug("收到redis过期监听,但开头不是"+VideoManagerConstants.KEEPLIVEKEY_PREFIX+",忽略"); return; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java index 4e2561c7..480ed1d9 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java @@ -63,6 +63,7 @@ public class PlatformKeepaliveExpireEventLister implements ApplicationListener

= 3) { // 有3次未收到心跳回复, 设置平台状态为离线, 开始重新注册 logger.warn("有3次未收到心跳回复,标记设置平台状态为离线, 并重新注册 平台国标ID:" + event.getPlatformGbID()); + storager.updateParentPlatformStatus(event.getPlatformGbID(), false); publisher.platformNotRegisterEventPublish(event.getPlatformGbID()); parentPlatformCatch.setKeepAliveReply(0); }else { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java index b9b0089a..a53583b6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java @@ -1,7 +1,10 @@ package com.genersoft.iot.vmp.gb28181.event.platformNotRegister; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,6 +12,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * @Description: 平台未注册事件,来源有二: * 1、平台新添加 @@ -23,23 +30,53 @@ public class PlatformNotRegisterEventLister implements ApplicationListener sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID()); + logger.info("停止[ {} ]的所有推流size", sendRtpItems.size()); + if (sendRtpItems != null && sendRtpItems.size() > 0) { + logger.info("停止[ {} ]的所有推流", event.getPlatformGbID()); + StringBuilder app = new StringBuilder(); + StringBuilder stream = new StringBuilder(); + for (int i = 0; i < sendRtpItems.size(); i++) { + if (app.length() != 0) { + app.append(","); + } + app.append(sendRtpItems.get(i).getApp()); + if (stream.length() != 0) { + stream.append(","); + } + stream.append(sendRtpItems.get(i).getStreamId()); + redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItems.get(i).getChannelId()); + } + Map param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app", app.toString()); + param.put("stream", stream.toString()); + zlmrtpServerFactory.stopSendRtpStream(param); + + } sipCommanderFroPlatform.register(parentPlatform); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java index 770edf06..b9f3f234 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java @@ -43,7 +43,7 @@ public class CheckForAllRecordsThread extends Thread { if (totalRecordList.size() < this.recordInfo.getSumNum()) { logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + this.recordInfo.getSumNum() + "项"); } else { - logger.info("录像数据已全部获取,共" + this.recordInfo.getSumNum() + "项"); + logger.info("录像数据已全部获取,共 {} 项", this.recordInfo.getSumNum()); this.recordInfo.setRecordList(totalRecordList); for (int i = 0; i < cacheKeys.size(); i++) { redis.del(cacheKeys.get(i).toString()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java index 17104bae..fdb7c0b2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java @@ -58,6 +58,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor { param.put("vhost","__defaultVhost__"); param.put("app",sendRtpItem.getApp()); param.put("stream",streamId); + param.put("ssrc",sendRtpItem.getSsrc()); logger.info("停止向上级推流:" + streamId); zlmrtpServerFactory.stopSendRtpStream(param); redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java index 91b6ecc6..43be89d0 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java @@ -93,6 +93,11 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); // 不是通道可能是直播流 if (channel != null || gbStream != null ) { + if (channel.getStatus() == 0) { + logger.info("通道离线,返回400"); + responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline"); + return; + } responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 }else { logger.info("通道不存在,返回404"); @@ -367,6 +372,12 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { getServerTransaction(evt).sendResponse(response); } + private void responseAck(RequestEvent evt, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException { + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); + response.setReasonPhrase(msg); + getServerTransaction(evt).sendResponse(response); + } + /** * 回复带sdp的200 * @param evt diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java index a21ce59e..c2f624fe 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java @@ -770,14 +770,17 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { try { Element rootElement = getRootElement(evt); String deviceId = XmlUtil.getText(rootElement, "DeviceID"); - // 检查设备是否存在, 不存在则不回复 - if (storager.exists(deviceId)) { + Device device = storager.queryVideoDevice(deviceId); + // 检查设备是否存在并在线, 不存在则不回复 + if (device != null && device.getOnline() == 1) { // 回复200 OK responseAck(evt); if (offLineDetector.isOnline(deviceId)) { publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); } else { } + }else { + logger.warn("收到[ "+deviceId+" ]心跳信息, 但是设备" + (device == null? "不存在":"离线") + ", 心跳信息不予以回复"); } } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { e.printStackTrace(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java index c2884702..7ad18c14 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java @@ -146,7 +146,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { // 注册成功 // 保存到redis // 下发catelog查询目录 - if (registerFlag == 1 && device != null) { + if (registerFlag == 1 ) { logger.info("注册成功! deviceId:" + device.getDeviceId()); // boolean exists = storager.exists(device.getDeviceId()); device.setRegisterTimeMillis(System.currentTimeMillis()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java index d6df26a5..ba3003d8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/RegisterResponseProcessor.java @@ -80,12 +80,13 @@ public class RegisterResponseProcessor implements ISIPResponseProcessor { // 注册/注销成功 logger.info(String.format("%s %s成功", platformGBId, action)); redisCatchStorage.delPlatformRegisterInfo(callId); - parentPlatform.setStatus(true); + parentPlatform.setStatus("注册".equals(action)); // 取回Expires设置,避免注销过程中被置为0 ParentPlatform parentPlatformTmp = storager.queryParentPlatByServerGBId(platformGBId); String expires = parentPlatformTmp.getExpires(); parentPlatform.setExpires(expires); - storager.updateParentPlatform(parentPlatform); + parentPlatform.setId(parentPlatformTmp.getId()); + storager.updateParentPlatformStatus(platformGBId, "注册".equals(action)); redisCatchStorage.updatePlatformRegister(parentPlatform); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java index 3b7428a2..a50b170b 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -1,6 +1,9 @@ package com.genersoft.iot.vmp.media.zlm; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.gb28181.bean.GbStream; @@ -119,4 +122,33 @@ public class ZLMMediaListManager { storager.mediaOutline(app, streamId); } } + + public void clearAllSessions() { + logger.info("清空所有国标相关的session"); + JSONObject allSessionJSON = zlmresTfulUtils.getAllSession(); + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + HashSet allLocalPorts = new HashSet(); + if (allSessionJSON.getInteger("code") == 0) { + JSONArray data = allSessionJSON.getJSONArray("data"); + if (data.size() > 0) { + for (int i = 0; i < data.size(); i++) { + JSONObject sessionJOSN = data.getJSONObject(i); + Integer local_port = sessionJOSN.getInteger("local_port"); + if (!local_port.equals(Integer.valueOf(mediaInfo.getHttpPort())) && + !local_port.equals(Integer.valueOf(mediaInfo.getHttpSSLport())) && + !local_port.equals(Integer.valueOf(mediaInfo.getRtmpPort())) && + !local_port.equals(Integer.valueOf(mediaInfo.getRtspPort())) && + !local_port.equals(Integer.valueOf(mediaInfo.getRtspSSlport())) && + !local_port.equals(Integer.valueOf(mediaInfo.getHookOnFlowReport()))){ + allLocalPorts.add(sessionJOSN.getInteger("local_port") + ""); + } + } + } + } + if (allLocalPorts.size() > 0) { + List result = new ArrayList<>(allLocalPorts); + String localPortSStr = String.join(",", result); + zlmresTfulUtils.kickSessions(localPortSStr); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index 8ff9224d..a864f3ca 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -194,4 +194,14 @@ public class ZLMRESTfulUtils { param.put("force", 1); return sendPost("close_streams",param, null); } + + public JSONObject getAllSession() { + return sendPost("getAllSession",null, null); + } + + public void kickSessions(String localPortSStr) { + Map param = new HashMap<>(); + param.put("local_port", localPortSStr); + sendPost("kick_sessions",param, null); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index ffe91d29..430c6900 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -18,13 +18,13 @@ public class ZLMRTPServerFactory { private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory"); - @Value("${media.rtp.udpPortRange}") - private String udpPortRange; + @Value("${media.rtp.portRange}") + private String portRange; @Autowired private ZLMRESTfulUtils zlmresTfulUtils; - private int[] udpPortRangeArray = new int[2]; + private int[] portRangeArray = new int[2]; private int currentPort = 0; @@ -52,7 +52,7 @@ public class ZLMRTPServerFactory { Map param = new HashMap<>(); int result = -1; - int newPort = getPortFromUdpPortRange(); + int newPort = getPortFromportRange(); param.put("port", newPort); param.put("enable_tcp", 1); param.put("stream_id", streamId); @@ -101,16 +101,16 @@ public class ZLMRTPServerFactory { return result; } - private int getPortFromUdpPortRange() { + private int getPortFromportRange() { if (currentPort == 0) { - String[] udpPortRangeStrArray = udpPortRange.split(","); - udpPortRangeArray[0] = Integer.parseInt(udpPortRangeStrArray[0]); - udpPortRangeArray[1] = Integer.parseInt(udpPortRangeStrArray[1]); + String[] portRangeStrArray = portRange.split(","); + portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]); + portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]); } - if (currentPort == 0 || currentPort++ > udpPortRangeArray[1]) { - currentPort = udpPortRangeArray[0]; - return udpPortRangeArray[0]; + if (currentPort == 0 || currentPort++ > portRangeArray[1]) { + currentPort = portRangeArray[0]; + return portRangeArray[0]; } else { if (currentPort % 2 == 1) { currentPort++; @@ -244,4 +244,8 @@ public class ZLMRTPServerFactory { } return result; } + + public void closeAllSendRtpStream() { + + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index 0e6bfc00..2bbc1bee 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -164,6 +164,10 @@ public class ZLMRunner implements CommandLineRunner { mediaServerConfig.setLocalIP(mediaIp); mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); redisCatchStorage.updateMediaInfo(mediaServerConfig); + + // 清空所有session +// zlmMediaListManager.clearAllSessions(); + // 更新流列表 zlmMediaListManager.updateMediaList(); // 恢复流代理 diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index 8b2c2bf5..978ddc33 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import java.util.List; import java.util.Map; public interface IRedisCatchStorage { @@ -91,6 +92,8 @@ public interface IRedisCatchStorage { */ SendRtpItem querySendRTPServer(String platformGbId, String channelId); + List querySendRTPServer(String platformGbId); + /** * 删除RTP推送信息缓存 * @param platformGbId diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java index 3e001b07..5d838c5d 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -135,6 +135,13 @@ public interface IVideoManagerStorager { */ public boolean outline(String deviceId); + /** + * 更新所有设备离线 + * + * @return true:更新成功 false:更新失败 + */ + public boolean outlineForAll(); + /** * 查询子设备 @@ -352,4 +359,10 @@ public interface IVideoManagerStorager { * @param streamId */ void mediaOutline(String app, String streamId); + + /** + * 设置平台在线/离线 + * @param online + */ + void updateParentPlatformStatus(String platformGbID, boolean online); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java index f6e328bf..bcc33de2 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java @@ -65,4 +65,7 @@ public interface DeviceMapper { @Delete("DELETE FROM device WHERE deviceId=#{deviceId}") int del(String deviceId); + + @Update("UPDATE device SET online=0") + int outlineForAll(); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java index c18c5c31..bb81171b 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java @@ -66,5 +66,8 @@ public interface ParentPlatformMapper { ParentPlatform getParentPlatById(int id); @Update("UPDATE parent_platform SET status=false" ) - void outlineForAllParentPlatform(); + int outlineForAllParentPlatform(); + + @Update("UPDATE parent_platform SET status=#{online} WHERE serverGBId=#{platformGbID}" ) + int updateParentPlatformStatus(String platformGbID, boolean online); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index 98795ef8..74d6779f 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -233,6 +233,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { return (SendRtpItem)redis.get(key); } + @Override + public List querySendRTPServer(String platformGbId) { + String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + platformGbId + "_*"; + List queryResult = redis.scan(key); + List result= new ArrayList<>(); + + for (int i = 0; i < queryResult.size(); i++) { + String keyItem = (String) queryResult.get(i); + result.add((SendRtpItem)redis.get(keyItem)); + } + + return result; + } + /** * 删除RTP推送信息缓存 * @param platformGbId diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index 7e206bf3..cbaa404a 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -256,6 +256,18 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { return deviceMapper.update(device) > 0; } + /** + * 更新所有设备离线 + * + * @return true:更新成功 false:更新失败 + */ + @Override + public synchronized boolean outlineForAll() { + logger.info("更新所有设备离线"); + int result = deviceMapper.outlineForAll(); + return result > 0; + } + /** * 清空通道 * @param deviceId @@ -575,5 +587,8 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { gbStreamMapper.setStatus(app, streamId, false); } - + @Override + public void updateParentPlatformStatus(String platformGbID, boolean online) { + platformMapper.updateParentPlatformStatus(platformGbID, online); + } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index e28925b4..cdab7111 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -78,12 +78,12 @@ media: autoApplyPlay: false # [可选] 部分设备需要扩展SDP,需要打开此设置 seniorSdp: false - # 启用udp多端口模式 + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 rtp: - # [可选] 是否启用udp多端口模式, 开启后会在udpPortRange范围内选择端口用于媒体流传输 + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 enable: true - # [可选] 在此范围内选择端口用于媒体流传输, 不只是udp, 使用TCP被动传输模式时,也是从这个范围内选择端口 - udpPortRange: 30000,30500 # 端口范围 + # [可选] 在此范围内选择端口用于媒体流传输, + portRange: 30000,30500 # 端口范围 # [可选] 日志配置, 一般不需要改 logging: