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/21] =?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 a9ce759fd..cbf431ac0 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 9f6acc96e..013d95eba 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 8b9cc0799..e42ea68b6 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/21] =?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 f0230f76d..3869f0b14 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/21] =?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 7ec73b81c..df841d521 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 3a9f5fb37..dd30fea53 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 c10313e8e..a6da61567 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 a23252f64..6e501e284 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 08f67ba94..b446148a2 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 7bf243cae..19494f033 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/21] =?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 df3345eef..2dc66b38f 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 013d95eba..96e4ecac8 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 000000000..9af64150b --- /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 000000000..277493ad1 --- /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 be78a520e..155522118 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 c28b16ec2..512431063 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 6e8071d820aa55173e64fd25609caa3b6b9af98a Mon Sep 17 00:00:00 2001 From: bradyx Date: Wed, 15 May 2024 13:43:51 +0800 Subject: [PATCH 07/21] =?UTF-8?q?fix:=20=E7=B3=BB=E7=BB=9F=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E6=97=B6=EF=BC=8C=E5=81=9C=E6=AD=A2=E5=B7=B2=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=9B=BD=E6=A0=87=E6=8E=A8=E6=B5=81=E6=8A=9B=E5=87=BA?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E8=A2=AB=E7=B3=BB=E7=BB=9F=E6=8D=95=E8=8E=B7?= =?UTF-8?q?=EF=BC=8C=E5=90=AF=E5=8A=A8=E6=9C=8D=E5=8A=A1=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/task/SipRunner.java | 2 +- .../media/service/IMediaNodeServerService.java | 2 ++ .../vmp/media/service/IMediaServerService.java | 2 ++ .../service/impl/MediaServerServiceImpl.java | 10 ++++++++++ .../media/zlm/ZLMMediaNodeServerService.java | 17 +++++++++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java index b61a623fe..e2b2223fd 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java @@ -104,7 +104,7 @@ public class SipRunner implements CommandLineRunner { redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream()); if (mediaServerItem != null) { ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); - boolean stopResult = mediaServerService.stopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc()); + boolean stopResult = mediaServerService.initStopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc()); if (stopResult) { ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); if (platform != null) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java index 873993826..a3916b36c 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java @@ -29,6 +29,8 @@ public interface IMediaNodeServerService { boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc); + boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc); + boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName); List getMediaList(MediaServer mediaServer, String app, String stream, String callId); diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java index 11d5bf560..cde96df19 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java @@ -76,6 +76,8 @@ public interface IMediaServerService { boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc); + boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc); + boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName); List getMediaList(MediaServer mediaInfo, String app, String stream, String callId); diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java index ae386fc99..2dd66e735 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java @@ -595,6 +595,16 @@ public class MediaServerServiceImpl implements IMediaServerService { return mediaNodeServerService.stopSendRtp(mediaInfo, app, stream, ssrc); } + @Override + public boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaInfo.getType()); + if (mediaNodeServerService == null) { + logger.info("[stopSendRtp] 失败, mediaServer的类型: {},未找到对应的实现类", mediaInfo.getType()); + return false; + } + return mediaNodeServerService.initStopSendRtp(mediaInfo, app, stream, ssrc); + } + @Override public boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName) { IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java index e91ced9d6..4cfdaf323 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java @@ -144,6 +144,23 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService { } + @Override + public boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) { + Map param = new HashMap<>(); + param.put("vhost", "__defaultVhost__"); + param.put("app", app); + param.put("stream", stream); + if (!ObjectUtils.isEmpty(ssrc)) { + param.put("ssrc", ssrc); + } + JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaInfo, param); + if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { + logger.error("停止发流失败: {}, 参数:{}", jsonObject.getString("msg"), JSON.toJSONString(param)); + return false; + } + return true; + } + @Override public boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName) { logger.info("[zlm-deleteRecordDirectory] 删除磁盘文件, server: {} {}:{}->{}/{}", mediaServer.getId(), app, stream, date, fileName); From 7565b2ea779ae973e894b6da051eb4119e49286d Mon Sep 17 00:00:00 2001 From: BradyXu Date: Wed, 15 May 2024 23:28:38 +0800 Subject: [PATCH 08/21] =?UTF-8?q?fix=20=E4=BC=98=E5=8C=96=E5=8F=8A?= =?UTF-8?q?=E8=81=94=E6=9C=AC=E5=9C=B0IP=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/dialog/platformEdit.vue | 106 ++++++++++-------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/web_src/src/components/dialog/platformEdit.vue b/web_src/src/components/dialog/platformEdit.vue index 06cb7c410..0a7522229 100755 --- a/web_src/src/components/dialog/platformEdit.vue +++ b/web_src/src/components/dialog/platformEdit.vue @@ -34,7 +34,7 @@ @@ -58,7 +58,7 @@ - + @@ -100,16 +100,17 @@ - + - - + + {{ - onSubmit_text - }} + onSubmit_text + }} + 取消 @@ -172,52 +173,56 @@ export default { administrativeDivision: "", sendStreamIp: null, }, - deviceIp: [], // 存储用户选择的设备IP + deviceIps: [], // 存储用户设备IP数组 rules: { - name: [{ required: true, message: "请输入平台名称", trigger: "blur" }], + name: [{required: true, message: "请输入平台名称", trigger: "blur"}], serverGBId: [ - { required: true, message: "请输入SIP服务国标编码", trigger: "blur" }, + {required: true, message: "请输入SIP服务国标编码", trigger: "blur"}, ], serverGBDomain: [ - { required: true, message: "请输入SIP服务国标域", trigger: "blur" }, + {required: true, message: "请输入SIP服务国标域", trigger: "blur"}, ], - serverIP: [{ required: true, message: "请输入SIP服务IP", trigger: "blur" }], - serverPort: [{ required: true, message: "请输入SIP服务端口", trigger: "blur" }], - deviceGBId: [{ validator: deviceGBIdRules, trigger: "blur" }], - username: [{ required: false, message: "请输入SIP认证用户名", trigger: "blur" }], - password: [{ required: false, message: "请输入SIP认证密码", trigger: "blur" }], - expires: [{ required: true, message: "请输入注册周期", trigger: "blur" }], - keepTimeout: [{ required: true, message: "请输入心跳周期", trigger: "blur" }], - transport: [{ required: true, message: "请选择信令传输", trigger: "blur" }], - characterSet: [{ required: true, message: "请选择编码字符集", trigger: "blur" }], + serverIP: [{required: true, message: "请输入SIP服务IP", trigger: "blur"}], + serverPort: [{required: true, message: "请输入SIP服务端口", trigger: "blur"}], + deviceGBId: [{validator: deviceGBIdRules, trigger: "blur"}], + username: [{required: false, message: "请输入SIP认证用户名", trigger: "blur"}], + password: [{required: false, message: "请输入SIP认证密码", trigger: "blur"}], + expires: [{required: true, message: "请输入注册周期", trigger: "blur"}], + keepTimeout: [{required: true, message: "请输入心跳周期", trigger: "blur"}], + transport: [{required: true, message: "请选择信令传输", trigger: "blur"}], + characterSet: [{required: true, message: "请选择编码字符集", trigger: "blur"}], + deviceIp: [{required: true, message: "请选择本地IP", trigger: "blur"}], }, }; }, methods: { openDialog: function (platform, callback) { var that = this; - if (platform == null) { - this.onSubmit_text = "立即创建"; - this.saveUrl = "/api/platform/add"; - this.$axios({ - method: 'get', - url:`/api/platform/server_config` - }).then(function (res) { - console.log(res); + this.$axios({ + method: 'get', + url: `/api/platform/server_config` + }).then(function (res) { + if (platform == null) { if (res.data.code === 0) { that.platform.deviceGBId = res.data.data.username; - that.deviceIp = res.data.data.deviceIp.split(','); + that.deviceIps = res.data.data.deviceIp.split(','); + that.platform.deviceIp = that.deviceIps[0]; that.platform.devicePort = res.data.data.devicePort; that.platform.username = res.data.data.username; that.platform.password = res.data.data.password; that.platform.sendStreamIp = res.data.data.sendStreamIp; that.platform.administrativeDivision = res.data.data.username.substr(0, 6); } - - }).catch(function (error) { - console.log(error); - }); - }else { + } else { + that.deviceIps = res.data.data.deviceIp.split(','); + } + }).catch(function (error) { + console.log(error); + }); + if (platform == null) { + this.onSubmit_text = "立即创建"; + this.saveUrl = "/api/platform/add"; + } else { this.platform.id = platform.id; this.platform.enable = platform.enable; this.platform.ptz = platform.ptz; @@ -230,7 +235,7 @@ export default { this.platform.serverIP = platform.serverIP; this.platform.serverPort = platform.serverPort; this.platform.deviceGBId = platform.deviceGBId; - this.deviceIp = platform.deviceIp.split(','); + this.platform.deviceIp = platform.deviceIp; this.platform.devicePort = platform.devicePort; this.platform.username = platform.username; this.platform.password = platform.password; @@ -256,7 +261,7 @@ export default { }, deviceGBIdChange: function () { - this.platform.username = this.platform.deviceGBId ; + this.platform.username = this.platform.deviceGBId; if (this.platform.administrativeDivision == null) { this.platform.administrativeDivision = this.platform.deviceGBId.substr(0, 6); } @@ -264,12 +269,12 @@ export default { onSubmit: function () { this.saveForm() }, - saveForm: function (){ + saveForm: function () { this.$axios({ method: 'post', url: this.saveUrl, data: this.platform - }).then((res) =>{ + }).then((res) => { if (res.data.code === 0) { this.$message({ showClose: true, @@ -280,14 +285,14 @@ export default { if (this.listChangeCallback != null) { this.listChangeCallback(); } - }else { + } else { this.$message({ showClose: true, message: res.data.msg, type: "error", }); } - }).catch((error)=> { + }).catch((error) => { console.log(error); }); }, @@ -325,24 +330,25 @@ export default { var result = false; var that = this; await that.$axios({ - method: 'get', - url:`/api/platform/exit/${deviceGbId}`}) + method: 'get', + url: `/api/platform/exit/${deviceGbId}` + }) .then(function (res) { - if (res.data.code === 0) { - result = res.data.data; - } + if (res.data.code === 0) { + result = res.data.data; + } }) .catch(function (error) { console.log(error); }); return result; }, - checkExpires: function() { + checkExpires: function () { if (this.platform.enable && this.platform.expires === "0") { this.platform.expires = "3600"; } }, - rtcpCheckBoxChange: function (result){ + rtcpCheckBoxChange: function (result) { if (result) { this.$message({ showClose: true, @@ -363,10 +369,12 @@ input::-webkit-inner-spin-button { appearance: none; margin: 0; } + /* 火狐 */ -input{ - -moz-appearance:textfield; +input { + -moz-appearance: textfield; } + .control-wrapper-not-used { position: relative; width: 6.25rem; From 09efdef4cee532bfd69811088d9bd21026159af5 Mon Sep 17 00:00:00 2001 From: hexq Date: Thu, 16 May 2024 13:25:06 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=E8=A7=A3=E5=86=B3MacOS=2014=E5=AF=B8=20M?= =?UTF-8?q?2=EF=BC=9A=E6=9C=80=E6=96=B0Chrome=E5=9B=BD=E6=A0=87=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E9=80=9A=E9=81=93=E2=80=9C=E7=9B=B4=E6=92=AD=E2=80=9D?= =?UTF-8?q?Jessibuca=E6=92=AD=E6=94=BE=E4=B8=8B=E6=96=B9=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E9=BB=91=E5=B1=8F=E7=9A=84=E5=85=BC=E5=AE=B9BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/src/components/common/jessibuca.vue | 5 +++++ web_src/src/components/dialog/devicePlayer.vue | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/web_src/src/components/common/jessibuca.vue b/web_src/src/components/common/jessibuca.vue index afd422297..4ea732ce8 100755 --- a/web_src/src/components/common/jessibuca.vue +++ b/web_src/src/components/common/jessibuca.vue @@ -1,6 +1,7 @@