Commit 9e28923b8c1c333df8ce3caf741b0e16da2ed48a

Authored by 648540858
Committed by GitHub
2 parents ccc0a99d b4dadf6c

Merge branch 'wvp-28181-2.0' into wvp-28181-2.0

Showing 28 changed files with 856 additions and 582 deletions

Too many changes to show.

To preserve performance only 28 of 35 files are displayed.

sql/2.6.8升级2.6.9.sql
... ... @@ -38,7 +38,7 @@ alter table device
38 38 change geoCoordSys geo_coord_sys varchar(50) not null;
39 39  
40 40 alter table device
41   - change treeType tree_type varchar(50) not null;
  41 + drop column treeType;
42 42  
43 43 alter table device
44 44 change mediaServerId media_server_id varchar(50) default 'auto' null;
... ... @@ -297,7 +297,7 @@ alter table parent_platform
297 297 change updateTime update_time varchar(50) null;
298 298  
299 299 alter table parent_platform
300   - change treeType tree_type varchar(50) not null;
  300 + drop column treeType;
301 301  
302 302 alter table parent_platform
303 303 change asMessageChannel as_message_channel bool default false;
... ...
sql/初始化.sql
... ... @@ -24,7 +24,6 @@ create table wvp_device (
24 24 charset character varying(50),
25 25 ssrc_check bool default false,
26 26 geo_coord_sys character varying(50),
27   - tree_type character varying(50),
28 27 media_server_id character varying(50),
29 28 custom_name character varying(255),
30 29 sdp_ip character varying(50),
... ... @@ -187,7 +186,6 @@ create table wvp_platform (
187 186 catalog_group integer,
188 187 create_time character varying(50),
189 188 update_time character varying(50),
190   - tree_type character varying(50),
191 189 as_message_channel bool default false,
192 190 constraint uk_platform_unique_server_gb_id unique (server_gb_id)
193 191 );
... ...
src/main/java/com/genersoft/iot/vmp/common/CivilCodePo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +public class CivilCodePo {
  4 +
  5 + private String code;
  6 +
  7 + private String name;
  8 +
  9 + private String parentCode;
  10 +
  11 + public static CivilCodePo getInstance(String[] infoArray) {
  12 + CivilCodePo civilCodePo = new CivilCodePo();
  13 + civilCodePo.setCode(infoArray[0]);
  14 + civilCodePo.setName(infoArray[1]);
  15 + civilCodePo.setParentCode(infoArray[2]);
  16 + return civilCodePo;
  17 + }
  18 +
  19 + public String getCode() {
  20 + return code;
  21 + }
  22 +
  23 + public void setCode(String code) {
  24 + this.code = code;
  25 + }
  26 +
  27 + public String getName() {
  28 + return name;
  29 + }
  30 +
  31 + public void setName(String name) {
  32 + this.name = name;
  33 + }
  34 +
  35 + public String getParentCode() {
  36 + return parentCode;
  37 + }
  38 +
  39 + public void setParentCode(String parentCode) {
  40 + this.parentCode = parentCode;
  41 + }
  42 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/CivilCodeFileConf.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf;
  2 +
  3 +import com.genersoft.iot.vmp.common.CivilCodePo;
  4 +import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.boot.CommandLineRunner;
  9 +import org.springframework.context.annotation.Configuration;
  10 +import org.springframework.context.annotation.Lazy;
  11 +import org.springframework.core.annotation.Order;
  12 +import org.springframework.core.io.ClassPathResource;
  13 +import org.springframework.util.ObjectUtils;
  14 +
  15 +import java.io.*;
  16 +import java.nio.file.Files;
  17 +import java.util.Map;
  18 +
  19 +/**
  20 + * 启动时读取行政区划表
  21 + */
  22 +@Configuration
  23 +@Order(value=14)
  24 +public class CivilCodeFileConf implements CommandLineRunner {
  25 +
  26 + private final static Logger logger = LoggerFactory.getLogger(CivilCodeFileConf.class);
  27 +
  28 + private final Map<String, CivilCodePo> civilCodeMap= new ConcurrentHashMap<>();
  29 +
  30 + @Autowired
  31 + @Lazy
  32 + private UserSetting userSetting;
  33 +
  34 + @Override
  35 + public void run(String... args) throws Exception {
  36 + if (ObjectUtils.isEmpty(userSetting.getCivilCodeFile())) {
  37 + logger.warn("[行政区划] 文件未设置,可能造成目录刷新结果不完整");
  38 + return;
  39 + }
  40 + InputStream inputStream;
  41 + if (userSetting.getCivilCodeFile().startsWith("classpath:")){
  42 + String filePath = userSetting.getCivilCodeFile().substring("classpath:".length());
  43 + ClassPathResource civilCodeFile = new ClassPathResource(filePath);
  44 + if (!civilCodeFile.exists()) {
  45 + logger.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
  46 + return;
  47 + }
  48 + inputStream = civilCodeFile.getInputStream();
  49 +
  50 + }else {
  51 + File civilCodeFile = new File(userSetting.getCivilCodeFile());
  52 + if (!civilCodeFile.exists()) {
  53 + logger.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
  54 + return;
  55 + }
  56 + inputStream = Files.newInputStream(civilCodeFile.toPath());
  57 + }
  58 +
  59 + BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(inputStream));
  60 + int index = -1;
  61 + String line;
  62 + while ((line = inputStreamReader.readLine()) != null) {
  63 + index ++;
  64 + if (index == 0) {
  65 + continue;
  66 + }
  67 + String[] infoArray = line.split(",");
  68 + CivilCodePo civilCodePo = CivilCodePo.getInstance(infoArray);
  69 + civilCodeMap.put(civilCodePo.getCode(), civilCodePo);
  70 + }
  71 + inputStreamReader.close();
  72 + inputStream.close();
  73 + if (civilCodeMap.size() == 0) {
  74 + logger.warn("[行政区划] 文件内容为空,可能造成目录刷新结果不完整");
  75 + }else {
  76 + logger.info("[行政区划] 加载成功,共加载数据{}条", civilCodeMap.size());
  77 + }
  78 + }
  79 +
  80 + public CivilCodePo getParentCode(String code) {
  81 + if (code.length() > 8) {
  82 + return null;
  83 + }
  84 + if (code.length() == 8) {
  85 + String parentCode = code.substring(0, 6);
  86 + return civilCodeMap.get(parentCode);
  87 + }else {
  88 + CivilCodePo civilCodePo = civilCodeMap.get(code);
  89 + if (civilCodePo == null){
  90 + return null;
  91 + }
  92 + String parentCode = civilCodePo.getParentCode();
  93 + if (parentCode == null) {
  94 + return null;
  95 + }
  96 + return civilCodeMap.get(parentCode);
  97 + }
  98 +
  99 + }
  100 +
  101 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
... ... @@ -45,6 +45,7 @@ public class DynamicTask {
45 45 * @return
46 46 */
47 47 public void startCron(String key, Runnable task, int cycleForCatalog) {
  48 + System.out.println(cycleForCatalog);
48 49 ScheduledFuture<?> future = futureMap.get(key);
49 50 if (future != null) {
50 51 if (future.isCancelled()) {
... ...
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
... ... @@ -56,7 +56,7 @@ public class SipPlatformRunner implements CommandLineRunner {
56 56 }
57 57  
58 58 // 设置所有平台离线
59   - platformService.offline(parentPlatform, true);
  59 + platformService.offline(parentPlatform, false);
60 60 }
61 61 }
62 62 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
... ... @@ -63,7 +63,7 @@ public class UserSetting {
63 63  
64 64 private String thirdPartyGBIdReg = "[\\s\\S]*";
65 65  
66   -
  66 + private String civilCodeFile = "classpath:civilCode.csv";
67 67  
68 68 private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
69 69  
... ... @@ -71,6 +71,10 @@ public class UserSetting {
71 71  
72 72 private int maxNotifyCountQueue = 10000;
73 73  
  74 + private int registerAgainAfterTime = 60;
  75 +
  76 + private boolean registerKeepIntDialog = false;
  77 +
74 78 public Boolean getSavePositionHistory() {
75 79 return savePositionHistory;
76 80 }
... ... @@ -299,9 +303,27 @@ public class UserSetting {
299 303 this.sqlLog = sqlLog;
300 304 }
301 305  
  306 + public String getCivilCodeFile() {
  307 + return civilCodeFile;
  308 + }
302 309  
  310 + public void setCivilCodeFile(String civilCodeFile) {
  311 + this.civilCodeFile = civilCodeFile;
  312 + }
303 313  
  314 + public int getRegisterAgainAfterTime() {
  315 + return registerAgainAfterTime;
  316 + }
304 317  
  318 + public void setRegisterAgainAfterTime(int registerAgainAfterTime) {
  319 + this.registerAgainAfterTime = registerAgainAfterTime;
  320 + }
305 321  
  322 + public boolean isRegisterKeepIntDialog() {
  323 + return registerKeepIntDialog;
  324 + }
306 325  
  326 + public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
  327 + this.registerKeepIntDialog = registerKeepIntDialog;
  328 + }
307 329 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -173,12 +173,6 @@ public class Device {
173 173 @Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02")
174 174 private String geoCoordSys;
175 175  
176   - /**
177   - * 树类型 国标规定了两种树的展现方式 行政区划:CivilCode 和业务分组:BusinessGroup
178   - */
179   - @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划:CivilCode 和业务分组:BusinessGroup")
180   - private String treeType;
181   -
182 176 @Schema(description = "密码")
183 177 private String password;
184 178  
... ... @@ -408,14 +402,6 @@ public class Device {
408 402 this.geoCoordSys = geoCoordSys;
409 403 }
410 404  
411   - public String getTreeType() {
412   - return treeType;
413   - }
414   -
415   - public void setTreeType(String treeType) {
416   - this.treeType = treeType;
417   - }
418   -
419 405 public String getPassword() {
420 406 return password;
421 407 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
... ... @@ -183,12 +183,6 @@ public class ParentPlatform {
183 183 @Schema(description = "创建时间")
184 184 private String createTime;
185 185  
186   - /**
187   - * 树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGroup
188   - */
189   - @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou")
190   - private String treeType;
191   -
192 186 @Schema(description = "是否作为消息通道")
193 187 private boolean asMessageChannel;
194 188  
... ... @@ -424,14 +418,6 @@ public class ParentPlatform {
424 418 this.createTime = createTime;
425 419 }
426 420  
427   - public String getTreeType() {
428   - return treeType;
429   - }
430   -
431   - public void setTreeType(String treeType) {
432   - this.treeType = treeType;
433   - }
434   -
435 421 public boolean isAsMessageChannel() {
436 422 return asMessageChannel;
437 423 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.bean;
2   -
3   -/**
4   - * 目录结构类型
5   - * @author lin
6   - */
7   -public class TreeType {
8   - public static final String BUSINESS_GROUP = "BusinessGroup";
9   - public static final String CIVIL_CODE = "CivilCode";
10   -}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -209,59 +209,149 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
209 209 // 行政区划分组只需要这两项就可以
210 210 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
211 211 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
212   - if (channel.getParentId() != null) {
213   - // 业务分组加上这一项即可,提高兼容性,
214   - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
215   -// catalogXml.append("<ParentID>" + parentPlatform.getDeviceGBId() + "/" + channel.getParentId() + "</ParentID>\r\n");
216   - }
217   - if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
218   - // 虚拟组织增加BusinessGroupID字段
219   - catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
220   - }
221   - if (!channel.getChannelId().equals(parentPlatform.getDeviceGBId())) {
222   - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
223   - if (channel.getParental() == 0) {
224   - catalogXml.append("<Status>" + (channel.isStatus() ? "ON" : "OFF") + "</Status>\r\n");
  212 + if (channel.getChannelId().length() <= 8) {
  213 + catalogXml.append("</Item>\r\n");
  214 + continue;
  215 + }else {
  216 + if (channel.getChannelId().length() != 20) {
  217 + continue;
225 218 }
226   - }
227   - if (channel.getParental() == 0) {
228   - // 通道项
229   - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
230   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
231   - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
232   - String civilCode = channel.getCivilCode() == null?parentPlatform.getAdministrativeDivision() : channel.getCivilCode();
233   - if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
234   - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
235   - catalogXml.append("<Owner>" + parentPlatform.getDeviceGBId()+ "</Owner>\r\n");
236   - catalogXml.append("<CivilCode>" + civilCode + "</CivilCode>\r\n");
237   - if (channel.getAddress() == null) {
238   - catalogXml.append("<Address></Address>\r\n");
239   - }else {
240   - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
241   - }
242   - catalogXml.append("<Block>" + channel.getBlock() + "</Block>\r\n");
243   - catalogXml.append("<SafetyWay>" + channel.getSafetyWay() + "</SafetyWay>\r\n");
244   - catalogXml.append("<CertNum>" + channel.getCertNum() + "</CertNum>\r\n");
245   - catalogXml.append("<Certifiable>" + channel.getCertifiable() + "</Certifiable>\r\n");
246   - catalogXml.append("<ErrCode>" + channel.getErrCode() + "</ErrCode>\r\n");
247   - catalogXml.append("<EndTime>" + channel.getEndTime() + "</EndTime>\r\n");
248   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
249   - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
250   - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
251   - catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n");
252   - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
253   - catalogXml.append("<Status>" + (channel.isStatus() ? "ON":"OFF") + "</Status>\r\n");
254   - catalogXml.append("<Longitude>" +
255   - (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
256   - + "</Longitude>\r\n");
257   - catalogXml.append("<Latitude>" +
258   - (channel.getLatitudeWgs84() != 0? channel.getLatitudeWgs84():channel.getLatitude())
259   - + "</Latitude>\r\n");
260   -
  219 + switch (Integer.parseInt(channel.getChannelId().substring(10, 13))){
  220 + case 200:
  221 +// catalogXml.append("<Manufacturer>三永华通</Manufacturer>\r\n");
  222 +// GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil");
  223 +// String model = (gitUtil == null || gitUtil.getBuildVersion() == null)?"1.0": gitUtil.getBuildVersion();
  224 +// catalogXml.append("<Model>" + model + "</Manufacturer>\r\n");
  225 +// catalogXml.append("<Owner>三永华通</Owner>\r\n");
  226 + if (channel.getCivilCode() != null) {
  227 + catalogXml.append("<CivilCode>"+channel.getCivilCode()+"</CivilCode>\r\n");
  228 + }else {
  229 + catalogXml.append("<CivilCode></CivilCode>\r\n");
  230 + }
  231 +
  232 + catalogXml.append("<RegisterWay>1</RegisterWay>\r\n");
  233 + catalogXml.append("<Secrecy>0</Secrecy>\r\n");
  234 + break;
  235 + case 215:
  236 + if (!ObjectUtils.isEmpty(channel.getParentId())) {
  237 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  238 + }
  239 +
  240 + break;
  241 + case 216:
  242 + if (!ObjectUtils.isEmpty(channel.getParentId())) {
  243 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  244 + }else {
  245 + catalogXml.append("<ParentID></ParentID>\r\n");
  246 + }
  247 + if (!ObjectUtils.isEmpty(channel.getBusinessGroupId())) {
  248 + catalogXml.append("<BusinessGroupID>" + channel.getBusinessGroupId() + "</BusinessGroupID>\r\n");
  249 + }else {
  250 + catalogXml.append("<BusinessGroupID></BusinessGroupID>\r\n");
  251 + }
  252 + break;
  253 + default:
  254 + // 通道项
  255 + if (channel.getManufacture() != null) {
  256 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  257 + }else {
  258 + catalogXml.append("<Manufacturer></Manufacturer>\r\n");
  259 + }
  260 + if (channel.getSecrecy() != null) {
  261 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  262 + }else {
  263 + catalogXml.append("<Secrecy></Secrecy>\r\n");
  264 + }
  265 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  266 + if (channel.getModel() != null) {
  267 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  268 + }else {
  269 + catalogXml.append("<Model></Model>\r\n");
  270 + }
  271 + if (channel.getOwner() != null) {
  272 + catalogXml.append("<Owner>" + channel.getOwner()+ "</Owner>\r\n");
  273 + }else {
  274 + catalogXml.append("<Owner></Owner>\r\n");
  275 + }
  276 + if (channel.getCivilCode() != null) {
  277 + catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
  278 + }else {
  279 + catalogXml.append("<CivilCode></CivilCode>\r\n");
  280 + }
  281 + if (channel.getAddress() == null) {
  282 + catalogXml.append("<Address></Address>\r\n");
  283 + }else {
  284 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  285 + }
  286 + if (!ObjectUtils.isEmpty(channel.getParentId())) {
  287 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  288 + }else {
  289 + catalogXml.append("<ParentID></ParentID>\r\n");
  290 + }
  291 + if (!ObjectUtils.isEmpty(channel.getBlock())) {
  292 + catalogXml.append("<Block>" + channel.getBlock() + "</Block>\r\n");
  293 + }else {
  294 + catalogXml.append("<Block></Block>\r\n");
  295 + }
  296 + if (!ObjectUtils.isEmpty(channel.getSafetyWay())) {
  297 + catalogXml.append("<SafetyWay>" + channel.getSafetyWay() + "</SafetyWay>\r\n");
  298 + }else {
  299 + catalogXml.append("<SafetyWay></SafetyWay>\r\n");
  300 + }
  301 + if (!ObjectUtils.isEmpty(channel.getCertNum())) {
  302 + catalogXml.append("<CertNum>" + channel.getCertNum() + "</CertNum>\r\n");
  303 + }else {
  304 + catalogXml.append("<CertNum></CertNum>\r\n");
  305 + }
  306 + if (!ObjectUtils.isEmpty(channel.getCertifiable())) {
  307 + catalogXml.append("<Certifiable>" + channel.getCertifiable() + "</Certifiable>\r\n");
  308 + }else {
  309 + catalogXml.append("<Certifiable></Certifiable>\r\n");
  310 + }
  311 + if (!ObjectUtils.isEmpty(channel.getErrCode())) {
  312 + catalogXml.append("<ErrCode>" + channel.getErrCode() + "</ErrCode>\r\n");
  313 + }else {
  314 + catalogXml.append("<ErrCode></ErrCode>\r\n");
  315 + }
  316 + if (!ObjectUtils.isEmpty(channel.getEndTime())) {
  317 + catalogXml.append("<EndTime>" + channel.getEndTime() + "</EndTime>\r\n");
  318 + }else {
  319 + catalogXml.append("<EndTime></EndTime>\r\n");
  320 + }
  321 + if (!ObjectUtils.isEmpty(channel.getSecrecy())) {
  322 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  323 + }else {
  324 + catalogXml.append("<Secrecy></Secrecy>\r\n");
  325 + }
  326 + if (!ObjectUtils.isEmpty(channel.getIpAddress())) {
  327 + catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
  328 + }else {
  329 + catalogXml.append("<IPAddress></IPAddress>\r\n");
  330 + }
  331 + catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
  332 + if (!ObjectUtils.isEmpty(channel.getPassword())) {
  333 + catalogXml.append("<Password>" + channel.getPassword() + "</Password>\r\n");
  334 + }else {
  335 + catalogXml.append("<Password></Password>\r\n");
  336 + }
  337 + if (!ObjectUtils.isEmpty(channel.getPTZType())) {
  338 + catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
  339 + }else {
  340 + catalogXml.append("<PTZType></PTZType>\r\n");
  341 + }
  342 + catalogXml.append("<Status>" + (channel.isStatus() ?"ON":"OFF") + "</Status>\r\n");
  343 +
  344 + catalogXml.append("<Longitude>" +
  345 + (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
  346 + + "</Longitude>\r\n");
  347 + catalogXml.append("<Latitude>" +
  348 + (channel.getLatitudeWgs84() != 0? channel.getLatitudeWgs84():channel.getLatitude())
  349 + + "</Latitude>\r\n");
  350 + break;
261 351  
262 352 }
  353 + catalogXml.append("</Item>\r\n");
263 354 }
264   - catalogXml.append("</Item>\r\n");
265 355 }
266 356 }
267 357  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -188,6 +188,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
188 188 logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
189 189 }
190 190 return;
  191 + }else {
  192 + // TODO 可能漏回复消息
191 193 }
192 194 }
193 195 } else {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2  
  3 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
3 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 5 import com.genersoft.iot.vmp.conf.UserSetting;
5 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
... ... @@ -20,7 +21,10 @@ import org.springframework.stereotype.Component;
20 21  
21 22 import javax.sip.RequestEvent;
22 23 import javax.sip.header.FromHeader;
23   -import java.util.*;
  24 +import java.util.ArrayList;
  25 +import java.util.Iterator;
  26 +import java.util.List;
  27 +import java.util.Map;
24 28 import java.util.concurrent.ConcurrentHashMap;
25 29 import java.util.concurrent.CopyOnWriteArrayList;
26 30  
... ... @@ -56,6 +60,9 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
56 60 @Autowired
57 61 private DynamicTask dynamicTask;
58 62  
  63 + @Autowired
  64 + private CivilCodeFileConf civilCodeFileConf;
  65 +
59 66 private final static String talkKey = "notify-request-for-catalog-task";
60 67  
61 68 public void process(RequestEvent evt) {
... ... @@ -96,7 +103,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
96 103 }else {
97 104 event = eventElement.getText().toUpperCase();
98 105 }
99   - DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
  106 + DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, event, civilCodeFileConf);
100 107  
101 108 channel.setDeviceId(device.getDeviceId());
102 109 logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2  
3 3 import com.alibaba.fastjson2.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
4 5 import com.genersoft.iot.vmp.conf.SipConfig;
5 6 import com.genersoft.iot.vmp.conf.UserSetting;
6 7 import com.genersoft.iot.vmp.gb28181.bean.*;
... ... @@ -79,6 +80,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
79 80 @Autowired
80 81 private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor;
81 82  
  83 + @Autowired
  84 + private CivilCodeFileConf civilCodeFileConf;
  85 +
82 86 private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
83 87  
84 88 @Qualifier("taskExecutor")
... ... @@ -408,7 +412,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
408 412 }else {
409 413 event = eventElement.getText().toUpperCase();
410 414 }
411   - DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
  415 + DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, event, civilCodeFileConf);
412 416 channel.setDeviceId(device.getDeviceId());
413 417 logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
414 418 switch (event) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
... ... @@ -164,7 +164,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
164 164 device.setStreamMode("UDP");
165 165 device.setCharset("GB2312");
166 166 device.setGeoCoordSys("WGS84");
167   - device.setTreeType("CivilCode");
168 167 device.setDeviceId(deviceId);
169 168 device.setOnLine(false);
170 169 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
2 2  
  3 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
3 4 import com.genersoft.iot.vmp.gb28181.bean.*;
4 5 import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
... ... @@ -53,6 +54,9 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
53 54 @Autowired
54 55 private ThreadPoolTaskExecutor taskExecutor;
55 56  
  57 + @Autowired
  58 + private CivilCodeFileConf civilCodeFileConf;
  59 +
56 60 @Override
57 61 public void afterPropertiesSet() throws Exception {
58 62 responseMessageHandler.addHandler(cmdType, this);
... ... @@ -100,6 +104,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
100 104 Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
101 105 if (deviceListIterator != null) {
102 106 List<DeviceChannel> channelList = new ArrayList<>();
  107 + List<String> parentChannelIds = new ArrayList<>();
103 108 // 遍历DeviceList
104 109 while (deviceListIterator.hasNext()) {
105 110 Element itemDevice = deviceListIterator.next();
... ... @@ -107,7 +112,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
107 112 if (channelDeviceElement == null) {
108 113 continue;
109 114 }
110   - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
  115 + DeviceChannel deviceChannel = XmlUtil.channelContentHandler(itemDevice, device, null, civilCodeFileConf);
111 116 deviceChannel = SipUtils.updateGps(deviceChannel, device.getGeoCoordSys());
112 117 deviceChannel.setDeviceId(take.getDevice().getDeviceId());
113 118  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
... ... @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.utils;
2 2  
3 3 import com.alibaba.fastjson2.JSONArray;
4 4 import com.alibaba.fastjson2.JSONObject;
  5 +import com.genersoft.iot.vmp.common.CivilCodePo;
  6 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
5 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
7 9 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
... ... @@ -192,7 +194,7 @@ public class XmlUtil {
192 194 CivilCode, BusinessGroup,VirtualOrganization,Other
193 195 }
194 196  
195   - public static DeviceChannel channelContentHander(Element itemDevice, Device device, String event){
  197 + public static DeviceChannel channelContentHandler(Element itemDevice, Device device, String event, CivilCodeFileConf civilCodeFileConf){
196 198 DeviceChannel deviceChannel = new DeviceChannel();
197 199 deviceChannel.setDeviceId(device.getDeviceId());
198 200 Element channdelIdElement = itemDevice.element("DeviceID");
... ... @@ -210,208 +212,353 @@ public class XmlUtil {
210 212 // 除了ADD和update情况下需要识别全部内容,
211 213 return deviceChannel;
212 214 }
213   -
214   - ChannelType channelType = ChannelType.Other;
215   - if (channelId.length() <= 8) {
216   - channelType = ChannelType.CivilCode;
217   - deviceChannel.setHasAudio(false);
218   - }else {
219   - if (channelId.length() == 20) {
220   - int code = Integer.parseInt(channelId.substring(10, 13));
221   - switch (code){
222   - case 215:
223   - channelType = ChannelType.BusinessGroup;
224   - deviceChannel.setHasAudio(false);
225   - break;
226   - case 216:
227   - channelType = ChannelType.VirtualOrganization;
228   - deviceChannel.setHasAudio(false);
229   - break;
230   - case 136:
231   - case 137:
232   - case 138:
233   - deviceChannel.setHasAudio(true);
234   - break;
235   - default:
236   - deviceChannel.setHasAudio(false);
237   - break;
238   -
239   - }
240   - }
  215 + Element nameElement = itemDevice.element("Name");
  216 + if (nameElement != null) {
  217 + deviceChannel.setName(nameElement.getText());
241 218 }
242   -
243   - Element channdelNameElement = itemDevice.element("Name");
244   - String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim() : "";
245   - deviceChannel.setName(channelName);
246   -
247   - String civilCode = XmlUtil.getText(itemDevice, "CivilCode");
248   - deviceChannel.setCivilCode(civilCode);
249   - if (channelType == ChannelType.CivilCode && civilCode == null) {
250   - deviceChannel.setParental(1);
251   - // 行政区划如果没有传递具体值,则推测一个
252   - if (channelId.length() > 2) {
253   - deviceChannel.setCivilCode(channelId.substring(0, channelId.length() - 2));
  219 + if(channelId.length() <= 8) {
  220 + deviceChannel.setHasAudio(false);
  221 + CivilCodePo parentCode = civilCodeFileConf.getParentCode(channelId);
  222 + if (parentCode != null) {
  223 + deviceChannel.setParentId(parentCode.getCode());
  224 + deviceChannel.setCivilCode(parentCode.getCode());
  225 + }else {
  226 + logger.warn("[xml解析] 无法确定行政区划{}的上级行政区划", channelId);
254 227 }
255   - }
256   - if (channelType.equals(ChannelType.CivilCode)) {
257   - // 行政区划其他字段没必要识别了,默认在线即可
258 228 deviceChannel.setStatus(true);
259   - deviceChannel.setParental(1);
260   - deviceChannel.setCreateTime(DateUtil.getNow());
261   - deviceChannel.setUpdateTime(DateUtil.getNow());
262 229 return deviceChannel;
263   - }
264   - /**
265   - * 行政区划展示设备树与业务分组展示设备树是两种不同的模式
266   - * 行政区划展示设备树 各个目录之间主要靠deviceId做关联,摄像头通过CivilCode指定其属于那个行政区划;都是不超过十位的编号; 结构如下:
267   - * 河北省
268   - * --> 石家庄市
269   - * --> 摄像头
270   - *String parentId = XmlUtil.getText(itemDevice, "ParentID");
271   - if (parentId != null) {
272   - if (parentId.contains("/")) {
273   - String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
274   - String businessGroup = parentId.substring(0, parentId.indexOf("/"));
275   - deviceChannel.setParentId(lastParentId);
276   - }else {
277   - deviceChannel.setParentId(parentId);
278   - }
279   - }
280   - deviceCh --> 正定县
281   - * --> 摄像头
282   - * --> 摄像头
283   - *
284   - * 业务分组展示设备树是顶级是业务分组,其下的虚拟组织靠BusinessGroupID指定其所属的业务分组;摄像头通过ParentId来指定其所属于的虚拟组织:
285   - * 业务分组
286   - * --> 虚拟组织
287   - * --> 摄像头
288   - * --> 虚拟组织
289   - * --> 摄像头
290   - * --> 摄像头
291   - */
292   - String parentId = XmlUtil.getText(itemDevice, "ParentID");
293   - String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
294   - if (parentId != null) {
295   - if (parentId.contains("/")) {
296   - String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
297   - if (businessGroupID == null) {
298   - businessGroupID = parentId.substring(0, parentId.indexOf("/"));
299   - }
300   - deviceChannel.setParentId(lastParentId);
  230 + }else {
  231 + if(channelId.length() != 20) {
  232 + logger.warn("[xml解析] 失败,编号不符合国标28181定义: {}", channelId);
  233 + return null;
  234 + }
  235 +
  236 + int code = Integer.parseInt(channelId.substring(10, 13));
  237 + if (code == 136 || code == 137 || code == 138) {
  238 + deviceChannel.setHasAudio(true);
301 239 }else {
302   - deviceChannel.setParentId(parentId);
  240 + deviceChannel.setHasAudio(false);
303 241 }
304   - // 兼容设备通道信息中自己为自己父节点的情况
305   - if (deviceChannel.getParentId().equals(deviceChannel.getChannelId())) {
306   - deviceChannel.setParentId(null);
  242 + // 设备厂商
  243 + String manufacturer = getText(itemDevice, "Manufacturer");
  244 + // 设备型号
  245 + String model = getText(itemDevice, "Model");
  246 + // 设备归属
  247 + String owner = getText(itemDevice, "Owner");
  248 + // 行政区域
  249 + String civilCode = getText(itemDevice, "CivilCode");
  250 + // 虚拟组织所属的业务分组ID,业务分组根据特定的业务需求制定,一个业务分组包含一组特定的虚拟组织
  251 + String businessGroupID = getText(itemDevice, "BusinessGroupID");
  252 + // 父设备/区域/系统ID
  253 + String parentID = getText(itemDevice, "ParentID");
  254 + if (parentID != null && parentID.equalsIgnoreCase("null")) {
  255 + parentID = null;
307 256 }
308   - }
309   - deviceChannel.setBusinessGroupId(businessGroupID);
310   - if (channelType.equals(ChannelType.BusinessGroup) || channelType.equals(ChannelType.VirtualOrganization)) {
311   - // 业务分组和虚拟组织 其他字段没必要识别了,默认在线即可
312   - deviceChannel.setStatus(true);
313   - deviceChannel.setParental(1);
314   - deviceChannel.setCreateTime(DateUtil.getNow());
315   - deviceChannel.setUpdateTime(DateUtil.getNow());
316   - return deviceChannel;
317   - }
  257 + // 注册方式(必选)缺省为1;1:符合IETFRFC3261标准的认证注册模式;2:基于口令的双向认证注册模式;3:基于数字证书的双向认证注册模式
  258 + String registerWay = getText(itemDevice, "RegisterWay");
  259 + // 保密属性(必选)缺省为0;0:不涉密,1:涉密
  260 + String secrecy = getText(itemDevice, "Secrecy");
  261 + // 安装地址
  262 + String address = getText(itemDevice, "Address");
  263 +
  264 + switch (code){
  265 + case 200:
  266 + // 系统目录
  267 + if (!ObjectUtils.isEmpty(manufacturer)) {
  268 + deviceChannel.setManufacture(manufacturer);
  269 + }
  270 + if (!ObjectUtils.isEmpty(model)) {
  271 + deviceChannel.setModel(model);
  272 + }
  273 + if (!ObjectUtils.isEmpty(owner)) {
  274 + deviceChannel.setOwner(owner);
  275 + }
  276 + if (!ObjectUtils.isEmpty(civilCode)) {
  277 + deviceChannel.setCivilCode(civilCode);
  278 + deviceChannel.setParentId(civilCode);
  279 + }else {
  280 + if (!ObjectUtils.isEmpty(parentID)) {
  281 + deviceChannel.setParentId(parentID);
  282 + }
  283 + }
  284 + if (!ObjectUtils.isEmpty(address)) {
  285 + deviceChannel.setAddress(address);
  286 + }
  287 + deviceChannel.setStatus(true);
  288 + if (!ObjectUtils.isEmpty(registerWay)) {
  289 + try {
  290 + deviceChannel.setRegisterWay(Integer.parseInt(registerWay));
  291 + }catch (NumberFormatException exception) {
  292 + logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay);
  293 + }
  294 + }
  295 + if (!ObjectUtils.isEmpty(secrecy)) {
  296 + deviceChannel.setSecrecy(secrecy);
  297 + }
  298 + return deviceChannel;
  299 + case 215:
  300 + // 业务分组
  301 + deviceChannel.setStatus(true);
  302 + if (!ObjectUtils.isEmpty(parentID)) {
  303 + if (!parentID.trim().equalsIgnoreCase(device.getDeviceId())) {
  304 + deviceChannel.setParentId(parentID);
  305 + }
  306 + }else {
  307 + logger.warn("[xml解析] 业务分组数据中缺少关键信息->ParentId");
  308 + if (!ObjectUtils.isEmpty(civilCode)) {
  309 + deviceChannel.setCivilCode(civilCode);
  310 + }
  311 + }
  312 + break;
  313 + case 216:
  314 + // 虚拟组织
  315 + deviceChannel.setStatus(true);
  316 + if (!ObjectUtils.isEmpty(businessGroupID)) {
  317 + deviceChannel.setBusinessGroupId(businessGroupID);
  318 + }
318 319  
319   - Element statusElement = itemDevice.element("Status");
320 320  
321   - if (statusElement != null) {
322   - String status = statusElement.getTextTrim().trim();
323   - // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
324   - if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
325   - deviceChannel.setStatus(true);
326   - }
327   - if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
328   - deviceChannel.setStatus(false);
329   - }
330   - }else {
331   - deviceChannel.setStatus(true);
332   - }
333   - // 识别自带的目录标识
334   - String parental = XmlUtil.getText(itemDevice, "Parental");
335   - // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
336   - if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
337   - deviceChannel.setParental(0);
338   - }else {
339   - deviceChannel.setParental(1);
340   - }
  321 + if (!ObjectUtils.isEmpty(parentID)) {
  322 + if (parentID.contains("/")) {
  323 + String[] parentIdArray = parentID.split("/");
  324 + parentID = parentIdArray[parentIdArray.length - 1];
  325 + }
  326 + deviceChannel.setParentId(parentID);
  327 + }else {
  328 + if (!ObjectUtils.isEmpty(businessGroupID)) {
  329 + deviceChannel.setParentId(businessGroupID);
  330 + }
  331 + }
  332 + break;
  333 + default:
  334 + // 设备目录
  335 + if (!ObjectUtils.isEmpty(manufacturer)) {
  336 + deviceChannel.setManufacture(manufacturer);
  337 + }
  338 + if (!ObjectUtils.isEmpty(model)) {
  339 + deviceChannel.setModel(model);
  340 + }
  341 + if (!ObjectUtils.isEmpty(owner)) {
  342 + deviceChannel.setOwner(owner);
  343 + }
  344 + if (!ObjectUtils.isEmpty(civilCode)) {
  345 + deviceChannel.setCivilCode(civilCode);
  346 + }
  347 + if (!ObjectUtils.isEmpty(businessGroupID)) {
  348 + deviceChannel.setBusinessGroupId(businessGroupID);
  349 + }
341 350  
  351 + // 警区
  352 + String block = getText(itemDevice, "Block");
  353 + if (!ObjectUtils.isEmpty(block)) {
  354 + deviceChannel.setBlock(block);
  355 + }
  356 + if (!ObjectUtils.isEmpty(address)) {
  357 + deviceChannel.setAddress(address);
  358 + }
342 359  
343   - deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
344   - deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
345   - deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
346   - deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
347   - deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
348   - deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
349   - deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
  360 + if (!ObjectUtils.isEmpty(secrecy)) {
  361 + deviceChannel.setSecrecy(secrecy);
  362 + }
350 363  
351   - String safetyWay = XmlUtil.getText(itemDevice, "SafetyWay");
352   - if (ObjectUtils.isEmpty(safetyWay)) {
353   - deviceChannel.setSafetyWay(0);
354   - } else {
355   - deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
356   - }
  364 + // 当为设备时,是否有子设备(必选)1有,0没有
  365 + String parental = getText(itemDevice, "Parental");
  366 + if (!ObjectUtils.isEmpty(parental)) {
  367 + try {
  368 + // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
  369 + if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
  370 + deviceChannel.setParental(0);
  371 + }else {
  372 + deviceChannel.setParental(1);
  373 + }
  374 + }catch (NumberFormatException e) {
  375 + logger.warn("[xml解析] 从通道数据获取 parental失败: {}", parental);
  376 + }
  377 + }
  378 + // 父设备/区域/系统ID
  379 + String realParentId = parentID;
  380 + if (!ObjectUtils.isEmpty(parentID)) {
  381 + if (parentID.contains("/")) {
  382 + String[] parentIdArray = parentID.split("/");
  383 + realParentId = parentIdArray[parentIdArray.length - 1];
  384 + }
  385 + deviceChannel.setParentId(realParentId);
  386 + }else {
  387 + if (!ObjectUtils.isEmpty(businessGroupID)) {
  388 + deviceChannel.setParentId(businessGroupID);
  389 + }else {
  390 + if (!ObjectUtils.isEmpty(civilCode)) {
  391 + deviceChannel.setParentId(civilCode);
  392 + }
  393 + }
  394 + }
  395 + // 注册方式
  396 + if (!ObjectUtils.isEmpty(registerWay)) {
  397 + try {
  398 + int registerWayInt = Integer.parseInt(registerWay);
  399 + deviceChannel.setRegisterWay(registerWayInt);
  400 + }catch (NumberFormatException exception) {
  401 + logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay);
  402 + deviceChannel.setRegisterWay(1);
  403 + }
  404 + }else {
  405 + deviceChannel.setRegisterWay(1);
  406 + }
357 407  
358   - String registerWay = XmlUtil.getText(itemDevice, "RegisterWay");
359   - if (ObjectUtils.isEmpty(registerWay)) {
360   - deviceChannel.setRegisterWay(1);
361   - } else {
362   - deviceChannel.setRegisterWay(Integer.parseInt(registerWay));
363   - }
  408 + // 信令安全模式(可选)缺省为0; 0:不采用;2:S/MIME 签名方式;3:S/MIME加密签名同时采用方式;4:数字摘要方式
  409 + String safetyWay = getText(itemDevice, "SafetyWay");
  410 + if (!ObjectUtils.isEmpty(safetyWay)) {
  411 + try {
  412 + deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
  413 + }catch (NumberFormatException e) {
  414 + logger.warn("[xml解析] 从通道数据获取 safetyWay失败: {}", safetyWay);
  415 + }
  416 + }
364 417  
365   - if (XmlUtil.getText(itemDevice, "Certifiable") == null
366   - || XmlUtil.getText(itemDevice, "Certifiable") == "") {
367   - deviceChannel.setCertifiable(0);
368   - } else {
369   - deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
370   - }
  418 + // 证书序列号(有证书的设备必选)
  419 + String certNum = getText(itemDevice, "CertNum");
  420 + if (!ObjectUtils.isEmpty(certNum)) {
  421 + deviceChannel.setCertNum(certNum);
  422 + }
371 423  
372   - if (XmlUtil.getText(itemDevice, "ErrCode") == null
373   - || XmlUtil.getText(itemDevice, "ErrCode") == "") {
374   - deviceChannel.setErrCode(0);
375   - } else {
376   - deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
377   - }
  424 + // 证书有效标识(有证书的设备必选)缺省为0;证书有效标识:0:无效 1:有效
  425 + String certifiable = getText(itemDevice, "Certifiable");
  426 + if (!ObjectUtils.isEmpty(certifiable)) {
  427 + try {
  428 + deviceChannel.setCertifiable(Integer.parseInt(certifiable));
  429 + }catch (NumberFormatException e) {
  430 + logger.warn("[xml解析] 从通道数据获取 Certifiable失败: {}", certifiable);
  431 + }
  432 + }
378 433  
379   - deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
380   - deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
381   - deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
382   - if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") {
383   - deviceChannel.setPort(0);
384   - } else {
385   - deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
386   - }
  434 + // 无效原因码(有证书且证书无效的设备必选)
  435 + String errCode = getText(itemDevice, "ErrCode");
  436 + if (!ObjectUtils.isEmpty(errCode)) {
  437 + try {
  438 + deviceChannel.setErrCode(Integer.parseInt(errCode));
  439 + }catch (NumberFormatException e) {
  440 + logger.warn("[xml解析] 从通道数据获取 ErrCode失败: {}", errCode);
  441 + }
  442 + }
387 443  
  444 + // 证书终止有效期(有证书的设备必选)
  445 + String endTime = getText(itemDevice, "EndTime");
  446 + if (!ObjectUtils.isEmpty(endTime)) {
  447 + deviceChannel.setEndTime(endTime);
  448 + }
388 449  
389   - String longitude = XmlUtil.getText(itemDevice, "Longitude");
390   - if (NumericUtil.isDouble(longitude)) {
391   - deviceChannel.setLongitude(Double.parseDouble(longitude));
392   - } else {
393   - deviceChannel.setLongitude(0.00);
394   - }
395   - String latitude = XmlUtil.getText(itemDevice, "Latitude");
396   - if (NumericUtil.isDouble(latitude)) {
397   - deviceChannel.setLatitude(Double.parseDouble(latitude));
398   - } else {
399   - deviceChannel.setLatitude(0.00);
400   - }
401 450  
402   - deviceChannel.setGpsTime(DateUtil.getNow());
  451 + // 设备/区域/系统IP地址
  452 + String ipAddress = getText(itemDevice, "IPAddress");
  453 + if (!ObjectUtils.isEmpty(ipAddress)) {
  454 + deviceChannel.setIpAddress(ipAddress);
  455 + }
  456 +
  457 + // 设备/区域/系统端口
  458 + String port = getText(itemDevice, "Port");
  459 + if (!ObjectUtils.isEmpty(port)) {
  460 + try {
  461 + deviceChannel.setPort(Integer.parseInt(port));
  462 + }catch (NumberFormatException e) {
  463 + logger.warn("[xml解析] 从通道数据获取 Port失败: {}", port);
  464 + }
  465 + }
  466 +
  467 + // 设备口令
  468 + String password = getText(itemDevice, "Password");
  469 + if (!ObjectUtils.isEmpty(password)) {
  470 + deviceChannel.setPassword(password);
  471 + }
  472 +
403 473  
  474 + // 设备状态
  475 + String status = getText(itemDevice, "Status");
  476 + if (status != null) {
  477 + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
  478 + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
  479 + deviceChannel.setStatus(true);
  480 + }
  481 + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
  482 + deviceChannel.setStatus(false);
  483 + }
  484 + }else {
  485 + deviceChannel.setStatus(true);
  486 + }
  487 +
  488 + // 经度
  489 + String longitude = getText(itemDevice, "Longitude");
  490 + if (NumericUtil.isDouble(longitude)) {
  491 + deviceChannel.setLongitude(Double.parseDouble(longitude));
  492 + } else {
  493 + deviceChannel.setLongitude(0.00);
  494 + }
  495 +
  496 + // 纬度
  497 + String latitude = getText(itemDevice, "Latitude");
  498 + if (NumericUtil.isDouble(latitude)) {
  499 + deviceChannel.setLatitude(Double.parseDouble(latitude));
  500 + } else {
  501 + deviceChannel.setLatitude(0.00);
  502 + }
  503 +
  504 + deviceChannel.setGpsTime(DateUtil.getNow());
  505 +
  506 + // -摄像机类型扩展,标识摄像机类型:1-球机;2-半球;3-固定枪机;4-遥控枪机。当目录项为摄像机时可选
  507 + String ptzType = getText(itemDevice, "PTZType");
  508 + if (ObjectUtils.isEmpty(ptzType)) {
  509 + //兼容INFO中的信息
  510 + Element info = itemDevice.element("Info");
  511 + String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType");
  512 + if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){
  513 + try {
  514 + deviceChannel.setPTZType(Integer.parseInt(ptzTypeFromInfo));
  515 + }catch (NumberFormatException e){
  516 + logger.warn("[xml解析] 从通道数据info中获取PTZType失败: {}", ptzTypeFromInfo);
  517 + }
  518 + }
  519 + } else {
  520 + try {
  521 + deviceChannel.setPTZType(Integer.parseInt(ptzType));
  522 + }catch (NumberFormatException e){
  523 + logger.warn("[xml解析] 从通道数据中获取PTZType失败: {}", ptzType);
  524 + }
  525 + }
404 526  
405   - if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
406   - //兼容INFO中的信息
407   - Element info = itemDevice.element("Info");
408   - if(XmlUtil.getText(info, "PTZType") == null || "".equals(XmlUtil.getText(info, "PTZType"))){
409   - deviceChannel.setPTZType(0);
410   - }else{
411   - deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(info, "PTZType")));
  527 + // TODO 摄像机位置类型扩展。
  528 + // 1-省际检查站、
  529 + // 2-党政机关、
  530 + // 3-车站码头、
  531 + // 4-中心广场、
  532 + // 5-体育场馆、
  533 + // 6-商业中心、
  534 + // 7-宗教场所、
  535 + // 8-校园周边、
  536 + // 9-治安复杂区域、
  537 + // 10-交通干线。
  538 + // String positionType = getText(itemDevice, "PositionType");
  539 +
  540 + // TODO 摄像机安装位置室外、室内属性。1-室外、2-室内。
  541 + // String roomType = getText(itemDevice, "RoomType");
  542 + // TODO 摄像机用途属性
  543 + // String useType = getText(itemDevice, "UseType");
  544 + // TODO 摄像机补光属性。1-无补光、2-红外补光、3-白光补光
  545 + // String supplyLightType = getText(itemDevice, "SupplyLightType");
  546 + // TODO 摄像机监视方位属性。1-东、2-西、3-南、4-北、5-东南、6-东北、7-西南、8-西北。
  547 + // String directionType = getText(itemDevice, "DirectionType");
  548 + // TODO 摄像机支持的分辨率,可有多个分辨率值,各个取值间以“/”分隔。分辨率取值参见附录 F中SDPf字段规定
  549 + // String resolution = getText(itemDevice, "Resolution");
  550 +
  551 + // TODO 下载倍速范围(可选),各可选参数以“/”分隔,如设备支持1,2,4倍速下载则应写为“1/2/4
  552 + // String downloadSpeed = getText(itemDevice, "DownloadSpeed");
  553 + // TODO 空域编码能力,取值0:不支持;1:1级增强(1个增强层);2:2级增强(2个增强层);3:3级增强(3个增强层)
  554 + // String svcSpaceSupportMode = getText(itemDevice, "SVCSpaceSupportMode");
  555 + // TODO 时域编码能力,取值0:不支持;1:1级增强;2:2级增强;3:3级增强
  556 + // String svcTimeSupportMode = getText(itemDevice, "SVCTimeSupportMode");
  557 +
  558 +
  559 + deviceChannel.setSecrecy(secrecy);
  560 + break;
412 561 }
413   - } else {
414   - deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
415 562 }
416 563  
417 564 return deviceChannel;
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
... ... @@ -50,8 +50,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
50 50 device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
51 51 }
52 52  
53   -
54   -
55 53 if ("WGS84".equals(device.getGeoCoordSys())) {
56 54 deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
57 55 deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
... ... @@ -262,4 +260,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
262 260 }
263 261 }
264 262 }
  263 +
  264 +
265 265 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
... ... @@ -122,9 +122,10 @@ public class DeviceServiceImpl implements IDeviceService {
122 122 }
123 123  
124 124 // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
125   - if (device.getCreateTime() == null) {
  125 + if (deviceInDb == null) {
126 126 device.setOnLine(true);
127 127 device.setCreateTime(now);
  128 + device.setUpdateTime(now);
128 129 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
129 130 deviceMapper.add(device);
130 131 redisCatchStorage.updateDevice(device);
... ... @@ -389,63 +390,11 @@ public class DeviceServiceImpl implements IDeviceService {
389 390 if (device == null) {
390 391 return null;
391 392 }
392   - if (parentId == null || parentId.equals(deviceId)) {
393   - // 字根节点开始查询
394   - List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), true, !onlyCatalog);
395   - return transportChannelsToTree(rootNodes, "");
  393 + if (ObjectUtils.isEmpty(parentId) || parentId.equals(deviceId)) {
  394 + parentId = null;
396 395 }
397   -
398   - if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
399   - if (parentId.length()%2 != 0) {
400   - return null;
401   - }
402   - // 使用行政区划展示树
403   -// if (parentId.length() > 10) {
404   -// // TODO 可能是行政区划与业务分组混杂的情形
405   -// return null;
406   -// }
407   -
408   - if (parentId.length() == 10 ) {
409   - if (onlyCatalog) {
410   - return null;
411   - }
412   - // parentId为行业编码, 其下不会再有行政区划
413   - List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
414   - List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(channels, parentId);
415   - return trees;
416   - }
417   - // 查询其下的行政区划和摄像机
418   - List<DeviceChannel> channelsForCivilCode = deviceChannelMapper.getChannelsWithCivilCodeAndLength(deviceId, parentId, parentId.length() + 2);
419   - if (!onlyCatalog) {
420   - List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
421   -
422   - for(DeviceChannel channel : channels) {
423   - boolean flag = false;
424   - for(DeviceChannel deviceChannel : channelsForCivilCode) {
425   - if(channel.getChannelId().equals(deviceChannel.getChannelId())) {
426   - flag = true;
427   - }
428   - }
429   - if(!flag) {
430   - channelsForCivilCode.add(channel);
431   - }
432   - }
433   - }
434   - List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(channelsForCivilCode, parentId);
435   - return trees;
436   -
437   - }
438   - // 使用业务分组展示树
439   - if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
440   - if (parentId.length() < 14 ) {
441   - return null;
442   - }
443   - List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null);
444   - List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(deviceChannels, parentId);
445   - return trees;
446   - }
447   -
448   - return null;
  396 + List<DeviceChannel> rootNodes = deviceChannelMapper.getSubChannelsByDeviceId(deviceId, parentId, onlyCatalog);
  397 + return transportChannelsToTree(rootNodes, "");
449 398 }
450 399  
451 400 @Override
... ... @@ -454,42 +403,11 @@ public class DeviceServiceImpl implements IDeviceService {
454 403 if (device == null) {
455 404 return null;
456 405 }
457   - if (parentId == null || parentId.equals(deviceId)) {
458   - // 字根节点开始查询
459   - List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), false, true);
460   - return rootNodes;
461   - }
462   -
463   - if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
464   - if (parentId.length()%2 != 0) {
465   - return null;
466   - }
467   - // 使用行政区划展示树
468   - if (parentId.length() > 10) {
469   - // TODO 可能是行政区划与业务分组混杂的情形
470   - return null;
471   - }
472   -
473   - if (parentId.length() == 10 ) {
474   - // parentId为行业编码, 其下不会再有行政区划
475   - List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
476   - return channels;
477   - }
478   - // 查询其下的行政区划和摄像机
479   - List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
480   - return channels;
481   -
482   - }
483   - // 使用业务分组展示树
484   - if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
485   - if (parentId.length() < 14 ) {
486   - return null;
487   - }
488   - List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null);
489   - return deviceChannels;
  406 + if (ObjectUtils.isEmpty(parentId) || parentId.equals(deviceId)) {
  407 + return deviceChannelMapper.getSubChannelsByDeviceId(deviceId, null, false);
  408 + }else {
  409 + return deviceChannelMapper.getSubChannelsByDeviceId(deviceId, parentId, false);
490 410 }
491   -
492   - return null;
493 411 }
494 412  
495 413 private List<BaseTree<DeviceChannel>> transportChannelsToTree(List<DeviceChannel> channels, String parentId) {
... ... @@ -509,65 +427,26 @@ public class DeviceServiceImpl implements IDeviceService {
509 427 node.setPid(parentId);
510 428 node.setBasicData(channel);
511 429 node.setParent(false);
512   - if (channel.getChannelId().length() > 8) {
513   - if (channel.getChannelId().length() > 13) {
514   - String gbCodeType = channel.getChannelId().substring(10, 13);
515   - node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) );
516   - }
517   - }else {
  430 + if (channel.getChannelId().length() <= 8) {
518 431 node.setParent(true);
519   - }
520   - treeNotes.add(node);
521   - }
522   - Collections.sort(treeNotes);
523   - return treeNotes;
524   - }
525   -
526   - private List<DeviceChannel> getRootNodes(String deviceId, boolean isCivilCode, boolean haveCatalog, boolean haveChannel) {
527   - if (!haveCatalog && !haveChannel) {
528   - return null;
529   - }
530   - List<DeviceChannel> result = new ArrayList<>();
531   - if (isCivilCode) {
532   - // 使用行政区划
533   - Integer length= deviceChannelMapper.getChannelMinLength(deviceId);
534   - if (length == null) {
535   - return null;
536   - }
537   - if (length <= 10) {
538   - if (haveCatalog) {
539   - List<DeviceChannel> provinceNode = deviceChannelMapper.getChannelsWithCivilCodeAndLength(deviceId, null, length);
540   - if (provinceNode != null && provinceNode.size() > 0) {
541   - result.addAll(provinceNode);
542   - }
543   - }
544   -
545   - if (haveChannel) {
546   - // 查询那些civilCode不在通道中的不规范通道,放置在根目录
547   - List<DeviceChannel> nonstandardNode = deviceChannelMapper.getChannelWithoutCivilCode(deviceId);
548   - if (nonstandardNode != null && nonstandardNode.size() > 0) {
549   - result.addAll(nonstandardNode);
550   - }
551   - }
552 432 }else {
553   - if (haveChannel) {
554   - List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null,null);
555   - if (deviceChannels != null && deviceChannels.size() > 0) {
556   - result.addAll(deviceChannels);
  433 + if (channel.getChannelId().length() != 20) {
  434 + node.setParent(channel.getParental() == 1);
  435 + }else {
  436 + try {
  437 + int type = Integer.parseInt(channel.getChannelId().substring(10, 13));
  438 + if (type == 215 || type == 216 || type == 200) {
  439 + node.setParent(true);
  440 + }
  441 + }catch (NumberFormatException e) {
  442 + node.setParent(false);
557 443 }
558 444 }
559 445 }
560   -
561   - }else {
562   - // 使用业务分组+虚拟组织
563   -
564   - // 只获取业务分组
565   - List<DeviceChannel> deviceChannels = deviceChannelMapper.getBusinessGroups(deviceId, ChannelIdType.BUSINESS_GROUP);
566   - if (deviceChannels != null && deviceChannels.size() > 0) {
567   - result.addAll(deviceChannels);
568   - }
  446 + treeNotes.add(node);
569 447 }
570   - return result;
  448 + Collections.sort(treeNotes);
  449 + return treeNotes;
571 450 }
572 451  
573 452 @Override
... ... @@ -617,7 +496,6 @@ public class DeviceServiceImpl implements IDeviceService {
617 496 }
618 497 deviceInStore.setSdpIp(device.getSdpIp());
619 498 deviceInStore.setCharset(device.getCharset());
620   - deviceInStore.setTreeType(device.getTreeType());
621 499  
622 500 // 目录订阅相关的信息
623 501 if (device.getSubscribeCycleForCatalog() > 0) {
... ... @@ -673,6 +551,9 @@ public class DeviceServiceImpl implements IDeviceService {
673 551 }catch (Exception e) {
674 552 dataSourceTransactionManager.rollback(transactionStatus);
675 553 }
  554 + if (result) {
  555 + redisCatchStorage.removeDevice(deviceId);
  556 + }
676 557 return result;
677 558 }
678 559  
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
... ... @@ -113,20 +113,15 @@ public class GbStreamServiceImpl implements IGbStreamService {
113 113 deviceChannel.setStatus(gbStream.isStatus());
114 114  
115 115 deviceChannel.setRegisterWay(1);
116   - deviceChannel.setCivilCode(platform.getAdministrativeDivision());
117   -
118   - if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
119   - deviceChannel.setCivilCode(catalogId);
120   - }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
121   - PlatformCatalog catalog = catalogMapper.select(catalogId);
122   - if (catalog == null) {
123   - deviceChannel.setParentId(platform.getDeviceGBId());
124   - deviceChannel.setBusinessGroupId(null);
125   - }else {
126   - deviceChannel.setParentId(catalog.getId());
127   - deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
128   - }
129 116  
  117 + PlatformCatalog catalog = catalogMapper.select(catalogId);
  118 + if (catalog != null) {
  119 + deviceChannel.setCivilCode(catalog.getCivilCode());
  120 + deviceChannel.setParentId(catalog.getParentId());
  121 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
  122 + }else {
  123 + deviceChannel.setCivilCode(platform.getAdministrativeDivision());
  124 + deviceChannel.setParentId(platform.getDeviceGBId());
130 125 }
131 126  
132 127 deviceChannel.setModel("live");
... ... @@ -221,20 +216,14 @@ public class GbStreamServiceImpl implements IGbStreamService {
221 216 deviceChannel.setStatus(status != null && status);
222 217  
223 218 deviceChannel.setRegisterWay(1);
224   - deviceChannel.setCivilCode(platform.getAdministrativeDivision());
225   -
226   - if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
227   - deviceChannel.setCivilCode(catalogId);
228   - }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
229   - PlatformCatalog catalog = catalogMapper.select(catalogId);
230   - if (catalog == null) {
231   - deviceChannel.setParentId(platform.getDeviceGBId());
232   - deviceChannel.setBusinessGroupId(null);
233   - }else {
234   - deviceChannel.setParentId(catalog.getId());
235   - deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
236   - }
237   -
  219 + PlatformCatalog catalog = catalogMapper.select(catalogId);
  220 + if (catalog != null) {
  221 + deviceChannel.setCivilCode(catalog.getCivilCode());
  222 + deviceChannel.setParentId(catalog.getParentId());
  223 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
  224 + }else {
  225 + deviceChannel.setCivilCode(platform.getAdministrativeDivision());
  226 + deviceChannel.setParentId(platform.getDeviceGBId());
238 227 }
239 228  
240 229 deviceChannel.setModel("live");
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
... ... @@ -126,22 +126,17 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
126 126 List<DeviceChannel> deviceChannelList = new ArrayList<>();
127 127 if (channelReduces.size() > 0){
128 128 PlatformCatalog catalog = catalogManager.select(catalogId);
129   - if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) {
  129 + if (catalog == null || !catalogId.equals(platform.getDeviceGBId())) {
130 130 logger.warn("未查询到目录{}的信息", catalogId);
131 131 return null;
132 132 }
133 133 for (ChannelReduce channelReduce : channelReduces) {
134 134 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
135 135 deviceChannel.setParental(0);
  136 + deviceChannel.setCivilCode(catalog.getCivilCode());
  137 + deviceChannel.setParentId(catalog.getParentId());
  138 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
136 139 deviceChannelList.add(deviceChannel);
137   - if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
138   - deviceChannel.setCivilCode(catalogId);
139   - }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
140   - deviceChannel.setParentId(catalogId);
141   - if (catalog != null) {
142   - deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
143   - }
144   - }
145 140 }
146 141 }
147 142 return deviceChannelList;
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
... ... @@ -35,6 +35,8 @@ import java.util.Map;
35 35 public class PlatformServiceImpl implements IPlatformService {
36 36  
37 37 private final static String REGISTER_KEY_PREFIX = "platform_register_";
  38 +
  39 + private final static String REGISTER_FAIL_AGAIN_KEY_PREFIX = "platform_register_fail_again_";
38 40 private final static String KEEPALIVE_KEY_PREFIX = "platform_keepalive_";
39 41  
40 42 private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
... ... @@ -132,14 +134,6 @@ public class PlatformServiceImpl implements IPlatformService {
132 134 ParentPlatform parentPlatformOld = platformMapper.getParentPlatById(parentPlatform.getId());
133 135 ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatformOld.getServerGBId());
134 136 parentPlatform.setUpdateTime(DateUtil.getNow());
135   - if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) {
136   - // 目录结构发生变化,清空之前的关联关系
137   - logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId());
138   - catalogMapper.delByPlatformId(parentPlatformOld.getServerGBId());
139   - platformChannelMapper.delByPlatformId(parentPlatformOld.getServerGBId());
140   - platformGbStreamMapper.delByPlatformId(parentPlatformOld.getServerGBId());
141   - }
142   -
143 137  
144 138 // 停止心跳定时
145 139 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatformOld.getServerGBId();
... ... @@ -150,12 +144,11 @@ public class PlatformServiceImpl implements IPlatformService {
150 144 // 注销旧的
151 145 try {
152 146 if (parentPlatformOld.isStatus()) {
153   - logger.info("保存平台{}时发现平台在线,发送注销命令", parentPlatformOld.getServerGBId());
  147 + logger.info("保存平台{}时发现平台在线,发送注销命令", parentPlatformOld.getServerGBId());
154 148 commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> {
155 149 logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId());
156 150 });
157 151 }
158   -
159 152 } catch (InvalidArgumentException | ParseException | SipException e) {
160 153 logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
161 154 }
... ... @@ -188,9 +181,6 @@ public class PlatformServiceImpl implements IPlatformService {
188 181 logger.error("[命令发送失败] 国标级联: {}", e.getMessage());
189 182 }
190 183 }
191   - // 重新开启定时注册, 使用续订消息
192   - // 重新开始心跳保活
193   -
194 184  
195 185 return false;
196 186 }
... ... @@ -199,6 +189,9 @@ public class PlatformServiceImpl implements IPlatformService {
199 189 @Override
200 190 public void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo) {
201 191 logger.info("[国标级联]:{}, 平台上线", parentPlatform.getServerGBId());
  192 + final String registerFailAgainTaskKey = REGISTER_FAIL_AGAIN_KEY_PREFIX + parentPlatform.getServerGBId();
  193 + dynamicTask.stop(registerFailAgainTaskKey);
  194 +
202 195 platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true);
203 196 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
204 197 if (parentPlatformCatch == null) {
... ... @@ -239,15 +232,9 @@ public class PlatformServiceImpl implements IPlatformService {
239 232 // 此时是第三次心跳超时, 平台离线
240 233 if (platformCatch.getKeepAliveReply() == 2) {
241 234 // 设置平台离线,并重新注册
242   - logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId());
243   - try {
244   - commanderForPlatform.register(parentPlatform, eventResult1 -> {
245   - logger.info("[国标级联] {},三次心跳超时后再次发起注册仍然失败,开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
246   - offline(parentPlatform, false);
247   - }, null);
248   - } catch (InvalidArgumentException | ParseException | SipException e) {
249   - logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
250   - }
  235 + logger.info("[国标级联] 三次心跳超时, 平台{}({})离线", parentPlatform.getName(), parentPlatform.getServerGBId());
  236 + offline(parentPlatform, false);
  237 +
251 238 }
252 239  
253 240 }else {
... ... @@ -273,21 +260,22 @@ public class PlatformServiceImpl implements IPlatformService {
273 260  
274 261 private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){
275 262 try {
276   - // 设置超时重发, 后续从底层支持消息重发
277   - String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout";
278   - if (dynamicTask.isAlive(key)) {
279   - return;
  263 + // 不在同一个会话中续订则每次全新注册
  264 + if (!userSetting.isRegisterKeepIntDialog()) {
  265 + sipTransactionInfo = null;
  266 + }
  267 +
  268 + if (sipTransactionInfo == null) {
  269 + logger.info("[国标级联] 平台:{}注册即将到期,开始重新注册", parentPlatform.getServerGBId());
  270 + }else {
  271 + logger.info("[国标级联] 平台:{}注册即将到期,开始续订", parentPlatform.getServerGBId());
280 272 }
281   - dynamicTask.startDelay(key, ()->{
282   - registerTask(parentPlatform, sipTransactionInfo);
283   - }, 1000);
284   - logger.info("[国标级联] 平台:{}注册即将到期,开始续订", parentPlatform.getServerGBId());
  273 +
285 274 commanderForPlatform.register(parentPlatform, sipTransactionInfo, eventResult -> {
286   - dynamicTask.stop(key);
  275 + logger.info("[国标级联] 平台:{}注册失败,{}:{}", parentPlatform.getServerGBId(),
  276 + eventResult.statusCode, eventResult.msg);
287 277 offline(parentPlatform, false);
288   - },eventResult -> {
289   - dynamicTask.stop(key);
290   - });
  278 + }, null);
291 279 } catch (InvalidArgumentException | ParseException | SipException e) {
292 280 logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
293 281 }
... ... @@ -308,24 +296,35 @@ public class PlatformServiceImpl implements IPlatformService {
308 296 // 停止所有推流
309 297 logger.info("[平台离线] {}, 停止所有推流", parentPlatform.getServerGBId());
310 298 stopAllPush(parentPlatform.getServerGBId());
311   - if (stopRegister) {
312   - // 清除注册定时
313   - logger.info("[平台离线] {}, 停止定时注册任务", parentPlatform.getServerGBId());
314   - final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
315   - if (dynamicTask.contains(registerTaskKey)) {
316   - dynamicTask.stop(registerTaskKey);
317   - }
  299 +
  300 + // 清除注册定时
  301 + logger.info("[平台离线] {}, 停止定时注册任务", parentPlatform.getServerGBId());
  302 + final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
  303 + if (dynamicTask.contains(registerTaskKey)) {
  304 + dynamicTask.stop(registerTaskKey);
318 305 }
319 306 // 清除心跳定时
320 307 logger.info("[平台离线] {}, 停止定时发送心跳任务", parentPlatform.getServerGBId());
321 308 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
322 309 if (dynamicTask.contains(keepaliveTaskKey)) {
323   - // 添加心跳任务
  310 + // 清除心跳任务
324 311 dynamicTask.stop(keepaliveTaskKey);
325 312 }
326 313 // 停止目录订阅回复
327 314 logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId());
328 315 subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
  316 + // 发起定时自动重新注册
  317 + if (!stopRegister) {
  318 + // 设置为60秒自动尝试重新注册
  319 + final String registerFailAgainTaskKey = REGISTER_FAIL_AGAIN_KEY_PREFIX + parentPlatform.getServerGBId();
  320 + ParentPlatform platform = platformMapper.getParentPlatById(parentPlatform.getId());
  321 + if (platform.isEnable()) {
  322 + dynamicTask.startCron(registerFailAgainTaskKey,
  323 + ()-> registerTask(platform, null),
  324 + userSetting.getRegisterAgainAfterTime() * 1000);
  325 + }
  326 +
  327 + }
329 328 }
330 329  
331 330 private void stopAllPush(String platformId) {
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
... ... @@ -451,10 +451,18 @@ public interface DeviceChannelMapper {
451 451 @Select("select count(1) from wvp_device_channel")
452 452 int getAllChannelCount();
453 453  
454   -
455   - /*=================设备主子码流逻辑START==============*/
  454 + // 设备主子码流逻辑START
456 455 @Update(value = {"UPDATE wvp_device_channel SET stream_id=null WHERE device_id=#{deviceId}"})
457 456 void clearPlay(String deviceId);
458   - /*=================设备主子码流逻辑END==============*/
  457 + // 设备主子码流逻辑END
  458 + @Select(value = {" <script>" +
  459 + "select * " +
  460 + "from device_channel " +
  461 + "where device_id=#{deviceId}" +
  462 + " <if test='parentId != null '> and parent_id = #{parentId} </if>" +
  463 + " <if test='parentId == null '> and parent_id is null </if>" +
  464 + " <if test='onlyCatalog == true '> and parental = 1 </if>" +
  465 + " </script>"})
  466 + List<DeviceChannel> getSubChannelsByDeviceId(String deviceId, String parentId, boolean onlyCatalog);
459 467  
460 468 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
... ... @@ -40,7 +40,6 @@ public interface DeviceMapper {
40 40 "ssrc_check," +
41 41 "as_message_channel," +
42 42 "geo_coord_sys," +
43   - "tree_type," +
44 43 "on_line," +
45 44 "media_server_id," +
46 45 "switch_primary_sub_stream," +
... ... @@ -75,7 +74,6 @@ public interface DeviceMapper {
75 74 "ssrc_check,"+
76 75 "as_message_channel,"+
77 76 "geo_coord_sys,"+
78   - "tree_type,"+
79 77 "on_line"+
80 78 ") VALUES (" +
81 79 "#{deviceId}," +
... ... @@ -104,7 +102,6 @@ public interface DeviceMapper {
104 102 "#{ssrcCheck}," +
105 103 "#{asMessageChannel}," +
106 104 "#{geoCoordSys}," +
107   - "#{treeType}," +
108 105 "#{onLine}" +
109 106 ")")
110 107 int add(Device device);
... ... @@ -159,7 +156,6 @@ public interface DeviceMapper {
159 156 "ssrc_check,"+
160 157 "as_message_channel,"+
161 158 "geo_coord_sys,"+
162   - "tree_type,"+
163 159 "on_line,"+
164 160 "media_server_id,"+
165 161 "switch_primary_sub_stream switchPrimarySubStream,"+
... ... @@ -201,7 +197,6 @@ public interface DeviceMapper {
201 197 "ssrc_check,"+
202 198 "as_message_channel,"+
203 199 "geo_coord_sys,"+
204   - "tree_type,"+
205 200 "on_line"+
206 201 " FROM wvp_device WHERE on_line = true")
207 202 List<Device> getOnlineDevices();
... ... @@ -232,7 +227,6 @@ public interface DeviceMapper {
232 227 "ssrc_check,"+
233 228 "as_message_channel,"+
234 229 "geo_coord_sys,"+
235   - "tree_type,"+
236 230 "on_line"+
237 231 " FROM wvp_device WHERE ip = #{host} AND port=#{port}")
238 232 Device getDeviceByHostAndPort(String host, int port);
... ... @@ -254,7 +248,6 @@ public interface DeviceMapper {
254 248 "<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" +
255 249 "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
256 250 "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
257   - "<if test=\"treeType != null\">, tree_type=#{treeType}</if>" +
258 251 "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +
259 252 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
260 253 "WHERE device_id=#{deviceId}"+
... ... @@ -272,7 +265,6 @@ public interface DeviceMapper {
272 265 "ssrc_check,"+
273 266 "as_message_channel,"+
274 267 "geo_coord_sys,"+
275   - "tree_type,"+
276 268 "on_line,"+
277 269 "media_server_id,"+
278 270 "switch_primary_sub_stream"+
... ... @@ -287,7 +279,6 @@ public interface DeviceMapper {
287 279 "#{ssrcCheck}," +
288 280 "#{asMessageChannel}," +
289 281 "#{geoCoordSys}," +
290   - "#{treeType}," +
291 282 "#{onLine}," +
292 283 "#{mediaServerId}," +
293 284 "#{switchPrimarySubStream}" +
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
... ... @@ -16,10 +16,10 @@ public interface ParentPlatformMapper {
16 16  
17 17 @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+
18 18 "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,"+
19   - "status,start_offline_push,catalog_id,administrative_division,catalog_group,create_time,update_time,tree_type) " +
  19 + "status,start_offline_push,catalog_id,administrative_division,catalog_group,create_time,update_time) " +
20 20 " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
21 21 " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " +
22   - " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
  22 + " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})")
23 23 int addParentPlatform(ParentPlatform parentPlatform);
24 24  
25 25 @Update("UPDATE wvp_platform " +
... ... @@ -47,7 +47,6 @@ public interface ParentPlatformMapper {
47 47 "administrative_division=#{administrativeDivision}, " +
48 48 "create_time=#{createTime}, " +
49 49 "update_time=#{updateTime}, " +
50   - "tree_type=#{treeType}, " +
51 50 "catalog_id=#{catalogId} " +
52 51 "WHERE id=#{id}")
53 52 int updateParentPlatform(ParentPlatform parentPlatform);
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
... ... @@ -128,51 +128,56 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
128 128 List<DeviceChannel> addChannels = new ArrayList<>();
129 129 StringBuilder stringBuilder = new StringBuilder();
130 130 Map<String, Integer> subContMap = new HashMap<>();
131   - if (deviceChannelList.size() > 0) {
132   - // 数据去重
133   - Set<String> gbIdSet = new HashSet<>();
134   - for (DeviceChannel deviceChannel : deviceChannelList) {
135   - if (!gbIdSet.contains(deviceChannel.getChannelId())) {
136   - gbIdSet.add(deviceChannel.getChannelId());
137   - deviceChannel.setUpdateTime(DateUtil.getNow());
138   - if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
139   - deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
140   - deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
141   - if (allChannelMap.get(deviceChannel.getChannelId()).isStatus() !=deviceChannel.isStatus()){
142   - List<String> strings = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getChannelId());
143   - if (!CollectionUtils.isEmpty(strings)){
144   - strings.forEach(platformId->{
145   - eventPublisher.catalogEventPublish(platformId, deviceChannel, deviceChannel.isStatus()?CatalogEvent.ON:CatalogEvent.OFF);
146   - });
147   - }
148   - }
149   - updateChannels.add(deviceChannel);
150   - }else {
151   - deviceChannel.setCreateTime(DateUtil.getNow());
152   - addChannels.add(deviceChannel);
153   - }
154   - channels.add(deviceChannel);
155   - if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
156   - if (subContMap.get(deviceChannel.getParentId()) == null) {
157   - subContMap.put(deviceChannel.getParentId(), 1);
158   - }else {
159   - Integer count = subContMap.get(deviceChannel.getParentId());
160   - subContMap.put(deviceChannel.getParentId(), count++);
161   - }
  131 +
  132 + // 数据去重
  133 + Set<String> gbIdSet = new HashSet<>();
  134 + for (DeviceChannel deviceChannel : deviceChannelList) {
  135 + if (gbIdSet.contains(deviceChannel.getChannelId())) {
  136 + stringBuilder.append(deviceChannel.getChannelId()).append(",");
  137 + continue;
  138 + }
  139 + gbIdSet.add(deviceChannel.getChannelId());
  140 + if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
  141 + deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
  142 + deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
  143 + if (allChannelMap.get(deviceChannel.getChannelId()).isStatus() !=deviceChannel.isStatus()){
  144 + List<String> strings = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getChannelId());
  145 + if (!CollectionUtils.isEmpty(strings)){
  146 + strings.forEach(platformId->{
  147 + eventPublisher.catalogEventPublish(platformId, deviceChannel, deviceChannel.isStatus()?CatalogEvent.ON:CatalogEvent.OFF);
  148 + });
162 149 }
  150 +
  151 + }
  152 + deviceChannel.setUpdateTime(DateUtil.getNow());
  153 + updateChannels.add(deviceChannel);
  154 + }else {
  155 + deviceChannel.setCreateTime(DateUtil.getNow());
  156 + deviceChannel.setUpdateTime(DateUtil.getNow());
  157 + addChannels.add(deviceChannel);
  158 + }
  159 + channels.add(deviceChannel);
  160 + if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
  161 + if (subContMap.get(deviceChannel.getParentId()) == null) {
  162 + subContMap.put(deviceChannel.getParentId(), 1);
163 163 }else {
164   - stringBuilder.append(deviceChannel.getChannelId()).append(",");
  164 + Integer count = subContMap.get(deviceChannel.getParentId());
  165 + subContMap.put(deviceChannel.getParentId(), count++);
165 166 }
166 167 }
167   - if (channels.size() > 0) {
168   - for (DeviceChannel channel : channels) {
169   - if (subContMap.get(channel.getChannelId()) != null){
170   - channel.setSubCount(subContMap.get(channel.getChannelId()));
  168 + }
  169 + if (channels.size() > 0) {
  170 + for (DeviceChannel channel : channels) {
  171 + if (subContMap.get(channel.getChannelId()) != null){
  172 + Integer count = subContMap.get(channel.getChannelId());
  173 + if (count > 0) {
  174 + channel.setSubCount(count);
  175 + channel.setParental(1);
171 176 }
172 177 }
173 178 }
174   -
175 179 }
  180 +
176 181 if (stringBuilder.length() > 0) {
177 182 logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder);
178 183 }
... ... @@ -795,25 +800,49 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
795 800 if (platform == null) {
796 801 return 0;
797 802 }
798   - if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
799   - if (platform.getDeviceGBId().equals(platformCatalog.getParentId())) {
800   - // 第一层节点
801   - platformCatalog.setBusinessGroupId(platformCatalog.getId());
802   - platformCatalog.setParentId(platform.getDeviceGBId());
803   - }else {
804   - // 获取顶层的
805   - PlatformCatalog topCatalog = getTopCatalog(platformCatalog.getParentId(), platform.getDeviceGBId());
806   - platformCatalog.setBusinessGroupId(topCatalog.getId());
  803 + if (platformCatalog.getId().length() <= 8) {
  804 + platformCatalog.setCivilCode(platformCatalog.getParentId());
  805 + }else {
  806 + if (platformCatalog.getId().length() != 20) {
  807 + return 0;
807 808 }
808   - }
809   - if (platform.getTreeType().equals(TreeType.CIVIL_CODE)) {
810   - platformCatalog.setCivilCode(platformCatalog.getId());
811   - if (platformCatalog.getPlatformId().equals(platformCatalog.getParentId())) {
812   - // 第一层节点
813   - platformCatalog.setParentId(platform.getDeviceGBId());
  809 + if (platformCatalog.getParentId() != null) {
  810 + switch (Integer.parseInt(platformCatalog.getId().substring(10, 13))){
  811 + case 200:
  812 + case 215:
  813 + if (platformCatalog.getParentId().length() <= 8) {
  814 + platformCatalog.setCivilCode(platformCatalog.getParentId());
  815 + }else {
  816 + PlatformCatalog catalog = catalogMapper.select(platformCatalog.getParentId());
  817 + if (catalog != null) {
  818 + platformCatalog.setCivilCode(catalog.getCivilCode());
  819 + }
  820 + }
  821 + break;
  822 + case 216:
  823 + if (platformCatalog.getParentId().length() <= 8) {
  824 + platformCatalog.setCivilCode(platformCatalog.getParentId());
  825 + }else {
  826 + PlatformCatalog catalog = catalogMapper.select(platformCatalog.getParentId());
  827 + if (catalog == null) {
  828 + logger.warn("[添加目录] 无法获取目录{}的CivilCode和BusinessGroupId", platformCatalog.getPlatformId());
  829 + break;
  830 + }
  831 + platformCatalog.setCivilCode(catalog.getCivilCode());
  832 + if (Integer.parseInt(platformCatalog.getParentId().substring(10, 13)) == 215) {
  833 + platformCatalog.setBusinessGroupId(platformCatalog.getParentId());
  834 + }else {
  835 + if (Integer.parseInt(platformCatalog.getParentId().substring(10, 13)) == 216) {
  836 + platformCatalog.setBusinessGroupId(catalog.getBusinessGroupId());
  837 + }
  838 + }
  839 + }
  840 + break;
  841 + default:
  842 + break;
  843 + }
814 844 }
815 845 }
816   -
817 846 int result = catalogMapper.add(platformCatalog);
818 847 if (result > 0) {
819 848 DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog);
... ... @@ -937,19 +966,14 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
937 966 DeviceChannel deviceChannel = new DeviceChannel();
938 967 deviceChannel.setChannelId(catalog.getId());
939 968 deviceChannel.setName(catalog.getName());
940   - deviceChannel.setLongitude(0.0);
941   - deviceChannel.setLatitude(0.0);
942 969 deviceChannel.setDeviceId(platform.getDeviceGBId());
943 970 deviceChannel.setManufacture("wvp-pro");
944 971 deviceChannel.setStatus(true);
945 972 deviceChannel.setParental(1);
946 973  
947 974 deviceChannel.setRegisterWay(1);
948   - // 行政区划应该是Domain的前八位
949   - if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
950   - deviceChannel.setParentId(catalog.getParentId());
951   - deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
952   - }
  975 + deviceChannel.setParentId(catalog.getParentId());
  976 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
953 977  
954 978 deviceChannel.setModel("live");
955 979 deviceChannel.setOwner("wvp-pro");
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
... ... @@ -403,8 +403,12 @@ public class PlatformController {
403 403 if (platform == null) {
404 404 throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台未找到");
405 405 }
406   - if (platformId.equals(parentId)) {
407   - parentId = platform.getDeviceGBId();
  406 +// if (platformId.equals(parentId)) {
  407 +// parentId = platform.getDeviceGBId();
  408 +// }
  409 +
  410 + if (platformId.equals(platform.getDeviceGBId())) {
  411 + parentId = null;
408 412 }
409 413  
410 414 return storager.getChildrenCatalogByPlatform(platformId, parentId);
... ...
src/main/resources/all-application.yml
... ... @@ -202,6 +202,10 @@ user-settings:
202 202 device-status-notify: false
203 203 # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
204 204 use-custom-ssrc-for-parent-invite: true
  205 + # 国标级联离线后多久重试一次注册
  206 + register-again-after-time: 60
  207 + # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
  208 + register-keep-int-dialog: false
205 209 # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个
206 210 allowed-origins:
207 211 - http://localhost:8008
... ...