Commit 5bcd8495e03b08ff417f74f816d20e028f9b1fe0
1 parent
b7635ec0
兼容海康不规范的xml,大幅度提高通道分页查询速度,优化节点的保活。
Showing
18 changed files
with
145 additions
and
81 deletions
sql/mysql.sql
| ... | ... | @@ -107,6 +107,7 @@ CREATE TABLE `device_channel` ( |
| 107 | 107 | `certNum` varchar(50) DEFAULT NULL, |
| 108 | 108 | `certifiable` int(11) DEFAULT NULL, |
| 109 | 109 | `errCode` int(11) DEFAULT NULL, |
| 110 | + `subCount` int(11) DEFAULT 0, | |
| 110 | 111 | `endTime` varchar(50) DEFAULT NULL, |
| 111 | 112 | `secrecy` varchar(50) DEFAULT NULL, |
| 112 | 113 | `ipAddress` varchar(50) DEFAULT NULL, | ... | ... |
sql/update.sql
| 1 | -ALTER TABLE stream_proxy ADD status bit(1) not null; | |
| 2 | 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 | 9 | \ No newline at end of file | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
| ... | ... | @@ -4,6 +4,7 @@ import gov.nist.javax.sip.SipProviderImpl; |
| 4 | 4 | import gov.nist.javax.sip.SipStackImpl; |
| 5 | 5 | import gov.nist.javax.sip.message.SIPRequest; |
| 6 | 6 | import gov.nist.javax.sip.stack.SIPServerTransaction; |
| 7 | +import org.apache.commons.lang3.ArrayUtils; | |
| 7 | 8 | import org.dom4j.Document; |
| 8 | 9 | import org.dom4j.DocumentException; |
| 9 | 10 | import org.dom4j.Element; |
| ... | ... | @@ -25,7 +26,12 @@ import javax.sip.message.MessageFactory; |
| 25 | 26 | import javax.sip.message.Request; |
| 26 | 27 | import javax.sip.message.Response; |
| 27 | 28 | import java.io.ByteArrayInputStream; |
| 29 | +import java.nio.ByteBuffer; | |
| 30 | +import java.nio.charset.StandardCharsets; | |
| 28 | 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 | 37 | * @description:处理接收IPCamera发来的SIP协议请求消息 |
| ... | ... | @@ -202,7 +208,32 @@ public abstract class SIPRequestProcessorParent { |
| 202 | 208 | Request request = evt.getRequest(); |
| 203 | 209 | SAXReader reader = new SAXReader(); |
| 204 | 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 | 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 | 27 | |
| 28 | 28 | public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { |
| 29 | 29 | OkHttpClient client = new OkHttpClient(); |
| 30 | + if (mediaServerItem == null) { | |
| 31 | + return null; | |
| 32 | + } | |
| 30 | 33 | String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); |
| 31 | 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 | 63 | mediaServerService.addToDatabase(mediaConfig.getMediaSerItem()); |
| 64 | 64 | }else { |
| 65 | 65 | MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem(); |
| 66 | - mediaSerItem.setId(defaultMediaServer.getId()); | |
| 67 | 66 | mediaServerService.updateToDatabase(mediaSerItem); |
| 68 | 67 | } |
| 69 | - | |
| 68 | + mediaServerService.syncCatchFromDatabase(); | |
| 70 | 69 | // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 |
| 71 | 70 | hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null, |
| 72 | 71 | (MediaServerItem mediaServerItem, JSONObject response)->{ |
| ... | ... | @@ -145,7 +144,6 @@ public class ZLMRunner implements CommandLineRunner { |
| 145 | 144 | JSONArray data = responseJSON.getJSONArray("data"); |
| 146 | 145 | if (data != null && data.size() > 0) { |
| 147 | 146 | ZLMServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); |
| 148 | - ZLMServerConfig.setIp(mediaServerItem.getIp()); | |
| 149 | 147 | } |
| 150 | 148 | } else { |
| 151 | 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 | 65 | if (mediaServerConfig == null) { |
| 66 | 66 | publisher.zlmOfflineEventPublish(mediaServerId); |
| 67 | 67 | }else { |
| 68 | - logger.info("[zlm心跳到期]:{}验证后zlm仍在线,回复心跳信息", mediaServerId); | |
| 68 | + logger.info("[zlm心跳到期]:{}验证后zlm仍在线,恢复心跳信息", mediaServerId); | |
| 69 | 69 | // 添加zlm信息 |
| 70 | 70 | mediaServerService.updateMediaServerKeepalive(mediaServerId, mediaServerConfig); |
| 71 | 71 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| ... | ... | @@ -30,7 +30,11 @@ import org.springframework.beans.factory.annotation.Autowired; |
| 30 | 30 | import org.springframework.beans.factory.annotation.Value; |
| 31 | 31 | import org.springframework.boot.CommandLineRunner; |
| 32 | 32 | import org.springframework.core.annotation.Order; |
| 33 | +import org.springframework.jdbc.datasource.DataSourceTransactionManager; | |
| 34 | +import org.springframework.security.core.parameters.P; | |
| 33 | 35 | import org.springframework.stereotype.Service; |
| 36 | +import org.springframework.transaction.TransactionDefinition; | |
| 37 | +import org.springframework.transaction.TransactionStatus; | |
| 34 | 38 | import org.springframework.util.StringUtils; |
| 35 | 39 | |
| 36 | 40 | import java.text.ParseException; |
| ... | ... | @@ -65,6 +69,12 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 65 | 69 | private MediaServerMapper mediaServerMapper; |
| 66 | 70 | |
| 67 | 71 | @Autowired |
| 72 | + DataSourceTransactionManager dataSourceTransactionManager; | |
| 73 | + | |
| 74 | + @Autowired | |
| 75 | + TransactionDefinition transactionDefinition; | |
| 76 | + | |
| 77 | + @Autowired | |
| 68 | 78 | private VideoStreamSessionManager streamSession; |
| 69 | 79 | |
| 70 | 80 | @Autowired |
| ... | ... | @@ -267,11 +277,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 267 | 277 | } |
| 268 | 278 | |
| 269 | 279 | @Override |
| 270 | - public MediaServerItem getOneByHostAndPort(String host, int port) { | |
| 271 | - return mediaServerMapper.queryOneByHostAndPort(host, port); | |
| 272 | - } | |
| 273 | - | |
| 274 | - @Override | |
| 275 | 280 | public MediaServerItem getDefaultMediaServer() { |
| 276 | 281 | return mediaServerMapper.queryDefault(); |
| 277 | 282 | } |
| ... | ... | @@ -323,7 +328,22 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 323 | 328 | |
| 324 | 329 | @Override |
| 325 | 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 | 352 | */ |
| 333 | 353 | @Override |
| 334 | 354 | public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { |
| 335 | - logger.info("[ ZLM:{} ]-[ {}:{} ]已连接", | |
| 355 | + logger.info("[ ZLM:{} ]-[ {}:{} ]正在连接", | |
| 336 | 356 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
| 337 | 357 | |
| 338 | 358 | MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); |
| 339 | 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 | 362 | return; |
| 345 | 363 | } |
| 346 | 364 | serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval()); |
| ... | ... | @@ -368,11 +386,10 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 368 | 386 | serverItem.setStatus(true); |
| 369 | 387 | |
| 370 | 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 | 393 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); |
| 377 | 394 | if (redisUtil.get(key) == null) { |
| 378 | 395 | SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain()); |
| ... | ... | @@ -387,7 +404,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 387 | 404 | setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); |
| 388 | 405 | |
| 389 | 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 | 482 | */ |
| 465 | 483 | @Override |
| 466 | 484 | public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { |
| 467 | - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm", | |
| 485 | + logger.info("[ ZLM:{} ]-[ {}:{} ]正在设置zlm", | |
| 468 | 486 | mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); |
| 469 | 487 | String protocol = sslEnabled ? "https" : "http"; |
| 470 | 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 | 619 | int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2; |
| 602 | 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 | 398 | void updateParentPlatformStatus(String platformGbID, boolean online); |
| 399 | 399 | |
| 400 | 400 | /** |
| 401 | - * 更新媒体节点 | |
| 402 | - * @param mediaServerItem | |
| 403 | - */ | |
| 404 | - void updateMediaServer(MediaServerItem mediaServerItem); | |
| 405 | - | |
| 406 | - /** | |
| 407 | 401 | * 根据媒体ID获取启用/不启用的代理列表 |
| 408 | 402 | * @param id 媒体ID |
| 409 | 403 | * @param enable 启用/不启用 | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
| ... | ... | @@ -56,27 +56,21 @@ public interface DeviceChannelMapper { |
| 56 | 56 | |
| 57 | 57 | @Select(value = {" <script>" + |
| 58 | 58 | "SELECT " + |
| 59 | - "dc1.*, " + | |
| 60 | - "COUNT(dc2.channelId) as subCount " + | |
| 59 | + "dc.* " + | |
| 61 | 60 | "from " + |
| 62 | - "device_channel dc1 " + | |
| 63 | - "left join device_channel dc2 on " + | |
| 64 | - "dc1.channelId = dc2.parentId " + | |
| 61 | + "device_channel dc " + | |
| 65 | 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 | 71 | " </script>"}) |
| 75 | 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 | 74 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") |
| 81 | 75 | DeviceChannel queryChannel(String deviceId, String channelId); |
| 82 | 76 | |
| ... | ... | @@ -100,7 +94,7 @@ public interface DeviceChannelMapper { |
| 100 | 94 | "dc.name, " + |
| 101 | 95 | "de.manufacturer, " + |
| 102 | 96 | "de.hostAddress, " + |
| 103 | - "(SELECT count(0) FROM device_channel WHERE parentId = dc.channelId) as subCount, " + | |
| 97 | + "dc.subCount, " + | |
| 104 | 98 | "pgc.platformId as platformId, " + |
| 105 | 99 | "pgc.catalogId as catalogId " + |
| 106 | 100 | "FROM device_channel dc " + |
| ... | ... | @@ -130,13 +124,13 @@ public interface DeviceChannelMapper { |
| 130 | 124 | |
| 131 | 125 | @Insert("<script> " + |
| 132 | 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 | 128 | " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + |
| 135 | 129 | " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, createTime, updateTime) " + |
| 136 | 130 | "values " + |
| 137 | 131 | "<foreach collection='addChannels' index='index' item='item' separator=','> " + |
| 138 | 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 | 134 | "'${item.address}', ${item.parental}, '${item.parentId}', ${item.safetyWay}, ${item.registerWay}, " + |
| 141 | 135 | "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " + |
| 142 | 136 | "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " + |
| ... | ... | @@ -156,6 +150,7 @@ public interface DeviceChannelMapper { |
| 156 | 150 | "<if test='item.owner != null'>, owner='${item.owner}'</if>" + |
| 157 | 151 | "<if test='item.civilCode != null'>, civilCode='${item.civilCode}'</if>" + |
| 158 | 152 | "<if test='item.block != null'>, block='${item.block}'</if>" + |
| 153 | + "<if test='item.subCount != null'>, block=${item.subCount}</if>" + | |
| 159 | 154 | "<if test='item.address != null'>, address='${item.address}'</if>" + |
| 160 | 155 | "<if test='item.parental != null'>, parental=${item.parental}</if>" + |
| 161 | 156 | "<if test='item.parentId != null'>, parentId='${item.parentId}'</if>" + |
| ... | ... | @@ -182,21 +177,17 @@ public interface DeviceChannelMapper { |
| 182 | 177 | |
| 183 | 178 | @Select(value = {" <script>" + |
| 184 | 179 | "SELECT " + |
| 185 | - "dc1.*, " + | |
| 186 | - "COUNT(dc2.channelId) as subCount " + | |
| 180 | + "dc1.* " + | |
| 187 | 181 | "from " + |
| 188 | 182 | "device_channel dc1 " + |
| 189 | - "left join device_channel dc2 on " + | |
| 190 | - "dc1.channelId = dc2.parentId " + | |
| 191 | 183 | "WHERE " + |
| 192 | 184 | "dc1.deviceId = #{deviceId} " + |
| 193 | 185 | " <if test='query != null'> AND (dc1.channelId LIKE '%${query}%' OR dc1.name LIKE '%${query}%' OR dc1.name LIKE '%${query}%')</if> " + |
| 194 | 186 | " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " + |
| 195 | 187 | " <if test='online == true' > AND dc1.status=1</if>" + |
| 196 | 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 | 191 | "ORDER BY dc1.channelId ASC " + |
| 201 | 192 | "Limit #{limit} OFFSET #{start}" + |
| 202 | 193 | " </script>"}) | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
| 1 | 1 | package com.genersoft.iot.vmp.storager.dao; |
| 2 | 2 | |
| 3 | 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 | 5 | import org.springframework.stereotype.Repository; |
| 9 | 6 | |
| 10 | 7 | import java.util.List; |
| ... | ... | @@ -122,14 +119,14 @@ public interface MediaServerMapper { |
| 122 | 119 | @Select("SELECT * FROM media_server") |
| 123 | 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 | 123 | void delOne(String id); |
| 127 | 124 | |
| 128 | 125 | @Select("DELETE FROM media_server WHERE ip='${host}' and httpPort=${port}") |
| 129 | 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 | 131 | @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}") |
| 135 | 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 | 174 | List<DeviceChannel> updateChannels = new ArrayList<>(); |
| 175 | 175 | HashMap<String, DeviceChannel> channelsInStore = new HashMap<>(); |
| 176 | 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 | 178 | if (channelList.size() == 0) { |
| 179 | 179 | for (DeviceChannel channel : channels) { |
| 180 | 180 | channel.setDeviceId(deviceId); |
| ... | ... | @@ -239,6 +239,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { |
| 239 | 239 | // 数据去重 |
| 240 | 240 | List<DeviceChannel> channels = new ArrayList<>(); |
| 241 | 241 | StringBuilder stringBuilder = new StringBuilder(); |
| 242 | + Map<String, Integer> subContMap = new HashMap<>(); | |
| 242 | 243 | if (deviceChannelList.size() > 1) { |
| 243 | 244 | // 数据去重 |
| 244 | 245 | Set<String> gbIdSet = new HashSet<>(); |
| ... | ... | @@ -246,10 +247,26 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { |
| 246 | 247 | if (!gbIdSet.contains(deviceChannel.getChannelId())) { |
| 247 | 248 | gbIdSet.add(deviceChannel.getChannelId()); |
| 248 | 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 | 258 | }else { |
| 250 | 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 | 270 | }else { |
| 254 | 271 | channels = deviceChannelList; |
| 255 | 272 | } |
| ... | ... | @@ -855,18 +872,6 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { |
| 855 | 872 | } |
| 856 | 873 | |
| 857 | 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 | 875 | public List<StreamProxyItem> getStreamProxyListForEnableInMediaServer(String id, boolean enable, boolean status) { |
| 871 | 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 | 58 | @GetMapping(value = "/media_server/list") |
| 59 | 59 | @ResponseBody |
| 60 | 60 | public WVPResult<List<MediaServerItem>> getMediaServerList(boolean detail){ |
| 61 | - List<MediaServerItem> all = mediaServerService.getAll(); | |
| 62 | - | |
| 63 | 61 | WVPResult<List<MediaServerItem>> result = new WVPResult<>(); |
| 64 | 62 | result.setCode(0); |
| 65 | 63 | result.setMsg("success"); | ... | ... |
src/main/resources/all-application.yml
src/main/resources/application-dev.yml
src/main/resources/application-docker.yml
web_src/src/components/channelList.vue
| ... | ... | @@ -84,7 +84,7 @@ |
| 84 | 84 | <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> --> |
| 85 | 85 | <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button> |
| 86 | 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 | 88 | <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button> |
| 89 | 89 | <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> --> |
| 90 | 90 | </el-button-group> | ... | ... |