diff --git a/README.md b/README.md index a64a1c1b..a50c36d8 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git # 非开源的内容 - [X] ONVIF设备的接入,支持点播,云台控制,国标级联点播,自动点播。在[知识星球](https://t.zsxq.com/10WAnH2MP)放了试用安装包以及使用教程,没有使用时间限制,需要源码可以星球私信我或者邮箱联系。 +- [X] 支持国标28181-2022协议,支持巡航轨迹查询,PTZ精准控制,存储卡格式化,设备软件升级,OSD配置,h265+aac,支持辅码流,录像倒放等。具体的功能列表可在[知识星球](https://t.zsxq.com/18GXkpkqs)查看,需要源码和测试可以在星球私信联系或者发邮件给我 # 授权协议 @@ -119,7 +120,7 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git # 技术支持 -[知识星球](https://t.zsxq.com/0d8VAD3Dm)专栏列表: +[知识星球](https://t.zsxq.com/0d8VAD3Dm)专栏列表:, - [使用入门系列一:WVP-PRO能做什么](https://t.zsxq.com/0dLguVoSp) 有偿技术支持,请发送邮件到648540858@qq.com diff --git a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java index 5a451e35..de0e2df5 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.time.Instant; +import java.util.Date; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -59,7 +60,8 @@ public class DynamicTask { } } // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 - future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog); + + future = threadPoolTaskScheduler.scheduleAtFixedRate(task, new Date(System.currentTimeMillis() + cycleForCatalog), cycleForCatalog); if (future != null){ futureMap.put(key, future); runnableMap.put(key, task); diff --git a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java index d58abcb3..32b6fac0 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java @@ -142,13 +142,13 @@ public class DeviceChannel { * 云台类型 */ @Schema(description = "云台类型") - private int PTZType; + private int ptzType; /** * 云台类型描述字符串 */ @Schema(description = "云台类型描述字符串") - private String PTZTypeText; + private String ptzTypeText; /** * 创建时间 @@ -266,23 +266,23 @@ public class DeviceChannel { this.deviceId = deviceId; } - public void setPTZType(int PTZType) { - this.PTZType = PTZType; - switch (PTZType) { + public void setPtzType(int ptzType) { + this.ptzType = ptzType; + switch (ptzType) { case 0: - this.PTZTypeText = "未知"; + this.ptzTypeText = "未知"; break; case 1: - this.PTZTypeText = "球机"; + this.ptzTypeText = "球机"; break; case 2: - this.PTZTypeText = "半球"; + this.ptzTypeText = "半球"; break; case 3: - this.PTZTypeText = "固定枪机"; + this.ptzTypeText = "固定枪机"; break; case 4: - this.PTZTypeText = "遥控枪机"; + this.ptzTypeText = "遥控枪机"; break; } } @@ -447,16 +447,16 @@ public class DeviceChannel { this.password = password; } - public int getPTZType() { - return PTZType; + public int getPtzType() { + return ptzType; } - public String getPTZTypeText() { - return PTZTypeText; + public String getPtzTypeText() { + return ptzTypeText; } - public void setPTZTypeText(String PTZTypeText) { - this.PTZTypeText = PTZTypeText; + public void setPtzTypeText(String ptzTypeText) { + this.ptzTypeText = ptzTypeText; } public boolean isStatus() { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java index e7b7ab80..6557bbaa 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java @@ -103,6 +103,16 @@ public class SubscribeHolder { return platforms; } + public List getAllMobilePositionSubscribePlatform() { + List platforms = new ArrayList<>(); + if(!mobilePositionMap.isEmpty()) { + for (String key : mobilePositionMap.keySet()) { + platforms.add(mobilePositionMap.get(key).getId()); + } + } + return platforms; + } + public void removeAllSubscribe(String platformId) { removeMobilePositionSubscribe(platformId); removeCatalogSubscribe(platformId); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java index d56e744d..c0b66fed 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; +import com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition.MobilePositionEvent; import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent; import org.springframework.beans.factory.annotation.Autowired; @@ -94,6 +95,13 @@ public class EventPublisher { } + public void mobilePositionEventPublish(MobilePosition mobilePosition) { + MobilePositionEvent event = new MobilePositionEvent(this); + event.setMobilePosition(mobilePosition); + applicationEventPublisher.publishEvent(event); + } + + public void catalogEventPublishForStream(String platformId, List gbStreams, String type) { CatalogEvent outEvent = new CatalogEvent(this); outEvent.setGbStreams(gbStreams); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/mobilePosition/MobilePositionEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/mobilePosition/MobilePositionEvent.java new file mode 100755 index 00000000..06866517 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/mobilePosition/MobilePositionEvent.java @@ -0,0 +1,20 @@ +package com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition; + +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; +import org.springframework.context.ApplicationEvent; + +public class MobilePositionEvent extends ApplicationEvent { + public MobilePositionEvent(Object source) { + super(source); + } + + private MobilePosition mobilePosition; + + public MobilePosition getMobilePosition() { + return mobilePosition; + } + + public void setMobilePosition(MobilePosition mobilePosition) { + this.mobilePosition = mobilePosition; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/mobilePosition/MobilePositionEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/mobilePosition/MobilePositionEventLister.java new file mode 100755 index 00000000..7a96116b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/mobilePosition/MobilePositionEventLister.java @@ -0,0 +1,61 @@ +package com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition; + +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; +import java.util.List; + +/** + * 移动位置通知消息转发 + */ +@Component +public class MobilePositionEventLister implements ApplicationListener { + + private final static Logger logger = LoggerFactory.getLogger(MobilePositionEventLister.class); + + @Autowired + private IVideoManagerStorage storager; + + @Autowired + private SIPCommanderFroPlatform sipCommanderFroPlatform; + + @Autowired + private SubscribeHolder subscribeHolder; + + @Override + public void onApplicationEvent(MobilePositionEvent event) { + // 获取所用订阅 + List platforms = subscribeHolder.getAllMobilePositionSubscribePlatform(); + if (platforms.isEmpty()) { + return; + } + List parentPlatformsForGB = storager.queryPlatFormListForGBWithGBId(event.getMobilePosition().getChannelId(), platforms); + + for (ParentPlatform platform : parentPlatformsForGB) { + logger.info("[向上级发送MobilePosition] 通道:{},平台:{}, 位置: {}:{}", event.getMobilePosition().getChannelId(), + platform.getServerGBId(), event.getMobilePosition().getLongitude(), event.getMobilePosition().getLatitude()); + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()); + try { + sipCommanderFroPlatform.sendNotifyMobilePosition(platform, GPSMsgInfo.getInstance(event.getMobilePosition()), + subscribe); + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException | + IllegalAccessException e) { + logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); + } + } + + } +} + \ No newline at end of file diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java index 24d4ef32..cb2caeca 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -50,7 +50,7 @@ public class VideoStreamSessionManager { ssrcTransaction.setType(type); redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() - + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); + + ":" + deviceId + ":" + channelId + ":" + callId + ":" + stream, ssrcTransaction); } public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){ @@ -67,7 +67,7 @@ public class VideoStreamSessionManager { if (ObjectUtils.isEmpty(stream)) { stream ="*"; } - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + ":" + deviceId + ":" + channelId + ":" + callId+ ":" + stream; List scanResult = RedisUtil.scan(redisTemplate, key); if (scanResult.size() == 0) { return null; @@ -80,12 +80,12 @@ public class VideoStreamSessionManager { if (ObjectUtils.isEmpty(callId)) { return null; } - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_" + callId+ "_*"; + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + ":*:*:" + callId+ ":*"; List scanResult = RedisUtil.scan(redisTemplate, key); if (!scanResult.isEmpty()) { return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0)); }else { - key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_play_*"; + key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + ":*:*:play:*"; scanResult = RedisUtil.scan(redisTemplate, key); if (scanResult.isEmpty()) { return null; @@ -115,7 +115,7 @@ public class VideoStreamSessionManager { if (ObjectUtils.isEmpty(stream)) { stream ="*"; } - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + ":" + deviceId + ":" + channelId + ":" + callId+ ":" + stream; List scanResult = RedisUtil.scan(redisTemplate, key); if (scanResult.size() == 0) { return null; @@ -149,8 +149,8 @@ public class VideoStreamSessionManager { return; } for (SsrcTransaction ssrcTransaction : ssrcTransactionList) { - redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" - + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream()); + redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + ":" + + deviceId + ":" + channelId + ":" + ssrcTransaction.getCallId() + ":" + ssrcTransaction.getStream()); } } @@ -159,8 +159,8 @@ public class VideoStreamSessionManager { if (ssrcTransaction == null ) { return; } - redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" - + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream()); + redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + ":" + + deviceId + ":" + channelId + ":" + ssrcTransaction.getCallId() + ":" + ssrcTransaction.getStream()); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index d48e3a8b..66589a8c 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -220,13 +220,8 @@ public interface ISIPCommander { /** * 看守位控制命令 * - * @param device 视频设备 - * @param channelId 通道id,非通道则是设备本身 - * @param enabled 看守位使能:1 = 开启,0 = 关闭 - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 */ - void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + void homePositionCmd(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; /** * 设备配置命令 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 723c715f..3a5f812b 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -880,7 +880,7 @@ public class SIPCommander implements ISIPCommander { * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 */ @Override - public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { + public void homePositionCmd(Device device, String channelId, Boolean enabled, Integer resetTime, Integer presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { StringBuffer cmdXml = new StringBuffer(200); String charset = device.getCharset(); @@ -894,18 +894,10 @@ public class SIPCommander implements ISIPCommander { cmdXml.append("" + channelId + "\r\n"); } cmdXml.append("\r\n"); - if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) { + if (enabled) { cmdXml.append("1\r\n"); - if (NumericUtil.isInteger(resetTime)) { - cmdXml.append("" + resetTime + "\r\n"); - } else { - cmdXml.append("0\r\n"); - } - if (NumericUtil.isInteger(presetIndex)) { - cmdXml.append("" + presetIndex + "\r\n"); - } else { - cmdXml.append("0\r\n"); - } + cmdXml.append("" + resetTime + "\r\n"); + cmdXml.append("" + presetIndex + "\r\n"); } else { cmdXml.append("0\r\n"); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java index abd32fba..29646546 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java @@ -358,8 +358,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { }else { catalogXml.append("\r\n"); } - if (!ObjectUtils.isEmpty(channel.getPTZType())) { - catalogXml.append("" + channel.getPTZType() + "\r\n"); + if (!ObjectUtils.isEmpty(channel.getPtzType())) { + catalogXml.append("" + channel.getPtzType() + "\r\n"); }else { catalogXml.append("\r\n"); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java index f66e3c38..ff7427bc 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java @@ -15,8 +15,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; +import com.genersoft.iot.vmp.service.bean.RequestStopPushStreamMsg; +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import gov.nist.javax.sip.message.SIPRequest; @@ -92,6 +95,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @Autowired private UserSetting userSetting; + @Autowired + private IStreamPushService pushService; + + @Autowired + private RedisGbPlayMsgListener redisGbPlayMsgListener; + @Override public void afterPropertiesSet() throws Exception { // 添加消息处理的订阅 @@ -115,7 +124,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In // 收流端发送的停止 if (sendRtpItem != null){ - logger.info("[收到bye] 来自{},停止通道:{}, 类型: {}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getPlayType()); + logger.info("[收到bye] 来自{},停止通道:{}, 类型: {}, callId: {}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getPlayType(), callIdHeader.getCallId()); String streamId = sendRtpItem.getStream(); Map param = new HashMap<>(); @@ -123,59 +132,82 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In param.put("app",sendRtpItem.getApp()); param.put("stream",streamId); param.put("ssrc",sendRtpItem.getSsrc()); - logger.info("[收到bye] 停止推流:{}", streamId); - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), - callIdHeader.getCallId(), null); - zlmServerFactory.stopSendRtpStream(mediaInfo, param); - if (userSetting.getUseCustomSsrcForParentInvite()) { - mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc()); - } + logger.info("[收到bye] 停止推流:{}, 媒体节点: {}", streamId, sendRtpItem.getMediaServerId()); + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { - ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); - if (platform != null) { - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, - sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), - sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); - messageForPushChannel.setPlatFormIndex(platform.getId()); - redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); + // 查询这路流是否是本平台的 + StreamPushItem push = pushService.getPush(sendRtpItem.getApp(), sendRtpItem.getStream()); + if (push!= null && !push.isSelf()) { + // 不是本平台的就发送redis消息让其他wvp停止发流 + ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); + if (platform != null) { + RequestStopPushStreamMsg streamMsg = RequestStopPushStreamMsg.getInstance(sendRtpItem, platform.getName(), platform.getId()); + redisGbPlayMsgListener.sendMsgForStopSendRtpStream(sendRtpItem.getServerId(), streamMsg); + } }else { - logger.info("[上级平台停止观看] 未找到平台{}的信息,发送redis消息失败", sendRtpItem.getPlatformId()); + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), + callIdHeader.getCallId(), null); + zlmServerFactory.stopSendRtpStream(mediaInfo, param); + if (userSetting.getUseCustomSsrcForParentInvite()) { + mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc()); + } + + ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); + if (platform != null) { + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), + sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); + messageForPushChannel.setPlatFormIndex(platform.getId()); + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); + }else { + logger.info("[上级平台停止观看] 未找到平台{}的信息,发送redis消息失败", sendRtpItem.getPlatformId()); + } + } + }else { + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), + callIdHeader.getCallId(), null); + zlmServerFactory.stopSendRtpStream(mediaInfo, param); + if (userSetting.getUseCustomSsrcForParentInvite()) { + mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc()); } } + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + if (mediaInfo != null) { + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) { + // 来自上级平台的停止对讲 + logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + } - AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) { - // 来自上级平台的停止对讲 - logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - } - - int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); - if (totalReaderCount <= 0) { - logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { - Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); - if (device == null) { - logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId); - } - try { - logger.info("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null); - } catch (InvalidArgumentException | ParseException | SipException | - SsrcTransactionNotFoundException e) { - logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); + int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); + if (totalReaderCount <= 0) { + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { + Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); + if (device == null) { + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId); + } + try { + logger.info("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null); + } catch (InvalidArgumentException | ParseException | SipException | + SsrcTransactionNotFoundException e) { + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); + } } } } } - // 可能是设备发送的停止 - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId()); - if (ssrcTransaction == null) { - return; - } - logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); + // 可能是设备发送的停止 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId()); + if (ssrcTransaction == null) { + return; + } + logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); ParentPlatform platform = platformService.queryPlatformByServerGBId(ssrcTransaction.getDeviceId()); if (platform != null ) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index 80844353..3205498f 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -498,6 +498,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements String endTimeStr = DateUtil.urlFormatter.format(end); String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr; SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false, false, device.getStreamModeForParam()); + sendRtpItem.setStream(stream); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), @@ -1006,7 +1007,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements Media media = mediaDescription.getMedia(); Vector mediaFormats = media.getMediaFormats(false); - if (mediaFormats.contains("8")) { +// if (mediaFormats.contains("8")) { port = media.getMediaPort(); String protocol = media.getProtocol(); // 区分TCP发流还是udp, 当前默认udp @@ -1022,7 +1023,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } } break; - } +// } } if (port == -1) { logger.info("不支持的媒体格式,返回415"); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java index 435f35f4..e54aa2df 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java @@ -1,7 +1,5 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.conf.CivilCodeFileConf; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; @@ -78,9 +76,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @Autowired private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor; - @Autowired - private CivilCodeFileConf civilCodeFileConf; - private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @@ -98,7 +93,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @Override public void process(RequestEvent evt) { try { - if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) { responseAck((SIPRequest) evt.getRequest(), Response.BUSY_HERE, null, null); logger.error("[notify] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue()); @@ -234,25 +228,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); - } + deviceChannelService.updateChannelGPS(device, deviceChannel, mobilePosition); - storager.updateChannelPosition(deviceChannel); - // 向关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息 - - - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); - jsonObject.put("serial", deviceId); - jsonObject.put("code", channelId); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); } catch (DocumentException e) { logger.error("未处理的异常 ", e); } @@ -340,25 +317,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); - } - - storager.updateChannelPosition(deviceChannel); - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); - jsonObject.put("serial", deviceChannel.getDeviceId()); - jsonObject.put("code", deviceChannel.getChannelId()); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); - + deviceChannelService.updateChannelGPS(device, deviceChannel, mobilePosition); } - // TODO: 需要实现存储报警信息、报警分类 // 回复200 OK if (redisCatchStorage.deviceIsOnline(deviceId)) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java index b2dd76b5..23adac13 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java @@ -248,7 +248,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class); //获取整个消息主体,我们只需要修改请求头即可 HomePositionRequest.HomePosition info = homePosition.getHomePosition(); - cmder.homePositionCmd(device, channelId, info.getEnabled(), info.getResetTime(), info.getPresetIndex(), + cmder.homePositionCmd(device, channelId, !"0".equals(info.getEnabled()), Integer.parseInt(info.getResetTime()), Integer.parseInt(info.getPresetIndex()), errorResult -> onError(request, errorResult), okResult -> onOk(request, okResult)); } catch (Exception e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java index 2fc7ae0e..ec4a3993 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java @@ -75,6 +75,9 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @Autowired private ThreadPoolTaskExecutor taskExecutor; + @Autowired + private EventPublisher eventPublisher; + @Override public void afterPropertiesSet() throws Exception { @@ -158,22 +161,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); - } - storager.updateChannelPosition(deviceChannel); - - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); - jsonObject.put("serial", deviceChannel.getDeviceId()); - jsonObject.put("code", deviceChannel.getChannelId()); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); + deviceChannelService.updateChannelGPS(device, deviceChannel, mobilePosition); } } if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java index 9a82b8ab..bc588c95 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java @@ -1,8 +1,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; -import com.alibaba.fastjson2.JSONObject; 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.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; @@ -57,6 +57,9 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen @Autowired private IDeviceChannelService deviceChannelService; + @Autowired + private EventPublisher eventPublisher; + private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @@ -137,22 +140,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); - } - storager.updateChannelPosition(deviceChannel); - - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); - jsonObject.put("serial", deviceChannel.getDeviceId()); - jsonObject.put("code", deviceChannel.getChannelId()); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); + deviceChannelService.updateChannelGPS(device, deviceChannel, mobilePosition); } catch (DocumentException e) { logger.error("未处理的异常 ", e); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java index 36a72bcd..5c3d6d66 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; -import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; @@ -131,11 +130,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); - if (userSetting.getSavePositionHistory()) { - storager.insertMobilePosition(mobilePosition); - } - - storager.updateChannelPosition(deviceChannel); + deviceChannelService.updateChannelGPS(device, deviceChannel, mobilePosition); String key = DeferredResultHolder.CALLBACK_CMD_MOBILE_POSITION + device.getDeviceId(); RequestMessage msg = new RequestMessage(); @@ -143,17 +138,6 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar msg.setData(mobilePosition); resultHolder.invokeAllResult(msg); - // 发送redis消息。 通知位置信息的变化 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); - jsonObject.put("serial", deviceChannel.getDeviceId()); - jsonObject.put("code", deviceChannel.getChannelId()); - jsonObject.put("longitude", mobilePosition.getLongitude()); - jsonObject.put("latitude", mobilePosition.getLatitude()); - jsonObject.put("altitude", mobilePosition.getAltitude()); - jsonObject.put("direction", mobilePosition.getDirection()); - jsonObject.put("speed", mobilePosition.getSpeed()); - redisCatchStorage.sendMobilePositionMsg(jsonObject); //回复 200 OK try { responseAck(request, Response.OK); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index 9de1ef2b..70702bb6 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -568,14 +568,14 @@ public class XmlUtil { String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType"); if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){ try { - deviceChannel.setPTZType(Integer.parseInt(ptzTypeFromInfo)); + deviceChannel.setPtzType(Integer.parseInt(ptzTypeFromInfo)); }catch (NumberFormatException e){ logger.warn("[xml解析] 从通道数据info中获取PTZType失败: {}", ptzTypeFromInfo); } } } else { try { - deviceChannel.setPTZType(Integer.parseInt(ptzType)); + deviceChannel.setPtzType(Integer.parseInt(ptzType)); }catch (NumberFormatException e){ logger.warn("[xml解析] 从通道数据中获取PTZType失败: {}", ptzType); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 72df8a05..5feb306b 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -72,9 +72,6 @@ public class ZLMHttpHookListener { @Autowired private AudioBroadcastManager audioBroadcastManager; - @Autowired - private ZLMServerFactory zlmServerFactory; - @Autowired private IPlayService playService; @@ -123,9 +120,6 @@ public class ZLMHttpHookListener { @Autowired private VideoStreamSessionManager sessionManager; - @Autowired - private AssistRESTfulUtils assistRESTfulUtils; - @Autowired private SSRCFactory ssrcFactory; @@ -147,7 +141,7 @@ public class ZLMHttpHookListener { taskExecutor.execute(() -> { List subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); - if (subscribes != null && subscribes.size() > 0) { + if (subscribes != null && !subscribes.isEmpty()) { for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { subscribe.response(null, param); } @@ -166,7 +160,7 @@ public class ZLMHttpHookListener { @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") public HookResult onPlay(@RequestBody OnPlayHookParam param) { if (logger.isDebugEnabled()) { - logger.debug("[ZLM HOOK] 播放鉴权:{}->{}" + param.getMediaServerId(), param); + logger.debug("[ZLM HOOK] 播放鉴权:{}->{}", param.getMediaServerId(), param); } String mediaServerId = param.getMediaServerId(); @@ -252,11 +246,7 @@ public class ZLMHttpHookListener { taskExecutor.execute(() -> { ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); if (subscribe != null) { - if (mediaInfo != null) { - subscribe.response(mediaInfo, param); - } else { - new HookResultForOnPublish(1, "zlm not register"); - } + subscribe.response(mediaInfo, param); } }); @@ -579,9 +569,9 @@ public class ZLMHttpHookListener { } // 收到无人观看说明流也没有在往上级推送 if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { - List sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( + List sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId( inviteInfo.getChannelId()); - if (sendRtpItems.size() > 0) { + if (!sendRtpItems.isEmpty()) { for (SendRtpItem sendRtpItem : sendRtpItems) { ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); try { @@ -798,7 +788,7 @@ public class ZLMHttpHookListener { logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId()); taskExecutor.execute(() -> { List subscribes = this.subscribe.getSubscribes(HookType.on_server_started); - if (subscribes != null && subscribes.size() > 0) { + if (subscribes != null && !subscribes.isEmpty()) { for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { subscribe.response(null, zlmServerConfig); } @@ -847,12 +837,11 @@ public class ZLMHttpHookListener { */ @ResponseBody @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8") - public HookResult onRtpServerTimeout(HttpServletRequest request, @RequestBody OnRtpServerTimeoutHookParam + public HookResult onRtpServerTimeout(@RequestBody OnRtpServerTimeoutHookParam param) { logger.info("[ZLM HOOK] rtpServer收流超时:{}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc()); taskExecutor.execute(() -> { - JSONObject json = (JSONObject) JSON.toJSON(param); List subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout); if (subscribes != null && !subscribes.isEmpty()) { for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java index 24222069..027e990e 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java @@ -289,6 +289,10 @@ public class ZLMServerFactory { * 调用zlm RESTful API —— stopSendRtp */ public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Mapparam) { + if (mediaServerItem == null) { + logger.error("[停止RTP推流] 失败: 媒体节点为NULL"); + return false; + } Boolean result = false; JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); if (jsonObject == null) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java index 5a208415..c690f11b 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; @@ -92,4 +93,9 @@ public interface IDeviceChannelService { * 修改通道的码流类型 */ void updateChannelStreamIdentification(DeviceChannel channel); + + List queryChaneListByDeviceId(String deviceId); + + void updateChannelGPS(Device device, DeviceChannel deviceChannel, MobilePosition mobilePosition); + } diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java b/src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java index b814c18f..3b84420f 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java @@ -1,5 +1,8 @@ package com.genersoft.iot.vmp.service.bean; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; +import com.genersoft.iot.vmp.utils.DateUtil; + public class GPSMsgInfo { /** @@ -39,6 +42,18 @@ public class GPSMsgInfo { private boolean stored; + public static GPSMsgInfo getInstance(MobilePosition mobilePosition) { + GPSMsgInfo gpsMsgInfo = new GPSMsgInfo(); + gpsMsgInfo.setId(mobilePosition.getChannelId()); + gpsMsgInfo.setAltitude(mobilePosition.getAltitude() + ""); + gpsMsgInfo.setLng(mobilePosition.getLongitude()); + gpsMsgInfo.setLat(mobilePosition.getLatitude()); + gpsMsgInfo.setSpeed(mobilePosition.getSpeed()); + gpsMsgInfo.setDirection(mobilePosition.getDirection() + ""); + gpsMsgInfo.setTime(DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); + return gpsMsgInfo; + } + public String getId() { return id; diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/RequestStopPushStreamMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestStopPushStreamMsg.java new file mode 100755 index 00000000..fcba5111 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestStopPushStreamMsg.java @@ -0,0 +1,49 @@ +package com.genersoft.iot.vmp.service.bean; + +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; + + +public class RequestStopPushStreamMsg { + + + private SendRtpItem sendRtpItem; + + + private String platformName; + + + private int platFormIndex; + + public SendRtpItem getSendRtpItem() { + return sendRtpItem; + } + + public void setSendRtpItem(SendRtpItem sendRtpItem) { + this.sendRtpItem = sendRtpItem; + } + + public String getPlatformName() { + return platformName; + } + + public void setPlatformName(String platformName) { + this.platformName = platformName; + } + + + public int getPlatFormIndex() { + return platFormIndex; + } + + public void setPlatFormIndex(int platFormIndex) { + this.platFormIndex = platFormIndex; + } + + public static RequestStopPushStreamMsg getInstance(SendRtpItem sendRtpItem, String platformName, int platFormIndex) { + RequestStopPushStreamMsg streamMsg = new RequestStopPushStreamMsg(); + streamMsg.setSendRtpItem(sendRtpItem); + streamMsg.setPlatformName(platformName); + streamMsg.setPlatFormIndex(platFormIndex); + return streamMsg; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java index cb118865..e9ee4cba 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java @@ -6,7 +6,17 @@ package com.genersoft.iot.vmp.service.bean; public class WvpRedisMsgCmd { + /** + * 请求获取推流信息 + */ public static final String GET_SEND_ITEM = "GetSendItem"; + /** + * 请求推流的请求 + */ public static final String REQUEST_PUSH_STREAM = "RequestPushStream"; + /** + * 停止推流的请求 + */ + public static final String REQUEST_STOP_PUSH_STREAM = "RequestStopPushStream"; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java index 55fa5e9a..632be91e 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java @@ -1,16 +1,21 @@ package com.genersoft.iot.vmp.service.impl; +import com.alibaba.fastjson2.JSONObject; import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.InviteInfo; import com.genersoft.iot.vmp.common.InviteSessionType; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; import com.genersoft.iot.vmp.service.IDeviceChannelService; import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceMapper; +import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; @@ -35,7 +40,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { private final static Logger logger = LoggerFactory.getLogger(DeviceChannelServiceImpl.class); @Autowired - private IRedisCatchStorage redisCatchStorage; + private EventPublisher eventPublisher; @Autowired private IInviteStreamService inviteStreamService; @@ -46,6 +51,15 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { @Autowired private DeviceMapper deviceMapper; + @Autowired + private DeviceMobilePositionMapper deviceMobilePositionMapper; + + @Autowired + private UserSetting userSetting; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + @Override public DeviceChannel updateGps(DeviceChannel deviceChannel, Device device) { if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) { @@ -84,7 +98,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { public void updateChannel(String deviceId, DeviceChannel channel) { String channelId = channel.getChannelId(); channel.setDeviceId(deviceId); -// StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { channel.setStreamId(inviteInfo.getStreamInfo().getStream()); @@ -280,4 +293,64 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { } channelMapper.updateChannelStreamIdentification(channel); } + + @Override + public List queryChaneListByDeviceId(String deviceId) { + return channelMapper.queryAllChannels(deviceId); + } + + @Override + public void updateChannelGPS(Device device, DeviceChannel deviceChannel, MobilePosition mobilePosition) { + if (userSetting.getSavePositionHistory()) { + deviceMobilePositionMapper.insertNewPosition(mobilePosition); + } + + if (deviceChannel.getChannelId().equals(deviceChannel.getDeviceId())) { + deviceChannel.setChannelId(null); + } + if (deviceChannel.getGpsTime() == null) { + deviceChannel.setGpsTime(DateUtil.getNow()); + } + + int updated = channelMapper.updatePosition(deviceChannel); + if (updated == 0) { + return; + } + + List deviceChannels = new ArrayList<>(); + if (deviceChannel.getChannelId() == null) { + // 有的设备这里上报的deviceId与通道Id是一样,这种情况更新设备下的全部通道 + List deviceChannelsInDb = queryChaneListByDeviceId(device.getDeviceId()); + deviceChannels.addAll(deviceChannelsInDb); + }else { + deviceChannels.add(deviceChannel); + } + if (deviceChannels.isEmpty()) { + return; + } + if (deviceChannels.size() > 100) { + logger.warn("[更新通道位置信息后发送通知] 设备可能是平台,上报的位置信息未标明通道编号," + + "导致所有通道被更新位置, deviceId:{}", device.getDeviceId()); + } + for (DeviceChannel channel : deviceChannels) { + // 向关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息 + mobilePosition.setChannelId(channel.getChannelId()); + try { + eventPublisher.mobilePositionEventPublish(mobilePosition); + }catch (Exception e) { + logger.error("[向上级转发移动位置失败] ", e); + } + // 发送redis消息。 通知位置信息的变化 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime())); + jsonObject.put("serial", mobilePosition.getDeviceId()); + jsonObject.put("code", mobilePosition.getChannelId()); + jsonObject.put("longitude", mobilePosition.getLongitude()); + jsonObject.put("latitude", mobilePosition.getLatitude()); + jsonObject.put("altitude", mobilePosition.getAltitude()); + jsonObject.put("direction", mobilePosition.getDirection()); + jsonObject.put("speed", mobilePosition.getSpeed()); + redisCatchStorage.sendMobilePositionMsg(jsonObject); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java index 1dc7db44..2c2674fd 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -269,6 +269,8 @@ public class DeviceServiceImpl implements IDeviceService { int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30); // 设置最小值为30 dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000); + + catalogSubscribeTask.run(); return true; } @@ -302,6 +304,7 @@ public class DeviceServiceImpl implements IDeviceService { int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30); // 刷新订阅 dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog * 1000); + mobilePositionSubscribeTask.run(); return true; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index 0df0d4d0..c8d203f4 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -1409,6 +1409,14 @@ public class PlayServiceImpl implements IPlayService { logger.info("调用ZLM推流接口, 结果: {}", jsonObject); logger.info("RTP推流成功[ {}/{} ],{}->{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), sendRtpItem.isTcpActive()?"被动发流": param.get("dst_url") + ":" + param.get("dst_port")); + if (sendRtpItem.getPlayType() == InviteStreamType.PUSH && correlationInfo instanceof ParentPlatform) { + ParentPlatform platform = (ParentPlatform)correlationInfo; + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, sendRtpItem.getApp(), sendRtpItem.getStream(), + sendRtpItem.getChannelId(), platform.getServerGBId(), platform.getName(), userSetting.getServerId(), + sendRtpItem.getMediaServerId()); + messageForPushChannel.setPlatFormIndex(platform.getId()); + redisCatchStorage.sendPlatformStartPlayMsg(messageForPushChannel); + } } else { logger.error("RTP推流失败: {}, 参数:{}", jsonObject.getString("msg"), JSONObject.toJSONString(param)); if (sendRtpItem.isOnlyAudio()) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java index eb261e34..3b990f00 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -133,7 +133,10 @@ public class RedisGbPlayMsgListener implements MessageListener { case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: RequestPushStreamMsg param = JSON.to(RequestPushStreamMsg.class, wvpRedisMsg.getContent()); requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); - + break; + case WvpRedisMsgCmd.REQUEST_STOP_PUSH_STREAM: + RequestStopPushStreamMsg streamMsg = JSON.to(RequestStopPushStreamMsg.class, wvpRedisMsg.getContent()); + requestStopPushStreamMsgHand(streamMsg, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); break; default: break; @@ -397,6 +400,19 @@ public class RedisGbPlayMsgListener implements MessageListener { redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); } + /** + * 发送请求推流的消息 + */ + public void sendMsgForStopSendRtpStream(String serverId, RequestStopPushStreamMsg streamMsg) { + String key = UUID.randomUUID().toString(); + WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, + WvpRedisMsgCmd.REQUEST_STOP_PUSH_STREAM, key, JSON.toJSONString(streamMsg)); + + JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg); + logger.info("[REDIS 请求其他平台停止推流] {}: {}", serverId, jsonObject); + redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); + } + private SendRtpItem querySendRTPServer(String platformGbId, String channelId, String streamId, String callId) { if (platformGbId == null) { platformGbId = "*"; @@ -423,4 +439,36 @@ public class RedisGbPlayMsgListener implements MessageListener { return null; } } + + /** + * 处理收到的请求推流的请求 + */ + private void requestStopPushStreamMsgHand(RequestStopPushStreamMsg streamMsg, String fromId, String serial) { + SendRtpItem sendRtpItem = streamMsg.getSendRtpItem(); + if (sendRtpItem == null) { + logger.info("[REDIS 执行其他平台的请求停止推流] 失败: sendRtpItem为NULL"); + return; + } + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + if (mediaInfo == null) { + // TODO 回复错误 + return; + } + Map param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",sendRtpItem.getApp()); + param.put("stream",sendRtpItem.getStream()); + param.put("ssrc", sendRtpItem.getSsrc()); + + if (zlmServerFactory.stopSendRtpStream(mediaInfo, param)) { + logger.info("[REDIS 执行其他平台的请求停止推流] 成功: {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream()); + // 发送redis消息 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), + sendRtpItem.getPlatformId(), streamMsg.getPlatformName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); + messageForPushChannel.setPlatFormIndex(streamMsg.getPlatFormIndex()); + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); + } + + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java index 1d7c2fd5..fe0ccd2a 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java @@ -73,7 +73,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { MessageForPushChannel pushChannel = JSON.parseObject(message.getBody(), MessageForPushChannel.class); StreamPushItem push = streamPushService.getPush(pushChannel.getApp(), pushChannel.getStream()); if (push != null) { - List sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( + List sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId( push.getGbId()); if (!sendRtpItems.isEmpty()) { for (SendRtpItem sendRtpItem : sendRtpItems) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java index 65239c8f..dc342b02 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java @@ -88,7 +88,8 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { streamPushItemForSave.add(streamPushItem); allGBId.put(streamPushItem.getGbId(), streamPushItem); } else { - if (allGBId.containsKey(streamPushItem.getGbId())) { + if (allGBId.containsKey(streamPushItem.getGbId()) + && (!allGBId.get(streamPushItem.getGbId()).getApp().equals(streamPushItem.getApp()) || !allGBId.get(streamPushItem.getGbId()).getStream().equals(streamPushItem.getStream()))) { GbStream gbStream = allGBId.get(streamPushItem.getGbId()); logger.warn("[REDIS消息-推流设备列表更新-UPDATE] 国标编号重复: {}, 已分配给{}/{}", streamPushItem.getGbId(), gbStream.getApp(), gbStream.getStream()); 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 b663c5c6..78fd2801 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -181,7 +181,7 @@ public interface IRedisCatchStorage { */ void sendStreamPushRequestedMsgForStatus(); - List querySendRTPServerByChnnelId(String channelId); + List querySendRTPServerByChannelId(String channelId); List querySendRTPServerByStream(String stream); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java index e823c6e0..c03d73a2 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -23,7 +23,7 @@ public interface DeviceChannelMapper { "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}, " + + "#{ipAddress}, #{port}, #{password}, #{ptzType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " + "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime}, #{streamIdentification})") int add(DeviceChannel channel); @@ -48,7 +48,7 @@ public interface DeviceChannelMapper { ", ip_address=#{ipAddress}" + ", port=#{port}" + ", password=#{password}" + - ", custom_ptz_type=#{PTZType}" + + ", custom_ptz_type=#{ptzType}" + ", status=#{status}" + ", stream_id=#{streamId}" + ", has_audio=#{hasAudio}" + @@ -250,7 +250,7 @@ public interface DeviceChannelMapper { "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + - "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + + "#{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.streamIdentification}) " + @@ -271,7 +271,7 @@ public interface DeviceChannelMapper { "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + - "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + + "#{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}) " + @@ -339,7 +339,7 @@ public interface DeviceChannelMapper { ", ip_address=#{item.ipAddress}" + ", port=#{item.port}" + ", password=#{item.password}" + - ", ptz_type=#{item.PTZType}" + + ", ptz_type=#{item.ptzType}" + ", status=#{item.status}" + ", stream_id=#{item.streamId}" + ", has_audio=#{item.hasAudio}" + @@ -395,7 +395,7 @@ public interface DeviceChannelMapper { "WHERE device_id=#{deviceId} " + " AND channel_id=#{channelId}" + " "}) - void updatePosition(DeviceChannel deviceChannel); + int updatePosition(DeviceChannel deviceChannel); @Select("SELECT * FROM wvp_device_channel WHERE length(trim(stream_id)) > 0") List getAllChannelInPlay(); 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 42d2b7ae..f41bf725 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java @@ -269,7 +269,7 @@ public interface DeviceMapper { "charset,"+ "ssrc_check,"+ "as_message_channel,"+ - "broadcastPushAfterAck,"+ + "broadcast_push_after_ack,"+ "geo_coord_sys,"+ "on_line,"+ "media_server_id"+ 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 27bbdba6..18a037dd 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -184,7 +184,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { } @Override - public List querySendRTPServerByChnnelId(String channelId) { + public List querySendRTPServerByChannelId(String channelId) { if (channelId == null) { return null; } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java index 85f516a3..2f5a5894 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import io.swagger.v3.oas.annotations.Operation; @@ -45,7 +45,7 @@ public class DeviceControl { private IVideoManagerStorage storager; @Autowired - private SIPCommander cmder; + private ISIPCommander cmder; @Autowired private DeferredResultHolder resultHolder; @@ -254,15 +254,13 @@ public class DeviceControl { @Operation(summary = "看守位控制", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) - @Parameter(name = "enabled", description = "是否开启看守位 1:开启,0:关闭", required = true) + @Parameter(name = "enabled", description = "是否开启看守位", required = true) @Parameter(name = "presetIndex", description = "调用预置位编号") - @Parameter(name = "resetTime", description = "自动归位时间间隔") - @GetMapping("/home_position/{deviceId}/{enabled}") - public DeferredResult homePositionApi(@PathVariable String deviceId, - @PathVariable String enabled, - @RequestParam(required = false) String resetTime, - @RequestParam(required = false) String presetIndex, - String channelId) { + @Parameter(name = "resetTime", description = "自动归位时间间隔 单位:秒") + @GetMapping("/home_position") + public DeferredResult homePositionApi(String deviceId, String channelId, Boolean enabled, + @RequestParam(required = false) Integer resetTime, + @RequestParam(required = false) Integer presetIndex) { if (logger.isDebugEnabled()) { logger.debug("报警复位API调用"); } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 558bd14b..ddbf237a 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -114,5 +114,5 @@ user-settings: device-status-notify: true # [可选] 日志配置, 一般不需要改 logging: - config: classpath:logback-spring-local.xml + config: classpath:logback-spring.xml diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 24f49468..02e92e7e 100755 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -100,9 +100,9 @@ {{ scope.row.location }} - + @@ -178,13 +178,24 @@ @click="changeSubchannel(scope.row)">查看 - 设备录像 - - 云端录像 - + + + + + + + + + + 更多功能 + + + + 设备录像 + + 云端录像 + + @@ -312,7 +323,7 @@ export default { that.total = res.data.data.total; that.deviceChannelList = res.data.data.list; that.deviceChannelList.forEach(e => { - e.ptztype = e.ptztype + ""; + e.ptzType = e.ptzType + ""; that.$set(e, "edit", false); that.$set(e, "location", ""); if (e.longitude && e.latitude) { @@ -372,6 +383,13 @@ export default { // that.$message.error("请求超时"); }); }, + moreClick: function (command, itemData) { + if (command === "records") { + this.queryRecords(itemData) + }else if (command === "cloudRecords") { + this.queryCloudRecords(itemData) + } + }, queryRecords: function (itemData) { let deviceId = this.deviceId; let channelId = itemData.channelId; @@ -460,7 +478,7 @@ export default { this.total = res.data.data.total; this.deviceChannelList = res.data.data.list; this.deviceChannelList.forEach(e => { - e.ptztype = e.ptztype + ""; + e.ptzType = e.ptzType + ""; this.$set(e, "edit", false); this.$set(e, "location", ""); if (e.longitude && e.latitude) { diff --git a/web_src/src/components/common/DeviceTree.vue b/web_src/src/components/common/DeviceTree.vue index c701bf0f..6030dc8a 100755 --- a/web_src/src/components/common/DeviceTree.vue +++ b/web_src/src/components/common/DeviceTree.vue @@ -131,11 +131,11 @@ export default { type = 2; } console.log(type) - if (item.basicData.ptztype === 1 ) { // 1-球机;2-半球;3-固定枪机;4-遥控枪机 + if (item.basicData.ptzType === 1 ) { // 1-球机;2-半球;3-固定枪机;4-遥控枪机 type = 4; - }else if (item.basicData.ptztype === 2) { + }else if (item.basicData.ptzType === 2) { type = 5; - }else if (item.basicData.ptztype === 3 || item.basicData.ptztype === 4) { + }else if (item.basicData.ptzType === 3 || item.basicData.ptzType === 4) { type = 6; } }else { diff --git a/web_src/src/components/dialog/channelMapInfobox.vue b/web_src/src/components/dialog/channelMapInfobox.vue index 2ef0e529..fa7ae5c9 100755 --- a/web_src/src/components/dialog/channelMapInfobox.vue +++ b/web_src/src/components/dialog/channelMapInfobox.vue @@ -7,7 +7,7 @@ {{channel.owner}} {{channel.civilCode}} {{channel.address}} - {{channel.ptztypeText}} + {{channel.ptzTypeText}} {{channel.longitude}},{{channel.latitude}} 在线 diff --git a/web_src/src/components/dialog/rtcPlayer.vue b/web_src/src/components/dialog/rtcPlayer.vue index f957df71..34fa35a5 100755 --- a/web_src/src/components/dialog/rtcPlayer.vue +++ b/web_src/src/components/dialog/rtcPlayer.vue @@ -41,8 +41,8 @@ export default { zlmsdpUrl: url,//流地址 simulecast: false, useCamera: false, - audioEnable: false, - videoEnable: false, + audioEnable: true, + videoEnable: true, recvOnly: true, }) webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE 协商出错 diff --git a/web_src/src/components/map.vue b/web_src/src/components/map.vue index 248426ce..64ae0e2d 100755 --- a/web_src/src/components/map.vue +++ b/web_src/src/components/map.vue @@ -243,7 +243,7 @@ export default { }, getImageByChannel: function (channel) { let src = "static/images/gis/camera.png" - switch (channel.ptztype) { + switch (channel.ptzType) { case 1: if (channel.status === 1) { src = "static/images/gis/camera1.png"