From 3f6ef955f51ba13991d3e71d7fa031d39d06a689 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 26 Apr 2024 15:02:49 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A9=BA=E6=8C=87?= =?UTF-8?q?=E9=92=88=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java | 4 +--- .../request/impl/NotifyRequestForMobilePositionProcessor.java | 2 +- .../iot/vmp/storager/impl/RedisCatchStorageImpl.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) 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 a9ce759f..cbf431ac 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 @@ -520,9 +520,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { if (parentPlatform == null) { return; } - if (logger.isDebugEnabled()) { - logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); - } + logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat()); String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java index 9f6acc96..013d95eb 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java @@ -166,7 +166,7 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor }catch (Exception e) { logger.error("[向上级转发移动位置失败] ", e); } - if (mobilePosition.getChannelId().equals(mobilePosition.getDeviceId()) || mobilePosition.getChannelId() == null) { + if (mobilePosition.getChannelId() == null || mobilePosition.getChannelId().equals(mobilePosition.getDeviceId()) ) { List channels = deviceChannelService.queryChaneListByDeviceId(mobilePosition.getDeviceId()); channels.forEach(channel -> { // 发送redis消息。 通知位置信息的变化 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 8b9cc079..e42ea68b 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 @@ -570,7 +570,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public void sendMobilePositionMsg(JSONObject jsonObject) { String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION; -// logger.info("[redis发送通知] 发送 移动位置 {}: {}", key, jsonObject.toString()); + logger.info("[redis发送通知] 发送 移动位置 {}: {}", key, jsonObject.toString()); redisTemplate.convertAndSend(key, jsonObject); } From d4cdf5510bb581f2ba0526a0b937fd20a87957cc Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 30 Apr 2024 14:39:53 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=89=E6=B5=81?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E8=B0=83=E7=94=A8=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/StreamProxyServiceImpl.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java index f0230f76..3869f0b1 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -170,15 +170,19 @@ public class StreamProxyServiceImpl implements IStreamProxyService { callback.run(ErrorCode.ERROR100.getCode(), "保存失败", null); return; } - HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(param.getApp(), param.getStream(), true, "rtsp", mediaInfo.getId()); - hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItem, response) -> { - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( - mediaInfo, param.getApp(), param.getStream(), null, null); - callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); - }); + if (param.isEnable()) { String talkKey = UUID.randomUUID().toString(); String delayTalkKey = UUID.randomUUID().toString(); + HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(param.getApp(), param.getStream(), true, "rtsp", mediaInfo.getId()); + hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItem, response) -> { + dynamicTask.stop(delayTalkKey); + hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( + mediaInfo, param.getApp(), param.getStream(), null, null); + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); + }); + dynamicTask.startDelay(delayTalkKey, ()->{ StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); if (streamInfo != null) { @@ -324,6 +328,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService { zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream()); } if ("ffmpeg".equalsIgnoreCase(param.getType())){ + if (param.getTimeoutMs() == 0) { + param.setTimeoutMs(15); + } result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrcUrl().trim(), param.getDstUrl(), param.getTimeoutMs() + "", param.isEnableAudio(), param.isEnableMp4(), param.getFfmpegCmdKey()); @@ -379,6 +386,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { gbStreamMapper.del(app, stream); videoManagerStorager.deleteStreamProxy(app, stream); redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PULL", app, stream); + redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PUSH", app, stream); JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyItem); if (jsonObject != null && jsonObject.getInteger("code") == 0) { logger.info("[移除代理]: 代理: {}/{}, 从zlm移除成功", app, stream); From 186b00e9b308937397bd652e2b149cb799b087bd Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 8 May 2024 11:18:47 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E4=BA=91=E7=AB=AF=E5=BD=95=E5=83=8F=E7=9A=84?= =?UTF-8?q?zip=E5=8E=8B=E7=BC=A9=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../cmd/SIPRequestHeaderProvider.java | 1 + .../iot/vmp/service/ICloudRecordService.java | 4 +- .../service/impl/CloudRecordServiceImpl.java | 31 ++- .../dao/CloudRecordServiceMapper.java | 7 +- .../com/genersoft/iot/vmp/utils/DateUtil.java | 8 + .../cloudRecord/CloudRecordController.java | 229 +++++++++++++++++- .../cloudRecord/bean/CloudRecordUrl.java | 32 +++ 8 files changed, 302 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/bean/CloudRecordUrl.java diff --git a/pom.xml b/pom.xml index 7ec73b81..df841d52 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.genersoft wvp-pro - 2.7.0 + 2.7.1 web video platform 国标28181视频平台 ${project.packaging} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java index 3a9f5fb3..dd30fea5 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java @@ -168,6 +168,7 @@ public class SIPRequestHeaderProvider { // via ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); +// viaHeader.setRPort(); viaHeaders.add(viaHeader); //from SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); diff --git a/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java b/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java index c10313e8..a6da6156 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java @@ -18,7 +18,7 @@ public interface ICloudRecordService { /** * 分页回去云端录像列表 */ - PageInfo getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List mediaServerItems); + PageInfo getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List mediaServerItems, String callId); /** * 根据hook消息增加一条记录 @@ -56,4 +56,6 @@ public interface ICloudRecordService { * 获取播放地址 */ DownloadFileInfo getPlayUrlPath(Integer recordId); + + List getAllList(String query, String app, String stream, String startTime, String endTime, List mediaServerItems, String callId, List ids); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java index a23252f6..6e501e28 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java @@ -51,7 +51,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService { private VideoStreamSessionManager streamSession; @Override - public PageInfo getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List mediaServerItems) { + public PageInfo getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List mediaServerItems, String callId) { // 开始时间和结束时间在数据库中都是以秒为单位的 Long startTimeStamp = null; Long endTimeStamp = null; @@ -71,7 +71,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService { } PageHelper.startPage(page, count); List all = cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp, - null, mediaServerItems); + callId, mediaServerItems, null); return new PageInfo<>(all); } @@ -87,7 +87,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService { long startTimeStamp = startDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond(); long endTimeStamp = endDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond(); List cloudRecordItemList = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp, - endTimeStamp, null, mediaServerItems); + endTimeStamp, null, mediaServerItems, null); if (cloudRecordItemList.isEmpty()) { return new ArrayList<>(); } @@ -196,7 +196,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService { } List all = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp, endTimeStamp, - callId, mediaServerItems); + callId, mediaServerItems, null); if (all.isEmpty()) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到待收藏的视频"); } @@ -232,4 +232,27 @@ public class CloudRecordServiceImpl implements ICloudRecordService { MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId()); return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath); } + + @Override + public List getAllList(String query, String app, String stream, String startTime, String endTime, List mediaServerItems, String callId, List ids) { + // 开始时间和结束时间在数据库中都是以秒为单位的 + Long startTimeStamp = null; + Long endTimeStamp = null; + if (startTime != null ) { + if (!DateUtil.verification(startTime, DateUtil.formatter)) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间格式错误,正确格式为: " + DateUtil.formatter); + } + startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(startTime); + + } + if (endTime != null ) { + if (!DateUtil.verification(endTime, DateUtil.formatter)) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "结束时间格式错误,正确格式为: " + DateUtil.formatter); + } + endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(endTime); + + } + return cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp, + callId, mediaServerItems, ids); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java index 08f67ba9..b446148a 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java @@ -50,12 +50,15 @@ public interface CloudRecordServiceMapper { " and media_server_id in " + " #{item.id}" + " " + + " and id in " + + " #{item}" + + " " + " order by start_time DESC" + - " ") List getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream, @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp, - @Param("callId")String callId, List mediaServerItemList); + @Param("callId")String callId, List mediaServerItemList, + List ids); @Select(" ") void updateChannelStreamIdentification(DeviceChannel channel); + + + @Update({""}) + void batchUpdatePosition(List channelList); + } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java index 7bf243ca..19494f03 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java @@ -13,7 +13,8 @@ import java.util.List; public interface DeviceMobilePositionMapper { @Insert("INSERT INTO wvp_device_mobile_position (device_id,channel_id, device_name,time,longitude,latitude,altitude,speed,direction,report_source,longitude_gcj02,latitude_gcj02,longitude_wgs84,latitude_wgs84,create_time)"+ - "VALUES (#{deviceId}, #{channelId}, #{deviceName}, #{time}, #{longitude}, #{latitude}, #{altitude}, #{speed}, #{direction}, #{reportSource}, #{longitudeGcj02}, #{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{createTime})") + "VALUES (#{deviceId}, #{channelId}, #{deviceName}, #{time}, #{longitude}, #{latitude}, #{altitude}, " + + "#{speed}, #{direction}, #{reportSource}, #{longitudeGcj02}, #{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{createTime})") int insertNewPosition(MobilePosition mobilePosition); @Select(value = {" ") + void batchInsert(List mobilePositions); } From 5564cfb384db16db972e8cb91ca55cf345cfb6ea Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 13 May 2024 17:22:36 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=A7=E9=87=8Fnotif?= =?UTF-8?q?y=20=E7=A7=BB=E5=8A=A8=E4=BD=8D=E7=BD=AE=E8=AE=A2=E9=98=85?= =?UTF-8?q?=E7=9A=84=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/conf/redis/RedisTemplateConfig.java | 17 ++++ ...tifyRequestForMobilePositionProcessor.java | 37 +------- .../vmp/service/IMobilePositionService.java | 13 +++ .../impl/MobilePositionServiceImpl.java | 95 +++++++++++++++++++ .../vmp/storager/dao/DeviceChannelMapper.java | 17 ---- .../dao/DeviceMobilePositionMapper.java | 4 +- 6 files changed, 132 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/service/IMobilePositionService.java create mode 100644 src/main/java/com/genersoft/iot/vmp/service/impl/MobilePositionServiceImpl.java diff --git a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java index df3345ee..2dc66b38 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.conf.redis; import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; @@ -25,4 +26,20 @@ public class RedisTemplateConfig { redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } + + @Bean + public RedisTemplate getRedisTemplateForMobilePosition(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 使用fastJson序列化 + GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer(); + // value值的序列化采用fastJsonRedisSerializer + redisTemplate.setValueSerializer(fastJsonRedisSerializer); + redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); + + // key的序列化采用StringRedisSerializer + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory); + return redisTemplate; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java index 013d95eb..96e4ecac 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.service.IDeviceChannelService; +import com.genersoft.iot.vmp.service.IMobilePositionService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.DateUtil; import org.dom4j.DocumentException; @@ -20,15 +21,11 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import javax.sip.RequestEvent; import javax.sip.header.FromHeader; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; /** @@ -54,6 +51,9 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor @Autowired private IDeviceChannelService deviceChannelService; + @Autowired + private IMobilePositionService mobilePositionService; + public void process(RequestEvent evt) { if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) { @@ -64,13 +64,10 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor } @Scheduled(fixedRate = 200) //每200毫秒执行一次 - @Transactional public void executeTaskQueue() { if (taskQueue.isEmpty()) { return; } - Map updateChannelMap = new ConcurrentHashMap<>(); - List addMobilePositionList = new ArrayList<>(); for (HandlerCatchData take : taskQueue) { if (take == null) { continue; @@ -150,16 +147,7 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor // mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime); mobilePosition.setReportSource("Mobile Position"); - // 更新device channel 的经纬度 - DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setDeviceId(device.getDeviceId()); - deviceChannel.setLongitude(mobilePosition.getLongitude()); - deviceChannel.setLatitude(mobilePosition.getLatitude()); - deviceChannel.setGpsTime(mobilePosition.getTime()); - updateChannelMap.put(deviceId + mobilePosition.getChannelId(), deviceChannel); - addMobilePositionList.add(mobilePosition); - - + mobilePositionService.add(mobilePosition); // 向关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息 try { eventPublisher.mobilePositionEventPublish(mobilePosition); @@ -199,21 +187,6 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor } } taskQueue.clear(); - if(!updateChannelMap.isEmpty()) { - List channels = new ArrayList<>(updateChannelMap.values()); - logger.info("[移动位置订阅]更新通道位置: {}", channels.size()); - deviceChannelService.batchUpdateChannel(channels); - updateChannelMap.clear(); - } - if (userSetting.isSavePositionHistory() && !addMobilePositionList.isEmpty()) { - try { - logger.info("[移动位置订阅] 添加通道轨迹点位: {}", addMobilePositionList.size()); - deviceChannelService.batchAddMobilePosition(addMobilePositionList); - }catch (Exception e) { - logger.info("[移动位置订阅] b添加通道轨迹点位保存失败: {}", addMobilePositionList.size()); - } - addMobilePositionList.clear(); - } } @Scheduled(fixedRate = 10000) public void execute(){ diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMobilePositionService.java b/src/main/java/com/genersoft/iot/vmp/service/IMobilePositionService.java new file mode 100644 index 00000000..9af64150 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/IMobilePositionService.java @@ -0,0 +1,13 @@ +package com.genersoft.iot.vmp.service; + + +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; + +import java.util.List; + +public interface IMobilePositionService { + + void add(List mobilePositionList); + + void add(MobilePosition mobilePosition); +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MobilePositionServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MobilePositionServiceImpl.java new file mode 100644 index 00000000..277493ad --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MobilePositionServiceImpl.java @@ -0,0 +1,95 @@ +package com.genersoft.iot.vmp.service.impl; + +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; +import com.genersoft.iot.vmp.service.IMobilePositionService; +import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; +import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@Service +public class MobilePositionServiceImpl implements IMobilePositionService { + + @Autowired + private DeviceChannelMapper channelMapper; + + @Autowired + private DeviceMobilePositionMapper mobilePositionMapper; + + @Autowired + private UserSetting userSetting; + + @Autowired + private RedisTemplate redisTemplate; + + private final static Logger logger = LoggerFactory.getLogger(MobilePositionServiceImpl.class); + + private final String REDIS_MOBILE_POSITION_LIST = "redis_mobile_position_list"; + + @Override + public void add(MobilePosition mobilePosition) { + List list = new ArrayList<>(); + list.add(mobilePosition); + add(list); + } + + @Override + public void add(List mobilePositionList) { + redisTemplate.opsForList().leftPushAll(REDIS_MOBILE_POSITION_LIST, mobilePositionList); + } + + private List get(int length) { + Long size = redisTemplate.opsForList().size(REDIS_MOBILE_POSITION_LIST); + if (size == null || size == 0) { + return new ArrayList<>(); + } + List mobilePositions; + if (size > length) { + mobilePositions = redisTemplate.opsForList().rightPop(REDIS_MOBILE_POSITION_LIST, length); + }else { + mobilePositions = redisTemplate.opsForList().rightPop(REDIS_MOBILE_POSITION_LIST, size); + } + return mobilePositions; + } + + + + @Scheduled(fixedRate = 1000) + @Transactional + public void executeTaskQueue() { + int countLimit = 3000; + List mobilePositions = get(countLimit); + if (mobilePositions == null || mobilePositions.isEmpty()) { + return; + } + if (userSetting.getSavePositionHistory()) { + mobilePositionMapper.batchadd(mobilePositions); + } + logger.info("[移动位置订阅]更新通道位置: {}", mobilePositions.size()); + Map updateChannelMap = new HashMap<>(); + for (MobilePosition mobilePosition : mobilePositions) { + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setDeviceId(mobilePosition.getDeviceId()); + deviceChannel.setLongitude(mobilePosition.getLongitude()); + deviceChannel.setLatitude(mobilePosition.getLatitude()); + deviceChannel.setGpsTime(mobilePosition.getTime()); + updateChannelMap.put(mobilePosition.getDeviceId() + mobilePosition.getChannelId(), deviceChannel); + } + List channels = new ArrayList<>(updateChannelMap.values()); + channelMapper.batchUpdatePosition(channels); + } + +} 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 be78a520..15552211 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 @@ -401,23 +401,6 @@ public interface DeviceChannelMapper { " "}) int updatePosition(DeviceChannel deviceChannel); - @Update({""}) - int batchUpdatePosition(List deviceChannelList); - @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/DeviceMobilePositionMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java index c28b16ec..51243106 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java @@ -49,7 +49,7 @@ public interface DeviceMobilePositionMapper { void batchadd2(List mobilePositions); @Insert("") void batchadd(List mobilePositions); From 49101a37e0f71f22fee25b811a54895f2f6f3e82 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 17 May 2024 16:32:01 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E5=85=BC=E5=AE=B9zlm-pro=E8=BD=AC?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotifyRequestForMobilePositionProcessor.java | 4 ++-- .../genersoft/iot/vmp/media/zlm/ZLMServerConfig.java | 11 +++++++++++ .../iot/vmp/media/zlm/dto/MediaServerItem.java | 12 ++++++++++++ .../iot/vmp/service/impl/MediaServerServiceImpl.java | 2 +- .../iot/vmp/service/impl/MediaServiceImpl.java | 5 ++++- .../iot/vmp/storager/dao/MediaServerMapper.java | 4 ++++ .../iot/vmp/storager/impl/RedisCatchStorageImpl.java | 2 +- 数据库/2.7.1/更新-mysql-2.7.1.sql | 2 ++ 数据库/2.7.1/更新-postgresql-kingbase-2.7.1.sql | 2 ++ 9 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 数据库/2.7.1/更新-mysql-2.7.1.sql create mode 100644 数据库/2.7.1/更新-postgresql-kingbase-2.7.1.sql diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java index 96e4ecac..c8111778 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java @@ -143,8 +143,8 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor } } -// logger.info("[收到移动位置订阅通知]:{}/{}->{}.{}, 时间: {}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(), -// mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime); + logger.debug("[收到移动位置订阅通知]:{}/{}->{}.{}, 时间: {}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(), + mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime); mobilePosition.setReportSource("Mobile Position"); mobilePositionService.add(mobilePosition); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java index 80910c02..6d6dcf6a 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java @@ -331,6 +331,9 @@ public class ZLMServerConfig extends HookParam { @JSONField(name = "shell.shell") private String shellPhell; + @JSONField(name = "transcode.suffix") + private String transcodeSuffix; + public String getHookIp() { return hookIp; @@ -1211,4 +1214,12 @@ public class ZLMServerConfig extends HookParam { public void setHookOnRtpServerTimeout(String hookOnRtpServerTimeout) { this.hookOnRtpServerTimeout = hookOnRtpServerTimeout; } + + public String getTranscodeSuffix() { + return transcodeSuffix; + } + + public void setTranscodeSuffix(String transcodeSuffix) { + this.transcodeSuffix = transcodeSuffix; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java index cebfec3b..d5a0f7fa 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java @@ -86,6 +86,9 @@ public class MediaServerItem{ @Schema(description = "录像存储路径") private String recordPath; + @Schema(description = "转码的前缀") + private String transcodeSuffix; + public MediaServerItem() { } @@ -108,6 +111,7 @@ public class MediaServerItem{ rtpEnable = false; // 默认使用单端口;直到用户自己设置开启多端口 rtpPortRange = zlmServerConfig.getPortRange().replace("_",","); // 默认使用30000,30500作为级联时发送流的端口号 recordAssistPort = 0; // 默认关闭 + transcodeSuffix = zlmServerConfig.getTranscodeSuffix(); } @@ -318,4 +322,12 @@ public class MediaServerItem{ public void setRecordPath(String recordPath) { this.recordPath = recordPath; } + + public String getTranscodeSuffix() { + return transcodeSuffix; + } + + public void setTranscodeSuffix(String transcodeSuffix) { + this.transcodeSuffix = transcodeSuffix; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index aeb0dc80..7620baad 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -410,6 +410,7 @@ public class MediaServerServiceImpl implements IMediaServerService { if (serverItem.getRtpProxyPort() == 0) { serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); } + serverItem.setTranscodeSuffix(zlmServerConfig.getTranscodeSuffix()); serverItem.setStatus(true); if (ObjectUtils.isEmpty(serverItem.getId())) { @@ -424,7 +425,6 @@ public class MediaServerServiceImpl implements IMediaServerService { redisTemplate.opsForValue().set(key, serverItem); resetOnlineServerItem(serverItem); - if (serverItem.isAutoConfig()) { setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java index 784f43f3..f2eb754b 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; @@ -91,6 +90,10 @@ public class MediaServiceImpl implements IMediaService { if (addr == null) { addr = mediaInfo.getStreamIp(); } + if (!"broadcast".equalsIgnoreCase(app) && !ObjectUtils.isEmpty(mediaInfo.getTranscodeSuffix()) && !"null".equalsIgnoreCase(mediaInfo.getTranscodeSuffix())) { + stream = stream + "_" + mediaInfo.getTranscodeSuffix(); + streamInfoResult.setStream(stream); + } streamInfoResult.setIp(addr); streamInfoResult.setMediaServerId(mediaInfo.getId()); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java index 46785911..da712128 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -36,6 +36,7 @@ public interface MediaServerMapper { "default_server,"+ "create_time,"+ "update_time,"+ + "transcode_suffix,"+ "hook_alive_interval"+ ") VALUES " + "(" + @@ -62,6 +63,7 @@ public interface MediaServerMapper { "#{defaultServer}, " + "#{createTime}, " + "#{updateTime}, " + + "#{transcodeSuffix}, " + "#{hookAliveInterval})") int add(MediaServerItem mediaServerItem); @@ -88,6 +90,7 @@ public interface MediaServerMapper { ", hook_alive_interval=#{hookAliveInterval}" + ", record_day=#{recordDay}" + ", record_path=#{recordPath}" + + ", transcode_suffix=#{transcodeSuffix}" + "WHERE id=#{id}"+ " "}) int update(MediaServerItem mediaServerItem); @@ -113,6 +116,7 @@ public interface MediaServerMapper { ", record_assist_port=#{recordAssistPort}" + ", record_day=#{recordDay}" + ", record_path=#{recordPath}" + + ", transcode_suffix=#{transcodeSuffix}" + ", hook_alive_interval=#{hookAliveInterval}" + "WHERE ip=#{ip} and http_port=#{httpPort}"+ " "}) 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 e42ea68b..9a18c9ae 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 @@ -570,7 +570,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public void sendMobilePositionMsg(JSONObject jsonObject) { String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION; - logger.info("[redis发送通知] 发送 移动位置 {}: {}", key, jsonObject.toString()); + logger.debug("[redis发送通知] 发送 移动位置 {}: {}", key, jsonObject.toString()); redisTemplate.convertAndSend(key, jsonObject); } diff --git a/数据库/2.7.1/更新-mysql-2.7.1.sql b/数据库/2.7.1/更新-mysql-2.7.1.sql new file mode 100644 index 00000000..86e8d0de --- /dev/null +++ b/数据库/2.7.1/更新-mysql-2.7.1.sql @@ -0,0 +1,2 @@ +alter table wvp_media_server + add transcode_suffix character varying(255); \ No newline at end of file diff --git a/数据库/2.7.1/更新-postgresql-kingbase-2.7.1.sql b/数据库/2.7.1/更新-postgresql-kingbase-2.7.1.sql new file mode 100644 index 00000000..86e8d0de --- /dev/null +++ b/数据库/2.7.1/更新-postgresql-kingbase-2.7.1.sql @@ -0,0 +1,2 @@ +alter table wvp_media_server + add transcode_suffix character varying(255); \ No newline at end of file From d70bfb53dd5d92d0405f7ce3d2c9bbabce26184b Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 20 May 2024 11:37:07 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=BC=E5=AE=B9zlm-p?= =?UTF-8?q?ro=E8=BD=AC=E7=A0=81=E6=97=B6=E6=97=A0=E4=BA=BA=E7=AE=A1?= =?UTF-8?q?=E7=9C=8B=E8=87=AA=E5=8A=A8=E7=A7=BB=E9=99=A4=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/media/zlm/ZLMHttpHookListener.java | 18 ++++++++++++++++++ .../iot/vmp/service/impl/MediaServiceImpl.java | 2 +- .../vmanager/gb28181/play/PlayController.java | 4 ++++ 3 files changed, 23 insertions(+), 1 deletion(-) 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 f3d74777..69682366 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 @@ -351,6 +351,11 @@ public class ZLMHttpHookListener { logger.info("[ZLM HOOK] 流变化未找到ZLM, {}", param.getMediaServerId()); return; } + if (!ObjectUtils.isEmpty(mediaInfo.getTranscodeSuffix()) + && !"null".equalsIgnoreCase(mediaInfo.getTranscodeSuffix()) + && param.getStream().endsWith(mediaInfo.getTranscodeSuffix()) ) { + return; + } if (subscribe != null) { subscribe.response(mediaInfo, param); } @@ -563,6 +568,19 @@ public class ZLMHttpHookListener { logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); + + MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); + if (mediaInfo == null) { + JSONObject ret = new JSONObject(); + ret.put("code", 0); + return ret; + } + if (!ObjectUtils.isEmpty(mediaInfo.getTranscodeSuffix()) + && !"null".equalsIgnoreCase(mediaInfo.getTranscodeSuffix()) + && param.getStream().endsWith(mediaInfo.getTranscodeSuffix()) ) { + param.setStream(param.getStream().substring(0, param.getStream().lastIndexOf(mediaInfo.getTranscodeSuffix()) -1 )); + } + JSONObject ret = new JSONObject(); ret.put("code", 0); // 国标类型的流 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java index f2eb754b..5e46d99f 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java @@ -92,7 +92,7 @@ public class MediaServiceImpl implements IMediaService { } if (!"broadcast".equalsIgnoreCase(app) && !ObjectUtils.isEmpty(mediaInfo.getTranscodeSuffix()) && !"null".equalsIgnoreCase(mediaInfo.getTranscodeSuffix())) { stream = stream + "_" + mediaInfo.getTranscodeSuffix(); - streamInfoResult.setStream(stream); +// streamInfoResult.setStream(stream); } streamInfoResult.setIp(addr); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java index 6404f4e6..42b9d5e3 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -37,6 +37,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; @@ -147,6 +148,9 @@ public class PlayController { } streamInfo.channgeStreamIp(host); } + if (!ObjectUtils.isEmpty(newMediaServerItem.getTranscodeSuffix()) && !"null".equalsIgnoreCase(newMediaServerItem.getTranscodeSuffix())) { + streamInfo.setStream(streamInfo.getStream() + "_" + newMediaServerItem.getTranscodeSuffix()); + } wvpResult.setData(new StreamContent(streamInfo)); }else { wvpResult.setCode(code); From 2daa59d78ce206308c35294da04cffe5e340143a Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 23 May 2024 17:10:45 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BD=BB=E5=BA=95?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E6=96=87=E6=A1=A3=E9=A1=B5=E9=9D=A2=20+=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=91=E7=AB=AF=E5=BD=95=E5=83=8F=E5=81=B6?= =?UTF-8?q?=E7=8E=B0callId=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/conf/SpringDocConfig.java | 2 ++ .../genersoft/iot/vmp/conf/UserSetting.java | 10 +++++++ .../security/JwtAuthenticationFilter.java | 6 +++++ .../vmp/conf/security/WebSecurityConfig.java | 2 +- .../vmp/media/zlm/ZLMHttpHookListener.java | 24 +++-------------- .../zlm/dto/hook/OnRecordMp4HookParam.java | 10 +++++++ .../iot/vmp/service/bean/CloudRecordItem.java | 7 +++++ .../service/impl/CloudRecordServiceImpl.java | 15 +++++------ .../iot/vmp/utils/MediaServerUtils.java | 26 +++++++++++++++++++ src/main/resources/all-application.yml | 2 ++ src/main/resources/application-dev.yml | 3 --- 数据库/2.7.1/初始化-mysql-2.7.1.sql | 1 + .../2.7.1/初始化-postgresql-kingbase-2.7.1.sql | 1 + 13 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/utils/MediaServerUtils.java diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java index 0a472f82..45f9a2fe 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.core.annotation.Order; import org.springdoc.core.GroupedOpenApi; import org.springframework.beans.factory.annotation.Value; @@ -18,6 +19,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration @Order(1) +@ConditionalOnProperty(value = "user-settings.doc-enable", havingValue = "true", matchIfMissing = true) public class SpringDocConfig { @Value("${doc.enabled: true}") diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java index a9b17aef..96253d6e 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java @@ -54,6 +54,8 @@ public class UserSetting { private Boolean deviceStatusNotify = Boolean.TRUE; private Boolean useCustomSsrcForParentInvite = Boolean.TRUE; + private Boolean docEnable = Boolean.TRUE; + private String serverId = "000000"; private String thirdPartyGBIdReg = "[\\s\\S]*"; @@ -315,4 +317,12 @@ public class UserSetting { public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) { this.registerKeepIntDialog = registerKeepIntDialog; } + + public Boolean getDocEnable() { + return docEnable; + } + + public void setDocEnable(Boolean docEnable) { + this.docEnable = docEnable; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java b/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java index f45f89a1..ce24e98a 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java @@ -35,10 +35,16 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { // 忽略登录请求的token验证 String requestURI = request.getRequestURI(); + System.out.println(requestURI); + if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } if (requestURI.equalsIgnoreCase("/api/user/login")) { chain.doFilter(request, response); return; } + if (!userSetting.isInterfaceAuthentication()) { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() ); SecurityContextHolder.getContext().setAuthentication(token); 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 ad959d62..55f93831 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 @@ -117,7 +117,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .authorizeRequests() .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll() - .antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html").permitAll() + .antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html#/**").permitAll() .anyRequest().authenticated() // 异常处理器 .and() 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 69682366..b6390488 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 @@ -29,6 +29,7 @@ import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; +import com.genersoft.iot.vmp.utils.MediaServerUtils; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; @@ -47,7 +48,6 @@ import javax.servlet.http.HttpServletRequest; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import java.text.ParseException; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -179,7 +179,7 @@ public class ZLMHttpHookListener { } }); if (!"rtp".equals(param.getApp())) { - Map paramMap = urlParamToMap(param.getParams()); + Map paramMap = MediaServerUtils.urlParamToMap(param.getParams()); StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) { return new HookResult(401, "Unauthorized"); @@ -220,7 +220,7 @@ public class ZLMHttpHookListener { logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)"); return new HookResultForOnPublish(401, "Unauthorized"); } - Map paramMap = urlParamToMap(param.getParams()); + Map paramMap = MediaServerUtils.urlParamToMap(param.getParams()); String sign = paramMap.get("sign"); if (sign == null) { logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)"); @@ -899,22 +899,4 @@ public class ZLMHttpHookListener { return HookResult.SUCCESS(); } - - private Map urlParamToMap(String params) { - HashMap map = new HashMap<>(); - if (ObjectUtils.isEmpty(params)) { - return map; - } - String[] paramsArray = params.split("&"); - if (paramsArray.length == 0) { - return map; - } - for (String param : paramsArray) { - String[] paramArray = param.split("="); - if (paramArray.length == 2) { - map.put(paramArray[0], paramArray[1]); - } - } - return map; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java index d52165ed..deeeff4d 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java @@ -15,6 +15,7 @@ public class OnRecordMp4HookParam extends HookParam{ private String vhost; private long start_time; private double time_len; + private String params; public String getApp() { return app; @@ -96,6 +97,14 @@ public class OnRecordMp4HookParam extends HookParam{ this.time_len = time_len; } + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + @Override public String toString() { return "OnRecordMp4HookParam{" + @@ -109,6 +118,7 @@ public class OnRecordMp4HookParam extends HookParam{ ", vhost='" + vhost + '\'' + ", start_time=" + start_time + ", time_len=" + time_len + + ", params=" + params + '}'; } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java b/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java index 771e4c81..c6e84de4 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java @@ -1,6 +1,9 @@ package com.genersoft.iot.vmp.service.bean; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; +import com.genersoft.iot.vmp.utils.MediaServerUtils; + +import java.util.Map; /** * 云端录像数据 @@ -88,6 +91,10 @@ public class CloudRecordItem { cloudRecordItem.setMediaServerId(param.getMediaServerId()); cloudRecordItem.setTimeLen((long) param.getTime_len() * 1000); cloudRecordItem.setEndTime((param.getStart_time() + (long)param.getTime_len()) * 1000); + Map paramsMap = MediaServerUtils.urlParamToMap(param.getParams()); + if (paramsMap.get("callId") != null) { + cloudRecordItem.setCallId(paramsMap.get("callId")); + } return cloudRecordItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java index 6e501e28..7c8f6a7e 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java @@ -7,7 +7,6 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; import com.genersoft.iot.vmp.service.ICloudRecordService; import com.genersoft.iot.vmp.service.IMediaServerService; @@ -26,8 +25,12 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.time.*; -import java.util.*; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @Service @DS("share") @@ -102,11 +105,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService { @Override public void addRecord(OnRecordMp4HookParam param) { CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(param); - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); - if (streamAuthorityInfo != null) { - cloudRecordItem.setCallId(streamAuthorityInfo.getCallId()); - } - logger.info("[添加录像记录] {}/{} 文件大小:{}, 时长: {}秒", param.getApp(), param.getStream(), param.getFile_size(),param.getTime_len()); + logger.info("[添加录像记录] {}/{}, callId: {}, 文件大小:{}, 时长: {}秒", param.getApp(), param.getStream(),cloudRecordItem.getCallId(), param.getFile_size(),param.getTime_len()); cloudRecordServiceMapper.add(cloudRecordItem); } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/MediaServerUtils.java b/src/main/java/com/genersoft/iot/vmp/utils/MediaServerUtils.java new file mode 100644 index 00000000..bb575478 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/utils/MediaServerUtils.java @@ -0,0 +1,26 @@ +package com.genersoft.iot.vmp.utils; + +import org.springframework.util.ObjectUtils; + +import java.util.HashMap; +import java.util.Map; + +public class MediaServerUtils { + public static Map urlParamToMap(String params) { + HashMap map = new HashMap<>(); + if (ObjectUtils.isEmpty(params)) { + return map; + } + String[] paramsArray = params.split("&"); + if (paramsArray.length == 0) { + return map; + } + for (String param : paramsArray) { + String[] paramArray = param.split("="); + if (paramArray.length == 2) { + map.put(paramArray[0], paramArray[1]); + } + } + return map; + } +} diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index e6161879..f2fd504a 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -241,6 +241,8 @@ user-settings: register-again-after-time: 60 # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话 register-keep-int-dialog: false + # 开启接口文档页面。 默认开启,生产环境建议关闭,遇到swagger相关的漏洞时也可以关闭 + doc-enable: true # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个 allowed-origins: - http://localhost:8008 diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 5be3036f..bce91183 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -110,7 +110,4 @@ user-settings: auto-apply-play: true # 设备/通道状态变化时发送消息 device-status-notify: true -# [可选] 日志配置, 一般不需要改 -logging: - config: classpath:logback-spring.xml diff --git a/数据库/2.7.1/初始化-mysql-2.7.1.sql b/数据库/2.7.1/初始化-mysql-2.7.1.sql index 6d7864fa..ee828f41 100644 --- a/数据库/2.7.1/初始化-mysql-2.7.1.sql +++ b/数据库/2.7.1/初始化-mysql-2.7.1.sql @@ -166,6 +166,7 @@ create table wvp_media_server ( hook_alive_interval integer, record_path character varying(255), record_day integer default 7, + transcode_suffix character varying(255), constraint uk_media_server_unique_ip_http_port unique (ip, http_port) ); diff --git a/数据库/2.7.1/初始化-postgresql-kingbase-2.7.1.sql b/数据库/2.7.1/初始化-postgresql-kingbase-2.7.1.sql index c81ca31b..86a63d94 100644 --- a/数据库/2.7.1/初始化-postgresql-kingbase-2.7.1.sql +++ b/数据库/2.7.1/初始化-postgresql-kingbase-2.7.1.sql @@ -166,6 +166,7 @@ create table wvp_media_server ( hook_alive_interval integer, record_path character varying(255), record_day integer default 7, + transcode_suffix character varying(255), constraint uk_media_server_unique_ip_http_port unique (ip, http_port) ); From fe9b8154e0d92b181a0024936049c0ddc8e86b5d Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 23 May 2024 17:15:14 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java b/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java index ce24e98a..2382b421 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java @@ -35,7 +35,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { // 忽略登录请求的token验证 String requestURI = request.getRequestURI(); - System.out.println(requestURI); if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); return;