Commit cadd0ee0387c7c4af4b6d8eb10641ef006174837

Authored by 648540858
2 parents 16e8aa32 0191e937

Merge remote-tracking branch 'origin/wvp-pro-record' into wvp-28181-2.0

# Conflicts:
#	web_src/src/components/control.vue
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.event.record;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
  4 +import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
  5 +import org.springframework.context.ApplicationEvent;
  6 +
  7 +/**
  8 + * @description: 录像查询结束时间
  9 + * @author: pan
  10 + * @data: 2022-02-23
  11 + */
  12 +
  13 +public class RecordEndEvent extends ApplicationEvent {
  14 + /**
  15 + *
  16 + */
  17 + private static final long serialVersionUID = 1L;
  18 +
  19 + public RecordEndEvent(Object source) {
  20 + super(source);
  21 + }
  22 +
  23 + private RecordInfo recordInfo;
  24 +
  25 + public RecordInfo getRecordInfo() {
  26 + return recordInfo;
  27 + }
  28 +
  29 + public void setRecordInfo(RecordInfo recordInfo) {
  30 + this.recordInfo = recordInfo;
  31 + }
  32 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.event.record;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +import org.springframework.context.ApplicationListener;
  7 +import org.springframework.stereotype.Component;
  8 +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  9 +
  10 +import java.io.IOException;
  11 +import java.util.*;
  12 +
  13 +/**
  14 + * @description: 录像查询结束时间
  15 + * @author: pan
  16 + * @data: 2022-02-23
  17 + */
  18 +
  19 +@Component
  20 +public class RecordEndEventListener implements ApplicationListener<RecordEndEvent> {
  21 +
  22 + private final static Logger logger = LoggerFactory.getLogger(RecordEndEventListener.class);
  23 +
  24 + private static Map<String, SseEmitter> sseEmitters = new Hashtable<>();
  25 +
  26 + public void addSseEmitters(String browserId, SseEmitter sseEmitter) {
  27 + sseEmitters.put(browserId, sseEmitter);
  28 + }
  29 +
  30 + public interface RecordEndEventHandler{
  31 + void handler(List<RecordItem> recordItems);
  32 + }
  33 +
  34 + private Map<String, RecordEndEventHandler> handlerMap = new HashMap<>();
  35 + @Override
  36 + public void onApplicationEvent(RecordEndEvent event) {
  37 + if (logger.isDebugEnabled()) {
  38 + logger.debug("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}条", event.getRecordInfo().getDeviceId(),
  39 + event.getRecordInfo().getChannelId(), event.getRecordInfo().getRecordList().size() );
  40 + }
  41 +
  42 + }
  43 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -258,7 +258,7 @@ public interface ISIPCommander {
258 258 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
259 259 * @param sn
260 260 */
261   - boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent);
  261 + boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
262 262  
263 263 /**
264 264 * 查询报警信息
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -1196,8 +1196,13 @@ public class SIPCommander implements ISIPCommander {
1196 1196 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
1197 1197 */
1198 1198 @Override
1199   - public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent) {
1200   -
  1199 + public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
  1200 + if (secrecy == null) {
  1201 + secrecy = 0;
  1202 + }
  1203 + if (type == null) {
  1204 + type = "all";
  1205 + }
1201 1206  
1202 1207 try {
1203 1208 StringBuffer recordInfoXml = new StringBuffer(200);
... ... @@ -1208,9 +1213,9 @@ public class SIPCommander implements ISIPCommander {
1208 1213 recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1209 1214 recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
1210 1215 recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
1211   - recordInfoXml.append("<Secrecy>0</Secrecy>\r\n");
  1216 + recordInfoXml.append("<Secrecy> "+ secrecy + " </Secrecy>\r\n");
1212 1217 // 大华NVR要求必须增加一个值为all的文本元素节点Type
1213   - recordInfoXml.append("<Type>all</Type>\r\n");
  1218 + recordInfoXml.append("<Type>" + type+"</Type>\r\n");
1214 1219 recordInfoXml.append("</Query>\r\n");
1215 1220  
1216 1221 String tm = Long.toString(System.currentTimeMillis());
... ... @@ -1221,7 +1226,7 @@ public class SIPCommander implements ISIPCommander {
1221 1226 Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
1222 1227 "z9hG4bK-ViaRecordInfo-" + tm, "fromRec" + tm, null, callIdHeader);
1223 1228  
1224   - transmitRequest(device, request, errorEvent);
  1229 + transmitRequest(device, request, errorEvent, okEvent);
1225 1230 } catch (SipException | ParseException | InvalidArgumentException e) {
1226 1231 e.printStackTrace();
1227 1232 return false;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -91,7 +91,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
91 91  
92 92 sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{
93 93 if (event != null) {
94   - logger.info("向上级平台 [ {} ] 注册发错误: {} ",
  94 + logger.info("向上级平台 [ {} ] 注册发错误: {} ",
95 95 parentPlatform.getServerGBId(),
96 96 event.msg);
97 97 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
  2 +
  3 +import com.genersoft.iot.vmp.conf.SipConfig;
  4 +import com.genersoft.iot.vmp.gb28181.bean.*;
  5 +import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  7 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
  9 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
  10 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
  11 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
  12 +import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
  13 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  14 +import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
  15 +import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
  16 +import org.dom4j.Element;
  17 +import org.slf4j.Logger;
  18 +import org.slf4j.LoggerFactory;
  19 +import org.springframework.beans.factory.InitializingBean;
  20 +import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.springframework.stereotype.Component;
  22 +
  23 +import javax.sip.InvalidArgumentException;
  24 +import javax.sip.RequestEvent;
  25 +import javax.sip.SipException;
  26 +import javax.sip.header.FromHeader;
  27 +import javax.sip.message.Response;
  28 +import java.text.ParseException;
  29 +import java.util.List;
  30 +
  31 +@Component
  32 +public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
  33 +
  34 + private Logger logger = LoggerFactory.getLogger(RecordInfoQueryMessageHandler.class);
  35 + private final String cmdType = "RecordInfo";
  36 +
  37 + @Autowired
  38 + private QueryMessageHandler queryMessageHandler;
  39 +
  40 + @Autowired
  41 + private IVideoManagerStorager storager;
  42 +
  43 + @Autowired
  44 + private SIPCommanderFroPlatform cmderFroPlatform;
  45 +
  46 + @Autowired
  47 + private SIPCommander commander;
  48 +
  49 + @Autowired
  50 + private SipConfig config;
  51 +
  52 + @Autowired
  53 + private EventPublisher publisher;
  54 +
  55 + @Override
  56 + public void afterPropertiesSet() throws Exception {
  57 + queryMessageHandler.addHandler(cmdType, this);
  58 + }
  59 +
  60 + @Override
  61 + public void handForDevice(RequestEvent evt, Device device, Element element) {
  62 +
  63 + }
  64 +
  65 + @Override
  66 + public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
  67 +
  68 + String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId();
  69 + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
  70 + try {
  71 + // 回复200 OK
  72 + responseAck(evt, Response.OK);
  73 + Element snElement = rootElement.element("SN");
  74 + int sn = Integer.parseInt(snElement.getText());
  75 + Element deviceIDElement = rootElement.element("DeviceID");
  76 + String channelId = deviceIDElement.getText();
  77 + Element startTimeElement = rootElement.element("StartTime");
  78 + String startTime = startTimeElement.getText();
  79 + Element endTimeElement = rootElement.element("EndTime");
  80 + String endTime = endTimeElement.getText();
  81 + Element secrecyElement = rootElement.element("Secrecy");
  82 + int secrecy = Integer.parseInt(secrecyElement.getText());
  83 + Element typeElement = rootElement.element("Type");
  84 + String type = typeElement.getText();
  85 + // 确认是直播还是国标, 国标直接请求下级,直播请求录像管理服务
  86 + List<ChannelSourceInfo> channelSources = storager.getChannelSource(parentPlatform.getServerGBId(), channelId);
  87 + if (channelSources.get(0).getCount() > 0) { // 国标
  88 + // 向国标设备请求录像数据
  89 + Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
  90 + commander.recordInfoQuery(device, channelId, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
  91 + DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
  92 + // 查询成功
  93 +
  94 + }),(eventResult -> {
  95 + // 查询失败
  96 +
  97 + }));
  98 +
  99 + }else if (channelSources.get(0).getCount() > 0) { // 直播流
  100 + // TODO
  101 + }else { // 错误的请求
  102 +
  103 + }
  104 + } catch (SipException e) {
  105 + e.printStackTrace();
  106 + } catch (InvalidArgumentException e) {
  107 + e.printStackTrace();
  108 + } catch (ParseException e) {
  109 + e.printStackTrace();
  110 + }
  111 +
  112 + }
  113 +}
... ...
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
... ... @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
5 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
6 6 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
7 7 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  8 +import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
8 9 import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree;
9 10 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
10 11 import com.github.pagehelper.PageInfo;
... ... @@ -475,4 +476,6 @@ public interface IVideoManagerStorager {
475 476 void delRelationByPlatformId(String serverGBId);
476 477  
477 478 PlatformCatalog queryDefaultCatalogInPlatform(String platformId);
  479 +
  480 + List<ChannelSourceInfo> getChannelSource(String platformId, String gbId);
478 481 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
1 1 package com.genersoft.iot.vmp.storager.dao;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  4 +import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
4 5 import org.apache.ibatis.annotations.*;
5 6 import org.springframework.stereotype.Repository;
6 7  
... ... @@ -86,4 +87,9 @@ public interface ParentPlatformMapper {
86 87 "WHERE serverGBId=#{platformId}"+
87 88 "</script>"})
88 89 int setDefaultCatalog(String platformId, String catalogId);
  90 +
  91 + @Select("select 'channel' as name, count(pgc.platformId) count from platform_gb_channel pgc where pgc.platformId=#{platformId} and pgc.channelId =#{gbId} " +
  92 + "union " +
  93 + "select 'stream' as name, count(pgs.platformId) count from platform_gb_stream pgs left join gb_stream gs on pgs.gbStreamId = gs.id where pgs.platformId=#{platformId} and gs.gbId = #{gbId}")
  94 + List<ChannelSourceInfo> getChannelSource(String platformId, String gbId);
89 95 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/dto/ChannelSourceInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.storager.dao.dto;
  2 +
  3 +public class ChannelSourceInfo {
  4 + private String name;
  5 + private int count;
  6 +
  7 + public String getName() {
  8 + return name;
  9 + }
  10 +
  11 + public void setName(String name) {
  12 + this.name = name;
  13 + }
  14 +
  15 + public int getCount() {
  16 + return count;
  17 + }
  18 +
  19 + public void setCount(int count) {
  20 + this.count = count;
  21 + }
  22 +}
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
... ... @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
14 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
16 16 import com.genersoft.iot.vmp.storager.dao.*;
  17 +import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
17 18 import com.genersoft.iot.vmp.utils.node.ForestNodeMerger;
18 19 import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree;
19 20 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
... ... @@ -1104,4 +1105,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
1104 1105 public PlatformCatalog queryDefaultCatalogInPlatform(String platformId) {
1105 1106 return catalogMapper.selectDefaultByPlatFormId(platformId);
1106 1107 }
  1108 +
  1109 + @Override
  1110 + public List<ChannelSourceInfo> getChannelSource(String platformId, String gbId) {
  1111 + return platformMapper.getChannelSource(platformId, gbId);
  1112 + }
1107 1113 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
... ... @@ -137,6 +137,11 @@ public class PlatformController {
137 137 wvpResult.setMsg("missing parameters");
138 138 return new ResponseEntity<>(wvpResult, HttpStatus.BAD_REQUEST);
139 139 }
  140 + if (parentPlatform.getServerPort()< 0 || parentPlatform.getServerPort() > 65535){
  141 + wvpResult.setCode(-1);
  142 + wvpResult.setMsg("error severPort");
  143 + return new ResponseEntity<>(wvpResult, HttpStatus.BAD_REQUEST);
  144 + }
140 145  
141 146 ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
142 147 if (parentPlatformOld != null) {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
... ... @@ -64,7 +64,7 @@ public class GBRecordController {
64 64 RequestMessage msg = new RequestMessage();
65 65 msg.setId(uuid);
66 66 msg.setKey(key);
67   - cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, (eventResult -> {
  67 + cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
68 68 msg.setData("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg );
69 69 resultHolder.invokeResult(msg);
70 70 }));
... ...
src/main/resources/all-application.yml
1 1  
2 2  
3 3  
4   -# 此配置文件只是用作展示所有配置项, 不可直接使用
  4 +# 此配置文件只是用作展示所有配置项, 不可直接使用
5 5  
6 6  
7 7 spring:
... ...
web_src/src/components/control.vue
... ... @@ -37,8 +37,20 @@
37 37 </el-popover>
38 38 <el-popover placement="bottom" width="900" height="300" trigger="click">
39 39 <div style="height: 600px;overflow:auto; padding: 20px">
  40 + <el-descriptions title="国标配置" border column="1">
  41 + <template slot="extra">
  42 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.sip)" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  43 + </template>
  44 + <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip">
  45 + <template slot="label">
  46 + {{ getNameFromKey(key) }}
  47 + </template>
  48 + {{ value }}
  49 + </el-descriptions-item>
  50 + </el-descriptions>
40 51  
41   - <el-descriptions title="基础配置" border column="1">
  52 + <div style="margin-top: 1rem">
  53 + <el-descriptions title="基础配置" border column="1">
42 54 <template slot="extra">
43 55 <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.base)" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
44 56 </template>
... ... @@ -70,18 +82,6 @@
70 82  
71 83 </el-descriptions-item>
72 84 </el-descriptions>
73   - <div style="margin-top: 1rem">
74   - <el-descriptions title="国标配置" border column="1">
75   - <template slot="extra">
76   - <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.sip)" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
77   - </template>
78   - <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">
79   - <template slot="label">
80   - {{ getNameFromKey(key) }}
81   - </template>
82   - {{ value }}
83   - </el-descriptions-item>
84   - </el-descriptions>
85 85 </div>
86 86 <div style="margin-top: 1rem">
87 87 <el-descriptions title="版本信息" border column="1">
... ...