Commit 5bcd8495e03b08ff417f74f816d20e028f9b1fe0

Authored by 648540858
1 parent b7635ec0

兼容海康不规范的xml,大幅度提高通道分页查询速度,优化节点的保活。

sql/mysql.sql
@@ -107,6 +107,7 @@ CREATE TABLE `device_channel` ( @@ -107,6 +107,7 @@ CREATE TABLE `device_channel` (
107 `certNum` varchar(50) DEFAULT NULL, 107 `certNum` varchar(50) DEFAULT NULL,
108 `certifiable` int(11) DEFAULT NULL, 108 `certifiable` int(11) DEFAULT NULL,
109 `errCode` int(11) DEFAULT NULL, 109 `errCode` int(11) DEFAULT NULL,
  110 + `subCount` int(11) DEFAULT 0,
110 `endTime` varchar(50) DEFAULT NULL, 111 `endTime` varchar(50) DEFAULT NULL,
111 `secrecy` varchar(50) DEFAULT NULL, 112 `secrecy` varchar(50) DEFAULT NULL,
112 `ipAddress` varchar(50) DEFAULT NULL, 113 `ipAddress` varchar(50) DEFAULT NULL,
sql/update.sql
1 -ALTER TABLE stream_proxy ADD status bit(1) not null;  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +ALTER TABLE stream_proxy ADD status bit(1) not null;
  3 +
  4 +# 去除子查询优化查询速度
  5 +alter table device_channel
  6 + add subCount int default 0 null;
  7 +
  8 +update device_channel dc set dc.subCount = (select te.count from (SELECT count(0) as count FROM device_channel WHERE parentId = dc.channelId) te)
3 \ No newline at end of file 9 \ No newline at end of file
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -11,7 +11,8 @@ import java.util.Date; @@ -11,7 +11,8 @@ import java.util.Date;
11 @Configuration("mediaConfig") 11 @Configuration("mediaConfig")
12 public class MediaConfig{ 12 public class MediaConfig{
13 13
14 - @Value("${media.id:}") 14 + // 修改必须配置,不再支持自动获取
  15 + @Value("${media.id}")
15 private String id; 16 private String id;
16 17
17 @Value("${media.ip}") 18 @Value("${media.ip}")
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -4,6 +4,7 @@ import gov.nist.javax.sip.SipProviderImpl; @@ -4,6 +4,7 @@ import gov.nist.javax.sip.SipProviderImpl;
4 import gov.nist.javax.sip.SipStackImpl; 4 import gov.nist.javax.sip.SipStackImpl;
5 import gov.nist.javax.sip.message.SIPRequest; 5 import gov.nist.javax.sip.message.SIPRequest;
6 import gov.nist.javax.sip.stack.SIPServerTransaction; 6 import gov.nist.javax.sip.stack.SIPServerTransaction;
  7 +import org.apache.commons.lang3.ArrayUtils;
7 import org.dom4j.Document; 8 import org.dom4j.Document;
8 import org.dom4j.DocumentException; 9 import org.dom4j.DocumentException;
9 import org.dom4j.Element; 10 import org.dom4j.Element;
@@ -25,7 +26,12 @@ import javax.sip.message.MessageFactory; @@ -25,7 +26,12 @@ import javax.sip.message.MessageFactory;
25 import javax.sip.message.Request; 26 import javax.sip.message.Request;
26 import javax.sip.message.Response; 27 import javax.sip.message.Response;
27 import java.io.ByteArrayInputStream; 28 import java.io.ByteArrayInputStream;
  29 +import java.nio.ByteBuffer;
  30 +import java.nio.charset.StandardCharsets;
28 import java.text.ParseException; 31 import java.text.ParseException;
  32 +import java.util.ArrayList;
  33 +import java.util.Arrays;
  34 +import java.util.List;
29 35
30 /** 36 /**
31 * @description:处理接收IPCamera发来的SIP协议请求消息 37 * @description:处理接收IPCamera发来的SIP协议请求消息
@@ -202,7 +208,32 @@ public abstract class SIPRequestProcessorParent { @@ -202,7 +208,32 @@ public abstract class SIPRequestProcessorParent {
202 Request request = evt.getRequest(); 208 Request request = evt.getRequest();
203 SAXReader reader = new SAXReader(); 209 SAXReader reader = new SAXReader();
204 reader.setEncoding(charset); 210 reader.setEncoding(charset);
205 - Document xml = reader.read(new ByteArrayInputStream(request.getRawContent())); 211 + // 对海康出现的未转义字符做处理。
  212 + String[] destStrArray = new String[]{"<",">","&","'","""};
  213 + char despChar = '&'; // 或许可扩展兼容其他字符
  214 + byte destBye = (byte) despChar;
  215 + List<Byte> result = new ArrayList<>();
  216 + byte[] rawContent = request.getRawContent();
  217 + for (int i = 0; i < rawContent.length; i++) {
  218 + if (rawContent[i] == destBye) {
  219 + boolean resul = false;
  220 + for (String destStr : destStrArray) {
  221 + if (i + destStr.length() <= rawContent.length) {
  222 + byte[] bytes = Arrays.copyOfRange(rawContent, i, i + destStr.length());
  223 + resul = resul || (Arrays.equals(bytes,destStr.getBytes()));
  224 + }
  225 + }
  226 + if (resul) {
  227 + result.add(rawContent[i]);
  228 + }
  229 + }else {
  230 + result.add(rawContent[i]);
  231 + }
  232 + }
  233 + Byte[] bytes = new Byte[0];
  234 + byte[] bytesResult = ArrayUtils.toPrimitive(result.toArray(bytes));
  235 +
  236 + Document xml = reader.read(new ByteArrayInputStream(bytesResult));
206 return xml.getRootElement(); 237 return xml.getRootElement();
207 } 238 }
208 239
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -27,6 +27,9 @@ public class ZLMRESTfulUtils { @@ -27,6 +27,9 @@ public class ZLMRESTfulUtils {
27 27
28 public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { 28 public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
29 OkHttpClient client = new OkHttpClient(); 29 OkHttpClient client = new OkHttpClient();
  30 + if (mediaServerItem == null) {
  31 + return null;
  32 + }
30 String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); 33 String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
31 JSONObject responseJSON = null; 34 JSONObject responseJSON = null;
32 35
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -63,10 +63,9 @@ public class ZLMRunner implements CommandLineRunner { @@ -63,10 +63,9 @@ public class ZLMRunner implements CommandLineRunner {
63 mediaServerService.addToDatabase(mediaConfig.getMediaSerItem()); 63 mediaServerService.addToDatabase(mediaConfig.getMediaSerItem());
64 }else { 64 }else {
65 MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem(); 65 MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
66 - mediaSerItem.setId(defaultMediaServer.getId());  
67 mediaServerService.updateToDatabase(mediaSerItem); 66 mediaServerService.updateToDatabase(mediaSerItem);
68 } 67 }
69 - 68 + mediaServerService.syncCatchFromDatabase();
70 // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 69 // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
71 hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null, 70 hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
72 (MediaServerItem mediaServerItem, JSONObject response)->{ 71 (MediaServerItem mediaServerItem, JSONObject response)->{
@@ -145,7 +144,6 @@ public class ZLMRunner implements CommandLineRunner { @@ -145,7 +144,6 @@ public class ZLMRunner implements CommandLineRunner {
145 JSONArray data = responseJSON.getJSONArray("data"); 144 JSONArray data = responseJSON.getJSONArray("data");
146 if (data != null && data.size() > 0) { 145 if (data != null && data.size() > 0) {
147 ZLMServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); 146 ZLMServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
148 - ZLMServerConfig.setIp(mediaServerItem.getIp());  
149 } 147 }
150 } else { 148 } else {
151 logger.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试", 149 logger.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试",
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java
@@ -65,7 +65,7 @@ public class ZLMKeepliveTimeoutListener extends RedisKeyExpirationEventMessageLi @@ -65,7 +65,7 @@ public class ZLMKeepliveTimeoutListener extends RedisKeyExpirationEventMessageLi
65 if (mediaServerConfig == null) { 65 if (mediaServerConfig == null) {
66 publisher.zlmOfflineEventPublish(mediaServerId); 66 publisher.zlmOfflineEventPublish(mediaServerId);
67 }else { 67 }else {
68 - logger.info("[zlm心跳到期]:{}验证后zlm仍在线,复心跳信息", mediaServerId); 68 + logger.info("[zlm心跳到期]:{}验证后zlm仍在线,复心跳信息", mediaServerId);
69 // 添加zlm信息 69 // 添加zlm信息
70 mediaServerService.updateMediaServerKeepalive(mediaServerId, mediaServerConfig); 70 mediaServerService.updateMediaServerKeepalive(mediaServerId, mediaServerConfig);
71 } 71 }
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -22,7 +22,7 @@ public interface IMediaServerService { @@ -22,7 +22,7 @@ public interface IMediaServerService {
22 22
23 MediaServerItem getOne(String generalMediaServerId); 23 MediaServerItem getOne(String generalMediaServerId);
24 24
25 - MediaServerItem getOneByHostAndPort(String host, int port); 25 + void syncCatchFromDatabase();
26 26
27 /** 27 /**
28 * 新的节点加入 28 * 新的节点加入
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -30,7 +30,11 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -30,7 +30,11 @@ import org.springframework.beans.factory.annotation.Autowired;
30 import org.springframework.beans.factory.annotation.Value; 30 import org.springframework.beans.factory.annotation.Value;
31 import org.springframework.boot.CommandLineRunner; 31 import org.springframework.boot.CommandLineRunner;
32 import org.springframework.core.annotation.Order; 32 import org.springframework.core.annotation.Order;
  33 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  34 +import org.springframework.security.core.parameters.P;
33 import org.springframework.stereotype.Service; 35 import org.springframework.stereotype.Service;
  36 +import org.springframework.transaction.TransactionDefinition;
  37 +import org.springframework.transaction.TransactionStatus;
34 import org.springframework.util.StringUtils; 38 import org.springframework.util.StringUtils;
35 39
36 import java.text.ParseException; 40 import java.text.ParseException;
@@ -65,6 +69,12 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -65,6 +69,12 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
65 private MediaServerMapper mediaServerMapper; 69 private MediaServerMapper mediaServerMapper;
66 70
67 @Autowired 71 @Autowired
  72 + DataSourceTransactionManager dataSourceTransactionManager;
  73 +
  74 + @Autowired
  75 + TransactionDefinition transactionDefinition;
  76 +
  77 + @Autowired
68 private VideoStreamSessionManager streamSession; 78 private VideoStreamSessionManager streamSession;
69 79
70 @Autowired 80 @Autowired
@@ -267,11 +277,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -267,11 +277,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
267 } 277 }
268 278
269 @Override 279 @Override
270 - public MediaServerItem getOneByHostAndPort(String host, int port) {  
271 - return mediaServerMapper.queryOneByHostAndPort(host, port);  
272 - }  
273 -  
274 - @Override  
275 public MediaServerItem getDefaultMediaServer() { 280 public MediaServerItem getDefaultMediaServer() {
276 return mediaServerMapper.queryDefault(); 281 return mediaServerMapper.queryDefault();
277 } 282 }
@@ -323,7 +328,22 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -323,7 +328,22 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
323 328
324 @Override 329 @Override
325 public int updateToDatabase(MediaServerItem mediaSerItem) { 330 public int updateToDatabase(MediaServerItem mediaSerItem) {
326 - return mediaServerMapper.update(mediaSerItem); 331 + int result = 0;
  332 + if (mediaSerItem.isDefaultServer()) {
  333 + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
  334 + int delResult = mediaServerMapper.delDefault();
  335 + if (delResult == 0) {
  336 + logger.error("移除数据库默认zlm节点失败");
  337 + //事务回滚
  338 + dataSourceTransactionManager.rollback(transactionStatus);
  339 + return 0;
  340 + }
  341 + result = mediaServerMapper.add(mediaSerItem);
  342 + dataSourceTransactionManager.commit(transactionStatus); //手动提交
  343 + }else {
  344 + result = mediaServerMapper.update(mediaSerItem);
  345 + }
  346 + return result;
327 } 347 }
328 348
329 /** 349 /**
@@ -332,15 +352,13 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -332,15 +352,13 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
332 */ 352 */
333 @Override 353 @Override
334 public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { 354 public void zlmServerOnline(ZLMServerConfig zlmServerConfig) {
335 - logger.info("[ ZLM:{} ]-[ {}:{} ]连接", 355 + logger.info("[ ZLM:{} ]-[ {}:{} ]正在连接",
336 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); 356 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
337 357
338 MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); 358 MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
339 if (serverItem == null) { 359 if (serverItem == null) {
340 - serverItem = mediaServerMapper.queryOneByHostAndPort(zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());  
341 - }  
342 - if (serverItem == null) {  
343 - logger.warn("[未注册的zlm] 拒接接入:来自{}:{}", zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() ); 360 + logger.warn("[未注册的zlm] 拒接接入:{}来自{}:{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
  361 + logger.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致");
344 return; 362 return;
345 } 363 }
346 serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval()); 364 serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval());
@@ -368,11 +386,10 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -368,11 +386,10 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
368 serverItem.setStatus(true); 386 serverItem.setStatus(true);
369 387
370 if (StringUtils.isEmpty(serverItem.getId())) { 388 if (StringUtils.isEmpty(serverItem.getId())) {
371 - serverItem.setId(zlmServerConfig.getGeneralMediaServerId());  
372 - mediaServerMapper.updateByHostAndPort(serverItem);  
373 - }else {  
374 - mediaServerMapper.update(serverItem); 389 + logger.warn("[未注册的zlm] serverItem缺少ID, 无法接入:{}:{}", zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
  390 + return;
375 } 391 }
  392 + mediaServerMapper.update(serverItem);
376 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); 393 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId();
377 if (redisUtil.get(key) == null) { 394 if (redisUtil.get(key) == null) {
378 SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain()); 395 SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain());
@@ -387,7 +404,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -387,7 +404,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
387 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); 404 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
388 405
389 publisher.zlmOnlineEventPublish(serverItem.getId()); 406 publisher.zlmOnlineEventPublish(serverItem.getId());
390 - 407 + logger.info("[ ZLM:{} ]-[ {}:{} ]连接成功",
  408 + zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
391 } 409 }
392 410
393 411
@@ -464,7 +482,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -464,7 +482,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
464 */ 482 */
465 @Override 483 @Override
466 public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { 484 public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) {
467 - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm", 485 + logger.info("[ ZLM:{} ]-[ {}:{} ]正在设置zlm",
468 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); 486 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
469 String protocol = sslEnabled ? "https" : "http"; 487 String protocol = sslEnabled ? "https" : "http";
470 String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); 488 String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
@@ -601,4 +619,21 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -601,4 +619,21 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
601 int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2; 619 int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2;
602 redisUtil.set(key, data, hookAliveInterval); 620 redisUtil.set(key, data, hookAliveInterval);
603 } 621 }
  622 +
  623 + @Override
  624 + public void syncCatchFromDatabase() {
  625 + List<MediaServerItem> allInCatch = getAll();
  626 + List<MediaServerItem> allInDatabase = mediaServerMapper.queryAll();
  627 + Map<String, MediaServerItem> mediaServerItemMap = new HashMap<>();
  628 +
  629 + for (MediaServerItem mediaServerItem : allInDatabase) {
  630 + mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem);
  631 + }
  632 + for (MediaServerItem mediaServerItem : allInCatch) {
  633 + if (mediaServerItemMap.get(mediaServerItem) == null) {
  634 + delete(mediaServerItem.getId());
  635 + }
  636 + }
  637 + }
  638 +
604 } 639 }
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -398,12 +398,6 @@ public interface IVideoManagerStorager { @@ -398,12 +398,6 @@ public interface IVideoManagerStorager {
398 void updateParentPlatformStatus(String platformGbID, boolean online); 398 void updateParentPlatformStatus(String platformGbID, boolean online);
399 399
400 /** 400 /**
401 - * 更新媒体节点  
402 - * @param mediaServerItem  
403 - */  
404 - void updateMediaServer(MediaServerItem mediaServerItem);  
405 -  
406 - /**  
407 * 根据媒体ID获取启用/不启用的代理列表 401 * 根据媒体ID获取启用/不启用的代理列表
408 * @param id 媒体ID 402 * @param id 媒体ID
409 * @param enable 启用/不启用 403 * @param enable 启用/不启用
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -56,27 +56,21 @@ public interface DeviceChannelMapper { @@ -56,27 +56,21 @@ public interface DeviceChannelMapper {
56 56
57 @Select(value = {" <script>" + 57 @Select(value = {" <script>" +
58 "SELECT " + 58 "SELECT " +
59 - "dc1.*, " +  
60 - "COUNT(dc2.channelId) as subCount " + 59 + "dc.* " +
61 "from " + 60 "from " +
62 - "device_channel dc1 " +  
63 - "left join device_channel dc2 on " +  
64 - "dc1.channelId = dc2.parentId " + 61 + "device_channel dc " +
65 "WHERE " + 62 "WHERE " +
66 - "dc1.deviceId = #{deviceId} " +  
67 - " <if test='query != null'> AND (dc1.channelId LIKE '%${query}%' OR dc1.name LIKE '%${query}%' OR dc1.name LIKE '%${query}%')</if> " +  
68 - " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " +  
69 - " <if test='online == true' > AND dc1.status=1</if>" +  
70 - " <if test='online == false' > AND dc1.status=0</if>" +  
71 - " <if test='hasSubChannel == true' > AND subCount >0</if>" +  
72 - " <if test='hasSubChannel == false' > AND subCount=0</if>" +  
73 - "GROUP BY dc1.channelId " + 63 + "dc.deviceId = #{deviceId} " +
  64 + " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " +
  65 + " <if test='parentChannelId != null'> AND dc.parentId=#{parentChannelId} </if> " +
  66 + " <if test='online == true' > AND dc.status=1</if>" +
  67 + " <if test='online == false' > AND dc.status=0</if>" +
  68 + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" +
  69 + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" +
  70 + "GROUP BY dc.channelId " +
74 " </script>"}) 71 " </script>"})
75 List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online); 72 List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online);
76 73
77 - @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId}")  
78 - List<DeviceChannel> queryChannelsByDeviceId(String deviceId);  
79 -  
80 @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") 74 @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}")
81 DeviceChannel queryChannel(String deviceId, String channelId); 75 DeviceChannel queryChannel(String deviceId, String channelId);
82 76
@@ -100,7 +94,7 @@ public interface DeviceChannelMapper { @@ -100,7 +94,7 @@ public interface DeviceChannelMapper {
100 "dc.name, " + 94 "dc.name, " +
101 "de.manufacturer, " + 95 "de.manufacturer, " +
102 "de.hostAddress, " + 96 "de.hostAddress, " +
103 - "(SELECT count(0) FROM device_channel WHERE parentId = dc.channelId) as subCount, " + 97 + "dc.subCount, " +
104 "pgc.platformId as platformId, " + 98 "pgc.platformId as platformId, " +
105 "pgc.catalogId as catalogId " + 99 "pgc.catalogId as catalogId " +
106 "FROM device_channel dc " + 100 "FROM device_channel dc " +
@@ -130,13 +124,13 @@ public interface DeviceChannelMapper { @@ -130,13 +124,13 @@ public interface DeviceChannelMapper {
130 124
131 @Insert("<script> " + 125 @Insert("<script> " +
132 "insert into device_channel " + 126 "insert into device_channel " +
133 - "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, " + 127 + "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " +
134 " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + 128 " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
135 " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, createTime, updateTime) " + 129 " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, createTime, updateTime) " +
136 "values " + 130 "values " +
137 "<foreach collection='addChannels' index='index' item='item' separator=','> " + 131 "<foreach collection='addChannels' index='index' item='item' separator=','> " +
138 "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " + 132 "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " +
139 - "'${item.owner}', '${item.civilCode}', '${item.block}'," + 133 + "'${item.owner}', '${item.civilCode}', '${item.block}',${item.subCount}," +
140 "'${item.address}', ${item.parental}, '${item.parentId}', ${item.safetyWay}, ${item.registerWay}, " + 134 "'${item.address}', ${item.parental}, '${item.parentId}', ${item.safetyWay}, ${item.registerWay}, " +
141 "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " + 135 "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " +
142 "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " + 136 "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " +
@@ -156,6 +150,7 @@ public interface DeviceChannelMapper { @@ -156,6 +150,7 @@ public interface DeviceChannelMapper {
156 "<if test='item.owner != null'>, owner='${item.owner}'</if>" + 150 "<if test='item.owner != null'>, owner='${item.owner}'</if>" +
157 "<if test='item.civilCode != null'>, civilCode='${item.civilCode}'</if>" + 151 "<if test='item.civilCode != null'>, civilCode='${item.civilCode}'</if>" +
158 "<if test='item.block != null'>, block='${item.block}'</if>" + 152 "<if test='item.block != null'>, block='${item.block}'</if>" +
  153 + "<if test='item.subCount != null'>, block=${item.subCount}</if>" +
159 "<if test='item.address != null'>, address='${item.address}'</if>" + 154 "<if test='item.address != null'>, address='${item.address}'</if>" +
160 "<if test='item.parental != null'>, parental=${item.parental}</if>" + 155 "<if test='item.parental != null'>, parental=${item.parental}</if>" +
161 "<if test='item.parentId != null'>, parentId='${item.parentId}'</if>" + 156 "<if test='item.parentId != null'>, parentId='${item.parentId}'</if>" +
@@ -182,21 +177,17 @@ public interface DeviceChannelMapper { @@ -182,21 +177,17 @@ public interface DeviceChannelMapper {
182 177
183 @Select(value = {" <script>" + 178 @Select(value = {" <script>" +
184 "SELECT " + 179 "SELECT " +
185 - "dc1.*, " +  
186 - "COUNT(dc2.channelId) as subCount " + 180 + "dc1.* " +
187 "from " + 181 "from " +
188 "device_channel dc1 " + 182 "device_channel dc1 " +
189 - "left join device_channel dc2 on " +  
190 - "dc1.channelId = dc2.parentId " +  
191 "WHERE " + 183 "WHERE " +
192 "dc1.deviceId = #{deviceId} " + 184 "dc1.deviceId = #{deviceId} " +
193 " <if test='query != null'> AND (dc1.channelId LIKE '%${query}%' OR dc1.name LIKE '%${query}%' OR dc1.name LIKE '%${query}%')</if> " + 185 " <if test='query != null'> AND (dc1.channelId LIKE '%${query}%' OR dc1.name LIKE '%${query}%' OR dc1.name LIKE '%${query}%')</if> " +
194 " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " + 186 " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " +
195 " <if test='online == true' > AND dc1.status=1</if>" + 187 " <if test='online == true' > AND dc1.status=1</if>" +
196 " <if test='online == false' > AND dc1.status=0</if>" + 188 " <if test='online == false' > AND dc1.status=0</if>" +
197 - " <if test='hasSubChannel == true' > AND subCount >0</if>" +  
198 - " <if test='hasSubChannel == false' > AND subCount=0</if>" +  
199 - "GROUP BY dc1.channelId " + 189 + " <if test='hasSubChannel == true' > AND dc1.subCount >0</if>" +
  190 + " <if test='hasSubChannel == false' > AND dc1.subCount=0</if>" +
200 "ORDER BY dc1.channelId ASC " + 191 "ORDER BY dc1.channelId ASC " +
201 "Limit #{limit} OFFSET #{start}" + 192 "Limit #{limit} OFFSET #{start}" +
202 " </script>"}) 193 " </script>"})
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
1 package com.genersoft.iot.vmp.storager.dao; 1 package com.genersoft.iot.vmp.storager.dao;
2 2
3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
4 -import org.apache.ibatis.annotations.Insert;  
5 -import org.apache.ibatis.annotations.Mapper;  
6 -import org.apache.ibatis.annotations.Select;  
7 -import org.apache.ibatis.annotations.Update; 4 +import org.apache.ibatis.annotations.*;
8 import org.springframework.stereotype.Repository; 5 import org.springframework.stereotype.Repository;
9 6
10 import java.util.List; 7 import java.util.List;
@@ -122,14 +119,14 @@ public interface MediaServerMapper { @@ -122,14 +119,14 @@ public interface MediaServerMapper {
122 @Select("SELECT * FROM media_server") 119 @Select("SELECT * FROM media_server")
123 List<MediaServerItem> queryAll(); 120 List<MediaServerItem> queryAll();
124 121
125 - @Select("DELETE FROM media_server WHERE id='${id}'") 122 + @Delete("DELETE FROM media_server WHERE id='${id}'")
126 void delOne(String id); 123 void delOne(String id);
127 124
128 @Select("DELETE FROM media_server WHERE ip='${host}' and httpPort=${port}") 125 @Select("DELETE FROM media_server WHERE ip='${host}' and httpPort=${port}")
129 void delOneByIPAndPort(String host, int port); 126 void delOneByIPAndPort(String host, int port);
130 127
131 - @Select("DELETE FROM media_server WHERE defaultServer=1;")  
132 - void delDefault(); 128 + @Delete("DELETE FROM media_server WHERE defaultServer=1")
  129 + int delDefault();
133 130
134 @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}") 131 @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}")
135 MediaServerItem queryOneByHostAndPort(String host, int port); 132 MediaServerItem queryOneByHostAndPort(String host, int port);
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
@@ -174,7 +174,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -174,7 +174,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
174 List<DeviceChannel> updateChannels = new ArrayList<>(); 174 List<DeviceChannel> updateChannels = new ArrayList<>();
175 HashMap<String, DeviceChannel> channelsInStore = new HashMap<>(); 175 HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
176 if (channels != null && channels.size() > 0) { 176 if (channels != null && channels.size() > 0) {
177 - List<DeviceChannel> channelList = deviceChannelMapper.queryChannelsByDeviceId(deviceId); 177 + List<DeviceChannel> channelList = deviceChannelMapper.queryChannels(deviceId, null, null, null, null);
178 if (channelList.size() == 0) { 178 if (channelList.size() == 0) {
179 for (DeviceChannel channel : channels) { 179 for (DeviceChannel channel : channels) {
180 channel.setDeviceId(deviceId); 180 channel.setDeviceId(deviceId);
@@ -239,6 +239,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -239,6 +239,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
239 // 数据去重 239 // 数据去重
240 List<DeviceChannel> channels = new ArrayList<>(); 240 List<DeviceChannel> channels = new ArrayList<>();
241 StringBuilder stringBuilder = new StringBuilder(); 241 StringBuilder stringBuilder = new StringBuilder();
  242 + Map<String, Integer> subContMap = new HashMap<>();
242 if (deviceChannelList.size() > 1) { 243 if (deviceChannelList.size() > 1) {
243 // 数据去重 244 // 数据去重
244 Set<String> gbIdSet = new HashSet<>(); 245 Set<String> gbIdSet = new HashSet<>();
@@ -246,10 +247,26 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -246,10 +247,26 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
246 if (!gbIdSet.contains(deviceChannel.getChannelId())) { 247 if (!gbIdSet.contains(deviceChannel.getChannelId())) {
247 gbIdSet.add(deviceChannel.getChannelId()); 248 gbIdSet.add(deviceChannel.getChannelId());
248 channels.add(deviceChannel); 249 channels.add(deviceChannel);
  250 + if (!StringUtils.isEmpty(deviceChannel.getParentId())) {
  251 + if (subContMap.get(deviceChannel.getParentId()) == null) {
  252 + subContMap.put(deviceChannel.getParentId(), 1);
  253 + }else {
  254 + Integer count = subContMap.get(deviceChannel.getParentId());
  255 + subContMap.put(deviceChannel.getParentId(), count++);
  256 + }
  257 + }
249 }else { 258 }else {
250 stringBuilder.append(deviceChannel.getChannelId() + ","); 259 stringBuilder.append(deviceChannel.getChannelId() + ",");
251 } 260 }
252 } 261 }
  262 + if (channels.size() > 0) {
  263 + for (DeviceChannel channel : channels) {
  264 + if (subContMap.get(channel.getChannelId()) != null){
  265 + channel.setSubCount(subContMap.get(channel.getChannelId()));
  266 + }
  267 + }
  268 + }
  269 +
253 }else { 270 }else {
254 channels = deviceChannelList; 271 channels = deviceChannelList;
255 } 272 }
@@ -855,18 +872,6 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -855,18 +872,6 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
855 } 872 }
856 873
857 @Override 874 @Override
858 - public void updateMediaServer(MediaServerItem mediaServerItem) {  
859 - String now = this.format.format(System.currentTimeMillis());  
860 - mediaServerItem.setUpdateTime(now);  
861 - if (mediaServerMapper.queryOne(mediaServerItem.getId()) != null) {  
862 - mediaServerMapper.update(mediaServerItem);  
863 - }else {  
864 - mediaServerItem.setCreateTime(now);  
865 - mediaServerMapper.add(mediaServerItem);  
866 - }  
867 - }  
868 -  
869 - @Override  
870 public List<StreamProxyItem> getStreamProxyListForEnableInMediaServer(String id, boolean enable, boolean status) { 875 public List<StreamProxyItem> getStreamProxyListForEnableInMediaServer(String id, boolean enable, boolean status) {
871 return streamProxyMapper.selectForEnableInMediaServer(id, enable, status); 876 return streamProxyMapper.selectForEnableInMediaServer(id, enable, status);
872 } 877 }
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -58,8 +58,6 @@ public class ServerController { @@ -58,8 +58,6 @@ public class ServerController {
58 @GetMapping(value = "/media_server/list") 58 @GetMapping(value = "/media_server/list")
59 @ResponseBody 59 @ResponseBody
60 public WVPResult<List<MediaServerItem>> getMediaServerList(boolean detail){ 60 public WVPResult<List<MediaServerItem>> getMediaServerList(boolean detail){
61 - List<MediaServerItem> all = mediaServerService.getAll();  
62 -  
63 WVPResult<List<MediaServerItem>> result = new WVPResult<>(); 61 WVPResult<List<MediaServerItem>> result = new WVPResult<>();
64 result.setCode(0); 62 result.setCode(0);
65 result.setMsg("success"); 63 result.setMsg("success");
src/main/resources/all-application.yml
@@ -93,7 +93,7 @@ sip: @@ -93,7 +93,7 @@ sip:
93 93
94 #zlm 默认服务器配置 94 #zlm 默认服务器配置
95 media: 95 media:
96 - # [可选] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId 96 + # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId
97 id: 97 id:
98 # [必须修改] zlm服务器的内网IP 98 # [必须修改] zlm服务器的内网IP
99 ip: 192.168.0.100 99 ip: 192.168.0.100
src/main/resources/application-dev.yml
@@ -48,6 +48,8 @@ sip: @@ -48,6 +48,8 @@ sip:
48 48
49 #zlm 默认服务器配置 49 #zlm 默认服务器配置
50 media: 50 media:
  51 + # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId
  52 + id:
51 # [必须修改] zlm服务器的内网IP 53 # [必须修改] zlm服务器的内网IP
52 ip: 54 ip:
53 # [必须修改] zlm服务器的http.port 55 # [必须修改] zlm服务器的http.port
src/main/resources/application-docker.yml
@@ -48,6 +48,8 @@ sip: @@ -48,6 +48,8 @@ sip:
48 48
49 #zlm 默认服务器配置 49 #zlm 默认服务器配置
50 media: 50 media:
  51 + # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId
  52 + id:
51 # [必须修改] zlm服务器的内网IP 53 # [必须修改] zlm服务器的内网IP
52 ip: ${ZLM_HOST:127.0.0.1} 54 ip: ${ZLM_HOST:127.0.0.1}
53 # [必须修改] zlm服务器的http.port 55 # [必须修改] zlm服务器的http.port
web_src/src/components/channelList.vue
@@ -84,7 +84,7 @@ @@ -84,7 +84,7 @@
84 <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> --> 84 <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->
85 <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button> 85 <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
86 <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button> 86 <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button>
87 - <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.parental == 1" @click="changeSubchannel(scope.row)">查看</el-button> 87 + <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0" @click="changeSubchannel(scope.row)">查看</el-button>
88 <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button> 88 <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button>
89 <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> --> 89 <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
90 </el-button-group> 90 </el-button-group>