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,7 +38,7 @@ alter table device
38 change geoCoordSys geo_coord_sys varchar(50) not null; 38 change geoCoordSys geo_coord_sys varchar(50) not null;
39 39
40 alter table device 40 alter table device
41 - change treeType tree_type varchar(50) not null; 41 + drop column treeType;
42 42
43 alter table device 43 alter table device
44 change mediaServerId media_server_id varchar(50) default 'auto' null; 44 change mediaServerId media_server_id varchar(50) default 'auto' null;
@@ -297,7 +297,7 @@ alter table parent_platform @@ -297,7 +297,7 @@ alter table parent_platform
297 change updateTime update_time varchar(50) null; 297 change updateTime update_time varchar(50) null;
298 298
299 alter table parent_platform 299 alter table parent_platform
300 - change treeType tree_type varchar(50) not null; 300 + drop column treeType;
301 301
302 alter table parent_platform 302 alter table parent_platform
303 change asMessageChannel as_message_channel bool default false; 303 change asMessageChannel as_message_channel bool default false;
sql/初始化.sql
@@ -24,7 +24,6 @@ create table wvp_device ( @@ -24,7 +24,6 @@ create table wvp_device (
24 charset character varying(50), 24 charset character varying(50),
25 ssrc_check bool default false, 25 ssrc_check bool default false,
26 geo_coord_sys character varying(50), 26 geo_coord_sys character varying(50),
27 - tree_type character varying(50),  
28 media_server_id character varying(50), 27 media_server_id character varying(50),
29 custom_name character varying(255), 28 custom_name character varying(255),
30 sdp_ip character varying(50), 29 sdp_ip character varying(50),
@@ -187,7 +186,6 @@ create table wvp_platform ( @@ -187,7 +186,6 @@ create table wvp_platform (
187 catalog_group integer, 186 catalog_group integer,
188 create_time character varying(50), 187 create_time character varying(50),
189 update_time character varying(50), 188 update_time character varying(50),
190 - tree_type character varying(50),  
191 as_message_channel bool default false, 189 as_message_channel bool default false,
192 constraint uk_platform_unique_server_gb_id unique (server_gb_id) 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,6 +45,7 @@ public class DynamicTask {
45 * @return 45 * @return
46 */ 46 */
47 public void startCron(String key, Runnable task, int cycleForCatalog) { 47 public void startCron(String key, Runnable task, int cycleForCatalog) {
  48 + System.out.println(cycleForCatalog);
48 ScheduledFuture<?> future = futureMap.get(key); 49 ScheduledFuture<?> future = futureMap.get(key);
49 if (future != null) { 50 if (future != null) {
50 if (future.isCancelled()) { 51 if (future.isCancelled()) {
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
@@ -56,7 +56,7 @@ public class SipPlatformRunner implements CommandLineRunner { @@ -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,7 +63,7 @@ public class UserSetting {
63 63
64 private String thirdPartyGBIdReg = "[\\s\\S]*"; 64 private String thirdPartyGBIdReg = "[\\s\\S]*";
65 65
66 - 66 + private String civilCodeFile = "classpath:civilCode.csv";
67 67
68 private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); 68 private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
69 69
@@ -71,6 +71,10 @@ public class UserSetting { @@ -71,6 +71,10 @@ public class UserSetting {
71 71
72 private int maxNotifyCountQueue = 10000; 72 private int maxNotifyCountQueue = 10000;
73 73
  74 + private int registerAgainAfterTime = 60;
  75 +
  76 + private boolean registerKeepIntDialog = false;
  77 +
74 public Boolean getSavePositionHistory() { 78 public Boolean getSavePositionHistory() {
75 return savePositionHistory; 79 return savePositionHistory;
76 } 80 }
@@ -299,9 +303,27 @@ public class UserSetting { @@ -299,9 +303,27 @@ public class UserSetting {
299 this.sqlLog = sqlLog; 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,12 +173,6 @@ public class Device {
173 @Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02") 173 @Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02")
174 private String geoCoordSys; 174 private String geoCoordSys;
175 175
176 - /**  
177 - * 树类型 国标规定了两种树的展现方式 行政区划:CivilCode 和业务分组:BusinessGroup  
178 - */  
179 - @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划:CivilCode 和业务分组:BusinessGroup")  
180 - private String treeType;  
181 -  
182 @Schema(description = "密码") 176 @Schema(description = "密码")
183 private String password; 177 private String password;
184 178
@@ -408,14 +402,6 @@ public class Device { @@ -408,14 +402,6 @@ public class Device {
408 this.geoCoordSys = geoCoordSys; 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 public String getPassword() { 405 public String getPassword() {
420 return password; 406 return password;
421 } 407 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -183,12 +183,6 @@ public class ParentPlatform { @@ -183,12 +183,6 @@ public class ParentPlatform {
183 @Schema(description = "创建时间") 183 @Schema(description = "创建时间")
184 private String createTime; 184 private String createTime;
185 185
186 - /**  
187 - * 树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGroup  
188 - */  
189 - @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou")  
190 - private String treeType;  
191 -  
192 @Schema(description = "是否作为消息通道") 186 @Schema(description = "是否作为消息通道")
193 private boolean asMessageChannel; 187 private boolean asMessageChannel;
194 188
@@ -424,14 +418,6 @@ public class ParentPlatform { @@ -424,14 +418,6 @@ public class ParentPlatform {
424 this.createTime = createTime; 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 public boolean isAsMessageChannel() { 421 public boolean isAsMessageChannel() {
436 return asMessageChannel; 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,59 +209,149 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
209 // 行政区划分组只需要这两项就可以 209 // 行政区划分组只需要这两项就可以
210 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); 210 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
211 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); 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,6 +188,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
188 logger.error("[命令发送失败] invite GONE: {}", e.getMessage()); 188 logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
189 } 189 }
190 return; 190 return;
  191 + }else {
  192 + // TODO 可能漏回复消息
191 } 193 }
192 } 194 }
193 } else { 195 } else {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2
  3 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
3 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
@@ -20,7 +21,10 @@ import org.springframework.stereotype.Component; @@ -20,7 +21,10 @@ import org.springframework.stereotype.Component;
20 21
21 import javax.sip.RequestEvent; 22 import javax.sip.RequestEvent;
22 import javax.sip.header.FromHeader; 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 import java.util.concurrent.ConcurrentHashMap; 28 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.CopyOnWriteArrayList; 29 import java.util.concurrent.CopyOnWriteArrayList;
26 30
@@ -56,6 +60,9 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -56,6 +60,9 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
56 @Autowired 60 @Autowired
57 private DynamicTask dynamicTask; 61 private DynamicTask dynamicTask;
58 62
  63 + @Autowired
  64 + private CivilCodeFileConf civilCodeFileConf;
  65 +
59 private final static String talkKey = "notify-request-for-catalog-task"; 66 private final static String talkKey = "notify-request-for-catalog-task";
60 67
61 public void process(RequestEvent evt) { 68 public void process(RequestEvent evt) {
@@ -96,7 +103,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -96,7 +103,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
96 }else { 103 }else {
97 event = eventElement.getText().toUpperCase(); 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 channel.setDeviceId(device.getDeviceId()); 108 channel.setDeviceId(device.getDeviceId());
102 logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); 109 logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
4 import com.genersoft.iot.vmp.conf.SipConfig; 5 import com.genersoft.iot.vmp.conf.SipConfig;
5 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
6 import com.genersoft.iot.vmp.gb28181.bean.*; 7 import com.genersoft.iot.vmp.gb28181.bean.*;
@@ -79,6 +80,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -79,6 +80,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
79 @Autowired 80 @Autowired
80 private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor; 81 private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor;
81 82
  83 + @Autowired
  84 + private CivilCodeFileConf civilCodeFileConf;
  85 +
82 private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); 86 private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
83 87
84 @Qualifier("taskExecutor") 88 @Qualifier("taskExecutor")
@@ -408,7 +412,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -408,7 +412,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
408 }else { 412 }else {
409 event = eventElement.getText().toUpperCase(); 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 channel.setDeviceId(device.getDeviceId()); 416 channel.setDeviceId(device.getDeviceId());
413 logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); 417 logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
414 switch (event) { 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,7 +164,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
164 device.setStreamMode("UDP"); 164 device.setStreamMode("UDP");
165 device.setCharset("GB2312"); 165 device.setCharset("GB2312");
166 device.setGeoCoordSys("WGS84"); 166 device.setGeoCoordSys("WGS84");
167 - device.setTreeType("CivilCode");  
168 device.setDeviceId(deviceId); 167 device.setDeviceId(deviceId);
169 device.setOnLine(false); 168 device.setOnLine(false);
170 } 169 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; 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 import com.genersoft.iot.vmp.gb28181.bean.*; 4 import com.genersoft.iot.vmp.gb28181.bean.*;
4 import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch; 5 import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch;
5 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 6 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@@ -53,6 +54,9 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -53,6 +54,9 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
53 @Autowired 54 @Autowired
54 private ThreadPoolTaskExecutor taskExecutor; 55 private ThreadPoolTaskExecutor taskExecutor;
55 56
  57 + @Autowired
  58 + private CivilCodeFileConf civilCodeFileConf;
  59 +
56 @Override 60 @Override
57 public void afterPropertiesSet() throws Exception { 61 public void afterPropertiesSet() throws Exception {
58 responseMessageHandler.addHandler(cmdType, this); 62 responseMessageHandler.addHandler(cmdType, this);
@@ -100,6 +104,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -100,6 +104,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
100 Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); 104 Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
101 if (deviceListIterator != null) { 105 if (deviceListIterator != null) {
102 List<DeviceChannel> channelList = new ArrayList<>(); 106 List<DeviceChannel> channelList = new ArrayList<>();
  107 + List<String> parentChannelIds = new ArrayList<>();
103 // 遍历DeviceList 108 // 遍历DeviceList
104 while (deviceListIterator.hasNext()) { 109 while (deviceListIterator.hasNext()) {
105 Element itemDevice = deviceListIterator.next(); 110 Element itemDevice = deviceListIterator.next();
@@ -107,7 +112,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -107,7 +112,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
107 if (channelDeviceElement == null) { 112 if (channelDeviceElement == null) {
108 continue; 113 continue;
109 } 114 }
110 - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null); 115 + DeviceChannel deviceChannel = XmlUtil.channelContentHandler(itemDevice, device, null, civilCodeFileConf);
111 deviceChannel = SipUtils.updateGps(deviceChannel, device.getGeoCoordSys()); 116 deviceChannel = SipUtils.updateGps(deviceChannel, device.getGeoCoordSys());
112 deviceChannel.setDeviceId(take.getDevice().getDeviceId()); 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,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.utils;
2 2
3 import com.alibaba.fastjson2.JSONArray; 3 import com.alibaba.fastjson2.JSONArray;
4 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
  5 +import com.genersoft.iot.vmp.common.CivilCodePo;
  6 +import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
7 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 9 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
@@ -192,7 +194,7 @@ public class XmlUtil { @@ -192,7 +194,7 @@ public class XmlUtil {
192 CivilCode, BusinessGroup,VirtualOrganization,Other 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 DeviceChannel deviceChannel = new DeviceChannel(); 198 DeviceChannel deviceChannel = new DeviceChannel();
197 deviceChannel.setDeviceId(device.getDeviceId()); 199 deviceChannel.setDeviceId(device.getDeviceId());
198 Element channdelIdElement = itemDevice.element("DeviceID"); 200 Element channdelIdElement = itemDevice.element("DeviceID");
@@ -210,208 +212,353 @@ public class XmlUtil { @@ -210,208 +212,353 @@ public class XmlUtil {
210 // 除了ADD和update情况下需要识别全部内容, 212 // 除了ADD和update情况下需要识别全部内容,
211 return deviceChannel; 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 deviceChannel.setStatus(true); 228 deviceChannel.setStatus(true);
259 - deviceChannel.setParental(1);  
260 - deviceChannel.setCreateTime(DateUtil.getNow());  
261 - deviceChannel.setUpdateTime(DateUtil.getNow());  
262 return deviceChannel; 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 }else { 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 return deviceChannel; 564 return deviceChannel;
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
@@ -50,8 +50,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { @@ -50,8 +50,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
50 device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId()); 50 device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
51 } 51 }
52 52
53 -  
54 -  
55 if ("WGS84".equals(device.getGeoCoordSys())) { 53 if ("WGS84".equals(device.getGeoCoordSys())) {
56 deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); 54 deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
57 deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); 55 deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
@@ -262,4 +260,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { @@ -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,9 +122,10 @@ public class DeviceServiceImpl implements IDeviceService {
122 } 122 }
123 123
124 // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 124 // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
125 - if (device.getCreateTime() == null) { 125 + if (deviceInDb == null) {
126 device.setOnLine(true); 126 device.setOnLine(true);
127 device.setCreateTime(now); 127 device.setCreateTime(now);
  128 + device.setUpdateTime(now);
128 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId()); 129 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
129 deviceMapper.add(device); 130 deviceMapper.add(device);
130 redisCatchStorage.updateDevice(device); 131 redisCatchStorage.updateDevice(device);
@@ -389,63 +390,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -389,63 +390,11 @@ public class DeviceServiceImpl implements IDeviceService {
389 if (device == null) { 390 if (device == null) {
390 return null; 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 @Override 400 @Override
@@ -454,42 +403,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -454,42 +403,11 @@ public class DeviceServiceImpl implements IDeviceService {
454 if (device == null) { 403 if (device == null) {
455 return null; 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 private List<BaseTree<DeviceChannel>> transportChannelsToTree(List<DeviceChannel> channels, String parentId) { 413 private List<BaseTree<DeviceChannel>> transportChannelsToTree(List<DeviceChannel> channels, String parentId) {
@@ -509,65 +427,26 @@ public class DeviceServiceImpl implements IDeviceService { @@ -509,65 +427,26 @@ public class DeviceServiceImpl implements IDeviceService {
509 node.setPid(parentId); 427 node.setPid(parentId);
510 node.setBasicData(channel); 428 node.setBasicData(channel);
511 node.setParent(false); 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 node.setParent(true); 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 }else { 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 @Override 452 @Override
@@ -617,7 +496,6 @@ public class DeviceServiceImpl implements IDeviceService { @@ -617,7 +496,6 @@ public class DeviceServiceImpl implements IDeviceService {
617 } 496 }
618 deviceInStore.setSdpIp(device.getSdpIp()); 497 deviceInStore.setSdpIp(device.getSdpIp());
619 deviceInStore.setCharset(device.getCharset()); 498 deviceInStore.setCharset(device.getCharset());
620 - deviceInStore.setTreeType(device.getTreeType());  
621 499
622 // 目录订阅相关的信息 500 // 目录订阅相关的信息
623 if (device.getSubscribeCycleForCatalog() > 0) { 501 if (device.getSubscribeCycleForCatalog() > 0) {
@@ -673,6 +551,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -673,6 +551,9 @@ public class DeviceServiceImpl implements IDeviceService {
673 }catch (Exception e) { 551 }catch (Exception e) {
674 dataSourceTransactionManager.rollback(transactionStatus); 552 dataSourceTransactionManager.rollback(transactionStatus);
675 } 553 }
  554 + if (result) {
  555 + redisCatchStorage.removeDevice(deviceId);
  556 + }
676 return result; 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,20 +113,15 @@ public class GbStreamServiceImpl implements IGbStreamService {
113 deviceChannel.setStatus(gbStream.isStatus()); 113 deviceChannel.setStatus(gbStream.isStatus());
114 114
115 deviceChannel.setRegisterWay(1); 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 deviceChannel.setModel("live"); 127 deviceChannel.setModel("live");
@@ -221,20 +216,14 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -221,20 +216,14 @@ public class GbStreamServiceImpl implements IGbStreamService {
221 deviceChannel.setStatus(status != null && status); 216 deviceChannel.setStatus(status != null && status);
222 217
223 deviceChannel.setRegisterWay(1); 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 deviceChannel.setModel("live"); 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,22 +126,17 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
126 List<DeviceChannel> deviceChannelList = new ArrayList<>(); 126 List<DeviceChannel> deviceChannelList = new ArrayList<>();
127 if (channelReduces.size() > 0){ 127 if (channelReduces.size() > 0){
128 PlatformCatalog catalog = catalogManager.select(catalogId); 128 PlatformCatalog catalog = catalogManager.select(catalogId);
129 - if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) { 129 + if (catalog == null || !catalogId.equals(platform.getDeviceGBId())) {
130 logger.warn("未查询到目录{}的信息", catalogId); 130 logger.warn("未查询到目录{}的信息", catalogId);
131 return null; 131 return null;
132 } 132 }
133 for (ChannelReduce channelReduce : channelReduces) { 133 for (ChannelReduce channelReduce : channelReduces) {
134 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); 134 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
135 deviceChannel.setParental(0); 135 deviceChannel.setParental(0);
  136 + deviceChannel.setCivilCode(catalog.getCivilCode());
  137 + deviceChannel.setParentId(catalog.getParentId());
  138 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
136 deviceChannelList.add(deviceChannel); 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 return deviceChannelList; 142 return deviceChannelList;
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
@@ -35,6 +35,8 @@ import java.util.Map; @@ -35,6 +35,8 @@ import java.util.Map;
35 public class PlatformServiceImpl implements IPlatformService { 35 public class PlatformServiceImpl implements IPlatformService {
36 36
37 private final static String REGISTER_KEY_PREFIX = "platform_register_"; 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 private final static String KEEPALIVE_KEY_PREFIX = "platform_keepalive_"; 40 private final static String KEEPALIVE_KEY_PREFIX = "platform_keepalive_";
39 41
40 private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class); 42 private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
@@ -132,14 +134,6 @@ public class PlatformServiceImpl implements IPlatformService { @@ -132,14 +134,6 @@ public class PlatformServiceImpl implements IPlatformService {
132 ParentPlatform parentPlatformOld = platformMapper.getParentPlatById(parentPlatform.getId()); 134 ParentPlatform parentPlatformOld = platformMapper.getParentPlatById(parentPlatform.getId());
133 ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatformOld.getServerGBId()); 135 ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatformOld.getServerGBId());
134 parentPlatform.setUpdateTime(DateUtil.getNow()); 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 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatformOld.getServerGBId(); 139 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatformOld.getServerGBId();
@@ -150,12 +144,11 @@ public class PlatformServiceImpl implements IPlatformService { @@ -150,12 +144,11 @@ public class PlatformServiceImpl implements IPlatformService {
150 // 注销旧的 144 // 注销旧的
151 try { 145 try {
152 if (parentPlatformOld.isStatus()) { 146 if (parentPlatformOld.isStatus()) {
153 - logger.info("保存平台{}时发现平台在线,发送注销命令", parentPlatformOld.getServerGBId()); 147 + logger.info("保存平台{}时发现平台在线,发送注销命令", parentPlatformOld.getServerGBId());
154 commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> { 148 commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> {
155 logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId()); 149 logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId());
156 }); 150 });
157 } 151 }
158 -  
159 } catch (InvalidArgumentException | ParseException | SipException e) { 152 } catch (InvalidArgumentException | ParseException | SipException e) {
160 logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); 153 logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
161 } 154 }
@@ -188,9 +181,6 @@ public class PlatformServiceImpl implements IPlatformService { @@ -188,9 +181,6 @@ public class PlatformServiceImpl implements IPlatformService {
188 logger.error("[命令发送失败] 国标级联: {}", e.getMessage()); 181 logger.error("[命令发送失败] 国标级联: {}", e.getMessage());
189 } 182 }
190 } 183 }
191 - // 重新开启定时注册, 使用续订消息  
192 - // 重新开始心跳保活  
193 -  
194 184
195 return false; 185 return false;
196 } 186 }
@@ -199,6 +189,9 @@ public class PlatformServiceImpl implements IPlatformService { @@ -199,6 +189,9 @@ public class PlatformServiceImpl implements IPlatformService {
199 @Override 189 @Override
200 public void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo) { 190 public void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo) {
201 logger.info("[国标级联]:{}, 平台上线", parentPlatform.getServerGBId()); 191 logger.info("[国标级联]:{}, 平台上线", parentPlatform.getServerGBId());
  192 + final String registerFailAgainTaskKey = REGISTER_FAIL_AGAIN_KEY_PREFIX + parentPlatform.getServerGBId();
  193 + dynamicTask.stop(registerFailAgainTaskKey);
  194 +
202 platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true); 195 platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true);
203 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); 196 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
204 if (parentPlatformCatch == null) { 197 if (parentPlatformCatch == null) {
@@ -239,15 +232,9 @@ public class PlatformServiceImpl implements IPlatformService { @@ -239,15 +232,9 @@ public class PlatformServiceImpl implements IPlatformService {
239 // 此时是第三次心跳超时, 平台离线 232 // 此时是第三次心跳超时, 平台离线
240 if (platformCatch.getKeepAliveReply() == 2) { 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 }else { 240 }else {
@@ -273,21 +260,22 @@ public class PlatformServiceImpl implements IPlatformService { @@ -273,21 +260,22 @@ public class PlatformServiceImpl implements IPlatformService {
273 260
274 private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){ 261 private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){
275 try { 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 commanderForPlatform.register(parentPlatform, sipTransactionInfo, eventResult -> { 274 commanderForPlatform.register(parentPlatform, sipTransactionInfo, eventResult -> {
286 - dynamicTask.stop(key); 275 + logger.info("[国标级联] 平台:{}注册失败,{}:{}", parentPlatform.getServerGBId(),
  276 + eventResult.statusCode, eventResult.msg);
287 offline(parentPlatform, false); 277 offline(parentPlatform, false);
288 - },eventResult -> {  
289 - dynamicTask.stop(key);  
290 - }); 278 + }, null);
291 } catch (InvalidArgumentException | ParseException | SipException e) { 279 } catch (InvalidArgumentException | ParseException | SipException e) {
292 logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage()); 280 logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
293 } 281 }
@@ -308,24 +296,35 @@ public class PlatformServiceImpl implements IPlatformService { @@ -308,24 +296,35 @@ public class PlatformServiceImpl implements IPlatformService {
308 // 停止所有推流 296 // 停止所有推流
309 logger.info("[平台离线] {}, 停止所有推流", parentPlatform.getServerGBId()); 297 logger.info("[平台离线] {}, 停止所有推流", parentPlatform.getServerGBId());
310 stopAllPush(parentPlatform.getServerGBId()); 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 logger.info("[平台离线] {}, 停止定时发送心跳任务", parentPlatform.getServerGBId()); 307 logger.info("[平台离线] {}, 停止定时发送心跳任务", parentPlatform.getServerGBId());
321 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); 308 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
322 if (dynamicTask.contains(keepaliveTaskKey)) { 309 if (dynamicTask.contains(keepaliveTaskKey)) {
323 - // 添加心跳任务 310 + // 清除心跳任务
324 dynamicTask.stop(keepaliveTaskKey); 311 dynamicTask.stop(keepaliveTaskKey);
325 } 312 }
326 // 停止目录订阅回复 313 // 停止目录订阅回复
327 logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId()); 314 logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId());
328 subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); 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 private void stopAllPush(String platformId) { 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,10 +451,18 @@ public interface DeviceChannelMapper {
451 @Select("select count(1) from wvp_device_channel") 451 @Select("select count(1) from wvp_device_channel")
452 int getAllChannelCount(); 452 int getAllChannelCount();
453 453
454 -  
455 - /*=================设备主子码流逻辑START==============*/ 454 + // 设备主子码流逻辑START
456 @Update(value = {"UPDATE wvp_device_channel SET stream_id=null WHERE device_id=#{deviceId}"}) 455 @Update(value = {"UPDATE wvp_device_channel SET stream_id=null WHERE device_id=#{deviceId}"})
457 void clearPlay(String deviceId); 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,7 +40,6 @@ public interface DeviceMapper {
40 "ssrc_check," + 40 "ssrc_check," +
41 "as_message_channel," + 41 "as_message_channel," +
42 "geo_coord_sys," + 42 "geo_coord_sys," +
43 - "tree_type," +  
44 "on_line," + 43 "on_line," +
45 "media_server_id," + 44 "media_server_id," +
46 "switch_primary_sub_stream," + 45 "switch_primary_sub_stream," +
@@ -75,7 +74,6 @@ public interface DeviceMapper { @@ -75,7 +74,6 @@ public interface DeviceMapper {
75 "ssrc_check,"+ 74 "ssrc_check,"+
76 "as_message_channel,"+ 75 "as_message_channel,"+
77 "geo_coord_sys,"+ 76 "geo_coord_sys,"+
78 - "tree_type,"+  
79 "on_line"+ 77 "on_line"+
80 ") VALUES (" + 78 ") VALUES (" +
81 "#{deviceId}," + 79 "#{deviceId}," +
@@ -104,7 +102,6 @@ public interface DeviceMapper { @@ -104,7 +102,6 @@ public interface DeviceMapper {
104 "#{ssrcCheck}," + 102 "#{ssrcCheck}," +
105 "#{asMessageChannel}," + 103 "#{asMessageChannel}," +
106 "#{geoCoordSys}," + 104 "#{geoCoordSys}," +
107 - "#{treeType}," +  
108 "#{onLine}" + 105 "#{onLine}" +
109 ")") 106 ")")
110 int add(Device device); 107 int add(Device device);
@@ -159,7 +156,6 @@ public interface DeviceMapper { @@ -159,7 +156,6 @@ public interface DeviceMapper {
159 "ssrc_check,"+ 156 "ssrc_check,"+
160 "as_message_channel,"+ 157 "as_message_channel,"+
161 "geo_coord_sys,"+ 158 "geo_coord_sys,"+
162 - "tree_type,"+  
163 "on_line,"+ 159 "on_line,"+
164 "media_server_id,"+ 160 "media_server_id,"+
165 "switch_primary_sub_stream switchPrimarySubStream,"+ 161 "switch_primary_sub_stream switchPrimarySubStream,"+
@@ -201,7 +197,6 @@ public interface DeviceMapper { @@ -201,7 +197,6 @@ public interface DeviceMapper {
201 "ssrc_check,"+ 197 "ssrc_check,"+
202 "as_message_channel,"+ 198 "as_message_channel,"+
203 "geo_coord_sys,"+ 199 "geo_coord_sys,"+
204 - "tree_type,"+  
205 "on_line"+ 200 "on_line"+
206 " FROM wvp_device WHERE on_line = true") 201 " FROM wvp_device WHERE on_line = true")
207 List<Device> getOnlineDevices(); 202 List<Device> getOnlineDevices();
@@ -232,7 +227,6 @@ public interface DeviceMapper { @@ -232,7 +227,6 @@ public interface DeviceMapper {
232 "ssrc_check,"+ 227 "ssrc_check,"+
233 "as_message_channel,"+ 228 "as_message_channel,"+
234 "geo_coord_sys,"+ 229 "geo_coord_sys,"+
235 - "tree_type,"+  
236 "on_line"+ 230 "on_line"+
237 " FROM wvp_device WHERE ip = #{host} AND port=#{port}") 231 " FROM wvp_device WHERE ip = #{host} AND port=#{port}")
238 Device getDeviceByHostAndPort(String host, int port); 232 Device getDeviceByHostAndPort(String host, int port);
@@ -254,7 +248,6 @@ public interface DeviceMapper { @@ -254,7 +248,6 @@ public interface DeviceMapper {
254 "<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" + 248 "<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" +
255 "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" + 249 "<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
256 "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" + 250 "<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
257 - "<if test=\"treeType != null\">, tree_type=#{treeType}</if>" +  
258 "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" + 251 "<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +
259 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" + 252 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
260 "WHERE device_id=#{deviceId}"+ 253 "WHERE device_id=#{deviceId}"+
@@ -272,7 +265,6 @@ public interface DeviceMapper { @@ -272,7 +265,6 @@ public interface DeviceMapper {
272 "ssrc_check,"+ 265 "ssrc_check,"+
273 "as_message_channel,"+ 266 "as_message_channel,"+
274 "geo_coord_sys,"+ 267 "geo_coord_sys,"+
275 - "tree_type,"+  
276 "on_line,"+ 268 "on_line,"+
277 "media_server_id,"+ 269 "media_server_id,"+
278 "switch_primary_sub_stream"+ 270 "switch_primary_sub_stream"+
@@ -287,7 +279,6 @@ public interface DeviceMapper { @@ -287,7 +279,6 @@ public interface DeviceMapper {
287 "#{ssrcCheck}," + 279 "#{ssrcCheck}," +
288 "#{asMessageChannel}," + 280 "#{asMessageChannel}," +
289 "#{geoCoordSys}," + 281 "#{geoCoordSys}," +
290 - "#{treeType}," +  
291 "#{onLine}," + 282 "#{onLine}," +
292 "#{mediaServerId}," + 283 "#{mediaServerId}," +
293 "#{switchPrimarySubStream}" + 284 "#{switchPrimarySubStream}" +
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
@@ -16,10 +16,10 @@ public interface ParentPlatformMapper { @@ -16,10 +16,10 @@ public interface ParentPlatformMapper {
16 16
17 @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+ 17 @Insert("INSERT INTO wvp_platform (enable, name, server_gb_id, server_gb_domain, server_ip, server_port,device_gb_id,device_ip,"+
18 "device_port,username,password,expires,keep_timeout,transport,character_set,ptz,rtcp,as_message_channel,"+ 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 " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + 20 " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
21 " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " + 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 int addParentPlatform(ParentPlatform parentPlatform); 23 int addParentPlatform(ParentPlatform parentPlatform);
24 24
25 @Update("UPDATE wvp_platform " + 25 @Update("UPDATE wvp_platform " +
@@ -47,7 +47,6 @@ public interface ParentPlatformMapper { @@ -47,7 +47,6 @@ public interface ParentPlatformMapper {
47 "administrative_division=#{administrativeDivision}, " + 47 "administrative_division=#{administrativeDivision}, " +
48 "create_time=#{createTime}, " + 48 "create_time=#{createTime}, " +
49 "update_time=#{updateTime}, " + 49 "update_time=#{updateTime}, " +
50 - "tree_type=#{treeType}, " +  
51 "catalog_id=#{catalogId} " + 50 "catalog_id=#{catalogId} " +
52 "WHERE id=#{id}") 51 "WHERE id=#{id}")
53 int updateParentPlatform(ParentPlatform parentPlatform); 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,51 +128,56 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
128 List<DeviceChannel> addChannels = new ArrayList<>(); 128 List<DeviceChannel> addChannels = new ArrayList<>();
129 StringBuilder stringBuilder = new StringBuilder(); 129 StringBuilder stringBuilder = new StringBuilder();
130 Map<String, Integer> subContMap = new HashMap<>(); 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 }else { 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 if (stringBuilder.length() > 0) { 181 if (stringBuilder.length() > 0) {
177 logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder); 182 logger.info("[目录查询]收到的数据存在重复: {}" , stringBuilder);
178 } 183 }
@@ -795,25 +800,49 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -795,25 +800,49 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
795 if (platform == null) { 800 if (platform == null) {
796 return 0; 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 int result = catalogMapper.add(platformCatalog); 846 int result = catalogMapper.add(platformCatalog);
818 if (result > 0) { 847 if (result > 0) {
819 DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog); 848 DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog);
@@ -937,19 +966,14 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -937,19 +966,14 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
937 DeviceChannel deviceChannel = new DeviceChannel(); 966 DeviceChannel deviceChannel = new DeviceChannel();
938 deviceChannel.setChannelId(catalog.getId()); 967 deviceChannel.setChannelId(catalog.getId());
939 deviceChannel.setName(catalog.getName()); 968 deviceChannel.setName(catalog.getName());
940 - deviceChannel.setLongitude(0.0);  
941 - deviceChannel.setLatitude(0.0);  
942 deviceChannel.setDeviceId(platform.getDeviceGBId()); 969 deviceChannel.setDeviceId(platform.getDeviceGBId());
943 deviceChannel.setManufacture("wvp-pro"); 970 deviceChannel.setManufacture("wvp-pro");
944 deviceChannel.setStatus(true); 971 deviceChannel.setStatus(true);
945 deviceChannel.setParental(1); 972 deviceChannel.setParental(1);
946 973
947 deviceChannel.setRegisterWay(1); 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 deviceChannel.setModel("live"); 978 deviceChannel.setModel("live");
955 deviceChannel.setOwner("wvp-pro"); 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,8 +403,12 @@ public class PlatformController {
403 if (platform == null) { 403 if (platform == null) {
404 throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台未找到"); 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 return storager.getChildrenCatalogByPlatform(platformId, parentId); 414 return storager.getChildrenCatalogByPlatform(platformId, parentId);
src/main/resources/all-application.yml
@@ -202,6 +202,10 @@ user-settings: @@ -202,6 +202,10 @@ user-settings:
202 device-status-notify: false 202 device-status-notify: false
203 # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 203 # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
204 use-custom-ssrc-for-parent-invite: true 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 allowed-origins: 210 allowed-origins:
207 - http://localhost:8008 211 - http://localhost:8008