xiwa 3 vuotta sitten
vanhempi
commit
456f7a471b
100 muutettua tiedostoa jossa 2829 lisäystä ja 1953 poistoa
  1. 10 0
      common/src/main/java/cc/iotkit/common/Constants.java
  2. 16 0
      communication/component/pom.xml
  3. 21 0
      communication/mqtt-component/pom.xml
  4. 15 0
      communication/pom.xml
  5. 39 0
      dao/src/main/java/cc/iotkit/dao/DeviceCache.java
  6. 0 62
      dao/src/main/java/cc/iotkit/dao/DeviceDao.java
  7. 5 0
      dao/src/main/java/cc/iotkit/dao/DeviceRepository.java
  8. 5 7
      dao/src/main/java/cc/iotkit/dao/ProductCache.java
  9. 11 0
      dao/src/main/java/cc/iotkit/dao/ProtocolGatewayRepository.java
  10. 0 22
      dao/src/main/java/cc/iotkit/dao/SceneLogDao.java
  11. 3 0
      dao/src/main/java/cc/iotkit/dao/SceneLogRepository.java
  12. 0 22
      dao/src/main/java/cc/iotkit/dao/TaskLogDao.java
  13. 3 0
      dao/src/main/java/cc/iotkit/dao/TaskLogRepository.java
  14. 9 0
      dao/src/main/java/cc/iotkit/dao/ThingModelMessageRepository.java
  15. 3 0
      dao/src/main/java/cc/iotkit/dao/ThingModelRepository.java
  16. 7 0
      dao/src/main/java/cc/iotkit/dao/UserInfoRepository.java
  17. 13 0
      dao/src/main/java/cc/iotkit/dao/config/ElasticsearchConfiguration.java
  18. 24 7
      dao/src/main/java/cc/iotkit/dao/config/RepositoryConfig.java
  19. 0 95
      device-server/mqtt-auth/pom.xml
  20. 0 53
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/dao/DaoTool.java
  21. 0 53
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/dao/DeviceDao.java
  22. 0 23
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/dao/ProductDao.java
  23. 0 82
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/DeviceService.java
  24. 0 12
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/MqttAuth.java
  25. 0 42
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/SysMqttAuth.java
  26. 0 18
      device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/WxMqttAuth.java
  27. 0 5
      device-server/mqtt-auth/src/main/resources/application-dev.yml
  28. 0 5
      device-server/mqtt-auth/src/main/resources/application.yml
  29. 0 23
      device-server/mqtt-auth/src/test/java/SupperUser.java
  30. 0 13
      device-server/mqtt-auth/src/test/java/SysMqttAuth.java
  31. BIN
      device-server/mqtt-server/log/error.2022-01-10.0.gz
  32. BIN
      device-server/mqtt-server/log/error.2022-01-11.0.gz
  33. BIN
      device-server/mqtt-server/log/error.2022-01-12.0.gz
  34. BIN
      device-server/mqtt-server/log/error.2022-01-13.0.gz
  35. BIN
      device-server/mqtt-server/log/info.2022-01-10.0.gz
  36. BIN
      device-server/mqtt-server/log/info.2022-01-11.0.gz
  37. BIN
      device-server/mqtt-server/log/info.2022-01-12.0.gz
  38. BIN
      device-server/mqtt-server/log/info.2022-01-13.0.gz
  39. 8 50
      device-server/mqtt-server/pom.xml
  40. 0 43
      device-server/mqtt-server/src/main/java/cc/iotkit/server/config/CacheConfig.java
  41. 0 42
      device-server/mqtt-server/src/main/java/cc/iotkit/server/config/GlobalExceptionHandler.java
  42. 0 147
      device-server/mqtt-server/src/main/java/cc/iotkit/server/config/MqttConfig.java
  43. 0 55
      device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/BaseDao.java
  44. 0 53
      device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DaoTool.java
  45. 0 62
      device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DeviceDao.java
  46. 0 13
      device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DeviceEventRepository.java
  47. 0 9
      device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DeviceRepository.java
  48. 0 9
      device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/ThingModelRepository.java
  49. 0 63
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/DisconnectedHandler.java
  50. 0 49
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/EventReportHandler.java
  51. 0 162
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/MqttConsumerHandler.java
  52. 0 14
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/MqttHandler.java
  53. 0 62
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/PropertyPostHandler.java
  54. 0 47
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/PropertyReplyHandler.java
  55. 0 36
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/RegisterHandler.java
  56. 0 49
      device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/ServiceReplyHandler.java
  57. 1 1
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/Application.java
  58. 19 0
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/config/AutobeanConfig.java
  59. 47 0
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/DeviceController.java
  60. 9 30
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/MqttAuthController.java
  61. 41 0
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/handler/DisconnectedHandler.java
  62. 1 1
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAcl.java
  63. 1 1
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAuthInfo.java
  64. 17 0
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Request.java
  65. 25 0
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Response.java
  66. 18 22
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/DeviceAuthService.java
  67. 256 0
      device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/MqttManager.java
  68. 0 219
      device-server/mqtt-server/src/main/java/cc/iotkit/server/service/DeviceService.java
  69. 0 40
      device-server/mqtt-server/src/main/java/cc/iotkit/server/service/IMqttSender.java
  70. 0 60
      device-server/mqtt-server/src/main/java/cc/iotkit/server/service/ThingModelService.java
  71. 0 1
      device-server/pom.xml
  72. BIN
      log/error.2022-03-14.0.gz
  73. BIN
      log/error.2022-03-15.0.gz
  74. BIN
      log/error.2022-03-16.0.gz
  75. 900 0
      log/error.2022-03-16.01767963764004696.tmp
  76. BIN
      log/error.2022-03-17.0.gz
  77. BIN
      log/error.2022-03-18.0.gz
  78. BIN
      log/info.2022-03-14.0.gz
  79. BIN
      log/info.2022-03-15.0.gz
  80. BIN
      log/info.2022-03-16.0.gz
  81. 1019 0
      log/info.2022-03-16.01767904371465962.tmp
  82. BIN
      log/info.2022-03-17.0.gz
  83. BIN
      log/info.2022-03-18.0.gz
  84. 5 0
      manager/pom.xml
  85. 1 1
      manager/src/main/java/cc/iotkit/manager/Application.java
  86. 2 1
      manager/src/main/java/cc/iotkit/manager/config/KeycloakSecurityConfig.java
  87. 4 4
      manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java
  88. 4 5
      manager/src/main/java/cc/iotkit/manager/controller/ProductController.java
  89. 126 0
      manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java
  90. 4 10
      manager/src/main/java/cc/iotkit/manager/controller/RuleEngineController.java
  91. 4 4
      manager/src/main/java/cc/iotkit/manager/controller/SpaceController.java
  92. 27 16
      manager/src/main/java/cc/iotkit/manager/controller/UserInfoController.java
  93. 5 5
      manager/src/main/java/cc/iotkit/manager/controller/aligenie/AligenieProductController.java
  94. 10 7
      manager/src/main/java/cc/iotkit/manager/controller/api/MessageController.java
  95. 4 4
      manager/src/main/java/cc/iotkit/manager/controller/api/SpaceController.java
  96. 3 3
      manager/src/main/java/cc/iotkit/manager/service/AligenieService.java
  97. 14 6
      manager/src/main/java/cc/iotkit/manager/service/DataOwnerService.java
  98. 2 2
      manager/src/main/java/cc/iotkit/manager/service/DeviceService.java
  99. 17 1
      manager/src/main/java/cc/iotkit/manager/service/KeycloakAdminService.java
  100. 51 0
      manager/src/main/java/cc/iotkit/manager/service/PulsarAdminService.java

+ 10 - 0
common/src/main/java/cc/iotkit/common/Constants.java

@@ -58,4 +58,14 @@ public interface Constants {
      */
     String PWD_SYSTEM_USER="s123456";
 
+    /**
+     * 设备原始上报消息的topic
+     */
+    String DEVICE_RAW_MESSAGE_TOPIC="device_raw";
+
+    /**
+     * 设备物模型消息的topic
+     */
+    String THING_MODEL_MESSAGE_TOPIC="device_thing";
+
 }

+ 16 - 0
communication/component/pom.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>iotkit-parent</artifactId>
+        <groupId>cc.iotkit</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>component</artifactId>
+
+
+</project>

+ 21 - 0
communication/mqtt-component/pom.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>iotkit-parent</artifactId>
+        <groupId>cc.iotkit</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>mqtt-component</artifactId>
+
+
+    <dependencies>
+
+
+    </dependencies>
+
+</project>

+ 15 - 0
communication/pom.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>iotkit-parent</artifactId>
+        <groupId>cc.iotkit</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>communication</artifactId>
+
+
+</project>

+ 39 - 0
dao/src/main/java/cc/iotkit/dao/DeviceCache.java

@@ -0,0 +1,39 @@
+package cc.iotkit.dao;
+
+import cc.iotkit.common.Constants;
+import cc.iotkit.model.device.DeviceInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import static org.springframework.data.mongodb.core.query.Criteria.where;
+import static org.springframework.data.mongodb.core.query.Query.query;
+
+@Repository
+public class DeviceCache extends BaseDao<DeviceInfo> {
+
+    @Autowired
+    private DeviceRepository deviceRepository;
+
+    @Autowired
+    public DeviceCache(MongoTemplate mongoTemplate) {
+        super(mongoTemplate, DeviceInfo.class);
+    }
+
+    @Cacheable(value = Constants.DEVICE_CACHE, key = "#pk+'_'+#dn")
+    public DeviceInfo findByProductKeyAndDeviceName(String pk, String dn) {
+        return deviceRepository.findByProductKeyAndDeviceName(pk, dn);
+    }
+
+    @Cacheable(value = Constants.DEVICE_CACHE, key = "#deviceId")
+    public DeviceInfo findByDeviceId(String deviceId) {
+        return deviceRepository.findByDeviceId(deviceId);
+    }
+
+    @Cacheable(value = Constants.DEVICE_CACHE, key = "#deviceId")
+    public DeviceInfo get(String deviceId) {
+        return deviceRepository.findById(deviceId).orElse(new DeviceInfo());
+    }
+}

+ 0 - 62
dao/src/main/java/cc/iotkit/dao/DeviceDao.java

@@ -1,62 +0,0 @@
-package cc.iotkit.dao;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.model.device.DeviceInfo;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Repository;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-import static org.springframework.data.mongodb.core.query.Query.query;
-
-@Repository
-public class DeviceDao extends BaseDao<DeviceInfo> {
-
-    @Autowired
-    private DeviceRepository deviceRepository;
-
-    @Autowired
-    public DeviceDao(MongoTemplate mongoTemplate) {
-        super(mongoTemplate, DeviceInfo.class);
-    }
-
-    public void addDevice(DeviceInfo device) {
-        device.setCreateAt(System.currentTimeMillis());
-        mongoTemplate.insert(device);
-    }
-
-    public void updateDevice(DeviceInfo device) {
-        if (device.getDeviceId() == null) {
-            return;
-        }
-        mongoTemplate.updateFirst(query(where("deviceId").is(device.getDeviceId())),
-                DaoTool.update(device), DeviceInfo.class);
-    }
-
-    public void updateDeviceByPkAndDn(DeviceInfo device) {
-        if (device.getProductKey() == null || device.getDeviceName() == null) {
-            return;
-        }
-        mongoTemplate.updateFirst(query(where("productKey").is(device.getProductKey()).
-                        and("deviceName").is(device.getDeviceName())),
-                DaoTool.update(device), DeviceInfo.class);
-    }
-
-    @Cacheable(value = "deviceInfoCache", key = "#pk+'_'+#dn")
-    public DeviceInfo getByPkAndDn(String pk, String dn) {
-        Query query = query(where("productKey").is(pk).and("deviceName").is(dn));
-        return mongoTemplate.findOne(query, DeviceInfo.class);
-    }
-
-    public DeviceInfo getByDeviceId(String deviceId) {
-        Query query = query(where("deviceId").is(deviceId));
-        return mongoTemplate.findOne(query, DeviceInfo.class);
-    }
-
-    @Cacheable(value = Constants.DEVICE_CACHE, key = "#deviceId")
-    public DeviceInfo get(String deviceId) {
-        return deviceRepository.findById(deviceId).orElse(new DeviceInfo());
-    }
-}

+ 5 - 0
dao/src/main/java/cc/iotkit/dao/DeviceRepository.java

@@ -6,4 +6,9 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface DeviceRepository extends MongoRepository<DeviceInfo, String> {
+
+    DeviceInfo findByProductKeyAndDeviceName(String productKey, String deviceName);
+
+    DeviceInfo findByDeviceId(String deviceId);
+
 }

+ 5 - 7
dao/src/main/java/cc/iotkit/dao/ProductDao.java → dao/src/main/java/cc/iotkit/dao/ProductCache.java

@@ -5,25 +5,23 @@ import cc.iotkit.model.product.Product;
 import cc.iotkit.model.product.ThingModel;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
-import org.springframework.data.domain.Example;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public class ProductDao {
+public class ProductCache {
 
     @Autowired
     private ProductRepository productRepository;
     @Autowired
     private ThingModelRepository thingModelRepository;
 
-    @Cacheable(value = Constants.PRODUCT_CACHE, key = "'getProductById'+#pk", unless = "#result == null")
-    public Product get(String pk) {
+    @Cacheable(value = Constants.PRODUCT_CACHE, key = "'pk'+#pk", unless = "#result == null")
+    public Product findById(String pk) {
         return productRepository.findById(pk).orElse(new Product());
     }
 
-    @Cacheable(value = Constants.THING_MODEL_CACHE, key = "'getThingModel'+#pk", unless = "#result == null")
+    @Cacheable(value = Constants.THING_MODEL_CACHE, key = "'pk'+#pk", unless = "#result == null")
     public ThingModel getThingModel(String pk) {
-        return thingModelRepository.findOne(Example.of(ThingModel.builder()
-                .productKey(pk).build())).orElse(new ThingModel());
+        return thingModelRepository.findByProductKey(pk);
     }
 }

+ 11 - 0
dao/src/main/java/cc/iotkit/dao/ProtocolGatewayRepository.java

@@ -0,0 +1,11 @@
+package cc.iotkit.dao;
+
+import cc.iotkit.model.protocol.ProtocolGateway;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProtocolGatewayRepository extends MongoRepository<ProtocolGateway, String> {
+
+
+}

+ 0 - 22
dao/src/main/java/cc/iotkit/dao/SceneLogDao.java

@@ -1,22 +0,0 @@
-package cc.iotkit.dao;
-
-import cc.iotkit.model.rule.SceneLog;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Repository;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-
-@Repository
-public class SceneLogDao extends BaseDao<SceneLog> {
-
-    @Autowired
-    public SceneLogDao(MongoTemplate mongoTemplate) {
-        super(mongoTemplate, SceneLog.class);
-    }
-
-    public void deleteLogs(String sceneId) {
-        this.mongoTemplate.remove(Query.query(where("sceneId").is(sceneId)), SceneLog.class);
-    }
-}

+ 3 - 0
dao/src/main/java/cc/iotkit/dao/SceneLogRepository.java

@@ -6,4 +6,7 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface SceneLogRepository extends MongoRepository<SceneLog, String> {
+
+    void deleteBySceneId(String sceneId);
+
 }

+ 0 - 22
dao/src/main/java/cc/iotkit/dao/TaskLogDao.java

@@ -1,22 +0,0 @@
-package cc.iotkit.dao;
-
-import cc.iotkit.model.rule.TaskLog;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Repository;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-
-@Repository
-public class TaskLogDao extends BaseDao<TaskLog> {
-
-    @Autowired
-    public TaskLogDao(MongoTemplate mongoTemplate) {
-        super(mongoTemplate, TaskLog.class);
-    }
-
-    public void deleteLogs(String taskId) {
-        this.mongoTemplate.remove(Query.query(where("taskId").is(taskId)), TaskLog.class);
-    }
-}

+ 3 - 0
dao/src/main/java/cc/iotkit/dao/TaskLogRepository.java

@@ -6,4 +6,7 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface TaskLogRepository extends MongoRepository<TaskLog, String> {
+
+    void deleteByTaskId(String taskId);
+
 }

+ 9 - 0
dao/src/main/java/cc/iotkit/dao/ThingModelMessageRepository.java

@@ -0,0 +1,9 @@
+package cc.iotkit.dao;
+
+import cc.iotkit.model.device.message.ThingModelMessage;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ThingModelMessageRepository extends ElasticsearchRepository<ThingModelMessage, String> {
+}

+ 3 - 0
dao/src/main/java/cc/iotkit/dao/ThingModelRepository.java

@@ -6,4 +6,7 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface ThingModelRepository extends MongoRepository<ThingModel, String> {
+
+    ThingModel findByProductKey(String productKey);
+
 }

+ 7 - 0
dao/src/main/java/cc/iotkit/dao/UserInfoRepository.java

@@ -4,6 +4,13 @@ import cc.iotkit.model.UserInfo;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface UserInfoRepository extends MongoRepository<UserInfo, String> {
+
+    List<UserInfo> findByType(int type);
+
+    List<UserInfo> findByTypeAndOwnerId(int type, String ownerId);
+
 }

+ 13 - 0
dao/src/main/java/cc/iotkit/dao/config/ElasticsearchConfiguration.java

@@ -0,0 +1,13 @@
+package cc.iotkit.dao.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
+
+@Configuration
+@EnableElasticsearchRepositories(basePackages = "cc.iotkit.dao", includeFilters =
+@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchRepository.class))
+public class ElasticsearchConfiguration {
+}

+ 24 - 7
dao/src/main/java/cc/iotkit/dao/config/RepositoryConfig.java

@@ -1,19 +1,24 @@
 package cc.iotkit.dao.config;
 
 import org.springframework.beans.factory.BeanFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
+import org.springframework.context.annotation.*;
 import org.springframework.data.convert.CustomConversions;
 import org.springframework.data.mongodb.MongoDatabaseFactory;
-import org.springframework.data.mongodb.core.convert.DbRefResolver;
-import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
-import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
-import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.convert.*;
 import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
+import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
 
+import java.util.Collections;
+
 @Configuration
-@EnableMongoRepositories(basePackages = "cc.iotkit.dao")
+@Import(value = MongoAutoConfiguration.class)
+@EnableMongoRepositories(basePackages = "cc.iotkit.dao", includeFilters = @ComponentScan.Filter(
+        type = FilterType.ASSIGNABLE_TYPE, value = MongoRepository.class))
 public class RepositoryConfig {
 
     @Bean
@@ -28,4 +33,16 @@ public class RepositoryConfig {
         return mappingMongoConverter;
     }
 
+    @Bean
+    @ConditionalOnMissingBean({MongoOperations.class})
+    MongoTemplate mongoTemplate(MongoDatabaseFactory factory, MongoConverter converter) {
+        return new MongoTemplate(factory, converter);
+    }
+
+    @Bean
+    @Primary
+    MongoCustomConversions mongoCustomConversions() {
+        return new MongoCustomConversions(Collections.emptyList());
+    }
+
 }

+ 0 - 95
device-server/mqtt-auth/pom.xml

@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>device-server</artifactId>
-        <groupId>cc.iotkit</groupId>
-        <version>0.0.1-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>mqtt-auth</artifactId>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-mongodb</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.ben-manes.caffeine</groupId>
-            <artifactId>caffeine</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>commons-beanutils</groupId>
-            <artifactId>commons-beanutils</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>joda-time</groupId>
-            <artifactId>joda-time</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cc.iotkit</groupId>
-            <artifactId>common</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cc.iotkit</groupId>
-            <artifactId>model</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <configuration>
-                    <excludes>
-                        <exclude>
-                            <groupId>org.projectlombok</groupId>
-                            <artifactId>lombok</artifactId>
-                        </exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

+ 0 - 53
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/dao/DaoTool.java

@@ -1,53 +0,0 @@
-package cc.iotkit.mqttauth.dao;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.SneakyThrows;
-import org.apache.commons.beanutils.BeanMap;
-import org.springframework.data.mongodb.core.query.Update;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class DaoTool {
-
-    public static void update(Update update, List<Prop> props) {
-        for (Prop pro : props) {
-            update.set(pro.getName(), pro.getValue());
-        }
-    }
-
-    public static List<Prop> getProp(String key, Object value) {
-        List<Prop> props = new ArrayList<>();
-        if (value instanceof Map) {
-            Set<Map.Entry<String, Object>> entrySet = ((Map) value).entrySet();
-            for (Map.Entry<String, Object> entry : entrySet) {
-                props.addAll(getProp(key + "." + entry.getKey(), entry.getValue()));
-            }
-        } else if (value != null && !(value instanceof Class)) {
-            props.add(new Prop(key, value));
-        }
-        return props;
-    }
-
-    @SneakyThrows
-    public static <T> Update update(T obj) {
-        Map<Object, Object> pros = new BeanMap(obj);
-        Update update = new Update();
-        for (Map.Entry<Object, Object> entry : pros.entrySet()) {
-            update(update, DaoTool.getProp(entry.getKey().toString(), entry.getValue()));
-        }
-        return update;
-    }
-
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    static class Prop {
-        private String name;
-        private Object value;
-    }
-}

+ 0 - 53
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/dao/DeviceDao.java

@@ -1,53 +0,0 @@
-package cc.iotkit.mqttauth.dao;
-
-import cc.iotkit.model.device.DeviceInfo;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Repository;
-
-import javax.annotation.Resource;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-import static org.springframework.data.mongodb.core.query.Query.query;
-
-@Repository
-public class DeviceDao {
-
-    @Resource
-    private MongoTemplate mongoTemplate;
-
-    public void addDevice(DeviceInfo device) {
-        device.setId(device.getDeviceId());
-        device.setCreateAt(System.currentTimeMillis());
-        mongoTemplate.insert(device);
-    }
-
-    public void updateDevice(DeviceInfo device) {
-        if (device.getDeviceId() == null) {
-            return;
-        }
-        mongoTemplate.updateFirst(query(where("deviceId").is(device.getDeviceId())),
-                DaoTool.update(device), DeviceInfo.class);
-    }
-
-    public void updateDeviceByPkAndDn(DeviceInfo device) {
-        if (device.getProductKey() == null || device.getDeviceName() == null) {
-            return;
-        }
-        mongoTemplate.updateFirst(query(where("productKey").is(device.getProductKey()).
-                        and("deviceName").is(device.getDeviceName())),
-                DaoTool.update(device), DeviceInfo.class);
-    }
-
-    @Cacheable(value = "deviceInfoCache", key = "#pk+'_'+#dn")
-    public DeviceInfo getByPkAndDn(String pk, String dn) {
-        Query query = query(where("productKey").is(pk).and("deviceName").is(dn));
-        return mongoTemplate.findOne(query, DeviceInfo.class);
-    }
-
-    public DeviceInfo getByDeviceId(String deviceId) {
-        Query query = query(where("deviceId").is(deviceId));
-        return mongoTemplate.findOne(query, DeviceInfo.class);
-    }
-}

+ 0 - 23
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/dao/ProductDao.java

@@ -1,23 +0,0 @@
-package cc.iotkit.mqttauth.dao;
-
-import cc.iotkit.model.product.Product;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Repository;
-
-import javax.annotation.Resource;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-import static org.springframework.data.mongodb.core.query.Query.query;
-
-@Repository
-public class ProductDao {
-
-    @Resource
-    private MongoTemplate mongoTemplate;
-
-    public Product getProduct(String pk) {
-        Query query = query(where("code").is(pk));
-        return mongoTemplate.findOne(query, Product.class);
-    }
-}

+ 0 - 82
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/DeviceService.java

@@ -1,82 +0,0 @@
-package cc.iotkit.mqttauth.service;
-
-import cc.iotkit.common.exception.BizException;
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.product.Product;
-import cc.iotkit.mqttauth.dao.DeviceDao;
-import cc.iotkit.mqttauth.dao.ProductDao;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.RandomUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-@Slf4j
-@Service
-public class DeviceService {
-
-    @Autowired
-    private DeviceDao deviceDao;
-    @Autowired
-    private ProductDao productDao;
-
-    public DeviceInfo register(DeviceInfo device) {
-
-        String pk = device.getProductKey();
-        Product product = productDao.getProduct(pk);
-        if (product == null) {
-            throw new BizException("Product does not exist");
-        }
-        String uid = product.getUid();
-
-        DeviceInfo deviceInfo = deviceDao.getByPkAndDn(pk, device.getDeviceName());
-        if (deviceInfo != null) {
-            device.setDeviceId(deviceInfo.getDeviceId());
-            device.setUid(uid);
-            deviceDao.updateDevice(device);
-            log.info("device register update:{}", JsonUtil.toJsonString(device));
-            return device;
-        }
-
-        device.setUid(uid);
-        device.setDeviceId(newDeviceId(device.getDeviceName()));
-        deviceDao.addDevice(device);
-        log.info("device registered:{}", JsonUtil.toJsonString(device));
-        return device;
-    }
-
-    public DeviceInfo getByPkAndDn(String pk, String dn) {
-        return deviceDao.getByPkAndDn(pk, dn);
-    }
-
-    public void online(String pk, String dn) {
-        DeviceInfo device = new DeviceInfo();
-        device.setProductKey(pk);
-        device.setDeviceName(dn);
-
-        device.getState().setOnline(true);
-        device.getState().setOnlineTime(System.currentTimeMillis());
-        deviceDao.updateDeviceByPkAndDn(device);
-    }
-
-    /**
-     * 1-13位	时间戳
-     * 14-29位	deviceNae,去除非字母和数字,不足16位补0,超过16位的mac取后16位,共16位
-     * 30-31位	mac长度,共2位
-     * 32位	随机一个0-f字符
-     */
-    public static String newDeviceId(String deviceNae) {
-        int maxDnLen = 16;
-        String dn = deviceNae.replaceAll("[^0-9A-Za-z]", "");
-        if (dn.length() > maxDnLen) {
-            dn = dn.substring(dn.length() - maxDnLen);
-        } else {
-            dn = (dn + "00000000000000000000").substring(0, maxDnLen);
-        }
-        String len = StringUtils.leftPad(deviceNae.length() + "", 2, '0');
-        String rnd = Integer.toHexString(RandomUtils.nextInt(0, 16));
-        return (System.currentTimeMillis() + "0" + dn + len + rnd).toLowerCase();
-    }
-
-}

+ 0 - 12
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/MqttAuth.java

@@ -1,12 +0,0 @@
-package cc.iotkit.mqttauth.service;
-
-import cc.iotkit.mqttauth.model.EmqAcl;
-import cc.iotkit.mqttauth.model.EmqAuthInfo;
-
-public interface MqttAuth {
-
-    void auth(EmqAuthInfo auth);
-
-    void acl(EmqAcl acl);
-
-}

+ 0 - 42
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/SysMqttAuth.java

@@ -1,42 +0,0 @@
-package cc.iotkit.mqttauth.service;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.CodecUtil;
-import cc.iotkit.mqttauth.model.EmqAcl;
-import cc.iotkit.mqttauth.model.EmqAuthInfo;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.stereotype.Component;
-
-@Slf4j
-@Component("SysMqttAuth")
-public class SysMqttAuth implements MqttAuth {
-    @Override
-    public void auth(EmqAuthInfo auth) {
-        try {
-            //password= aes(sy_username,ACCOUNT_SECRET)
-            String uid = auth.getUsername();
-            String codes = CodecUtil.aesDecryptHex(auth.getPassword(), Constants.ACCOUNT_SECRET);
-            if (StringUtils.isBlank(codes)) {
-                throw new RuntimeException("mqtt auth failed,pwd error.");
-            }
-            //解出来的用户id与username是否一致
-            String[] parts = codes.split("_");
-            if (parts.length < 2 || !uid.equals(parts[1])) {
-                throw new RuntimeException("mqtt auth failed,pw validate error.");
-            }
-        } catch (Throwable e) {
-            log.error("sys user mqtt failed.", e);
-            throw new RuntimeException("mqtt auth failed:" + e.getMessage());
-        }
-    }
-
-    @Override
-    public void acl(EmqAcl acl) {
-        //平台用户可订阅以所有设备
-//        String topic = acl.getTopic();
-//        if (!topic.startsWith("/app/")) {
-//            throw new RuntimeException("acl failed.");
-//        }
-    }
-}

+ 0 - 18
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/WxMqttAuth.java

@@ -1,18 +0,0 @@
-package cc.iotkit.mqttauth.service;
-
-import cc.iotkit.mqttauth.model.EmqAcl;
-import cc.iotkit.mqttauth.model.EmqAuthInfo;
-import org.springframework.stereotype.Component;
-
-@Component("WxMqttAuth")
-public class WxMqttAuth implements MqttAuth {
-    @Override
-    public void auth(EmqAuthInfo auth) {
-
-    }
-
-    @Override
-    public void acl(EmqAcl acl) {
-
-    }
-}

+ 0 - 5
device-server/mqtt-auth/src/main/resources/application-dev.yml

@@ -1,5 +0,0 @@
-spring:
-  data:
-    mongodb:
-      uri: mongodb://填写mongodb地址/admin
-      database: iotkit

+ 0 - 5
device-server/mqtt-auth/src/main/resources/application.yml

@@ -1,5 +0,0 @@
-spring:
-  data:
-    mongodb:
-      uri: mongodb://填写mongodb地址/admin
-      database: iotkit

+ 0 - 23
device-server/mqtt-auth/src/test/java/SupperUser.java

@@ -1,23 +0,0 @@
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.CodecUtil;
-import cc.iotkit.mqttauth.controller.MqttAuthController;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class SupperUser {
-
-    @Test
-    public void createSuperuser() throws Exception {
-        //mqtt生成超级用户,作为mqtt-server连接mqtt的clientId
-        String clientId = "mqtt-server-producer-dev";
-        System.out.println("clientId:su_" + CodecUtil.aesEncrypt("admin_" + clientId, Constants.MQTT_SECRET));
-    }
-
-    @Test
-    public void isSupperUser() {
-        String clientId = "su_344A6E61654F567A30536E59646A306659664A75625A374D35484756776D457977374653684B306B414E513D";
-//        String clientId = "su_tng1t408QrZDEoM7CxiDueP++4FmXIxS7x35YbpuNf8=";
-        MqttAuthController authController = new MqttAuthController();
-        Assert.assertTrue(authController.isSupperUser(clientId));
-    }
-}

+ 0 - 13
device-server/mqtt-auth/src/test/java/SysMqttAuth.java

@@ -1,13 +0,0 @@
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.CodecUtil;
-import org.junit.Test;
-
-public class SysMqttAuth {
-
-    @Test
-    public void createSyPwd() throws Exception {
-        System.out.println(CodecUtil.aesEncrypt("sy_gateway_dev", Constants.ACCOUNT_SECRET));
-        System.out.println(CodecUtil.aesDecryptHex("4B6272544E59324C596562686173494A696E764E69673D3D", Constants.ACCOUNT_SECRET));
-    }
-
-}

BIN
device-server/mqtt-server/log/error.2022-01-10.0.gz


BIN
device-server/mqtt-server/log/error.2022-01-11.0.gz


BIN
device-server/mqtt-server/log/error.2022-01-12.0.gz


BIN
device-server/mqtt-server/log/error.2022-01-13.0.gz


BIN
device-server/mqtt-server/log/info.2022-01-10.0.gz


BIN
device-server/mqtt-server/log/info.2022-01-11.0.gz


BIN
device-server/mqtt-server/log/info.2022-01-12.0.gz


BIN
device-server/mqtt-server/log/info.2022-01-13.0.gz


+ 8 - 50
device-server/mqtt-server/pom.xml

@@ -12,79 +12,31 @@
     <artifactId>mqtt-server</artifactId>
 
     <dependencies>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-mongodb</artifactId>
-        </dependency>
 
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-integration</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.integration</groupId>
-            <artifactId>spring-integration-mqtt</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-cache</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-commons</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.ben-manes.caffeine</groupId>
-            <artifactId>caffeine</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <optional>true</optional>
         </dependency>
 
-        <dependency>
-            <groupId>commons-beanutils</groupId>
-            <artifactId>commons-beanutils</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>commons-codec</groupId>
             <artifactId>commons-codec</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
         </dependency>
 
         <dependency>
-            <groupId>joda-time</groupId>
-            <artifactId>joda-time</artifactId>
+            <groupId>org.eclipse.paho</groupId>
+            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
         </dependency>
 
         <dependency>
@@ -96,11 +48,17 @@
             <groupId>cc.iotkit</groupId>
             <artifactId>common</artifactId>
         </dependency>
+
         <dependency>
             <groupId>cc.iotkit</groupId>
             <artifactId>device-api</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>cc.iotkit</groupId>
+            <artifactId>gateway-client</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 0 - 43
device-server/mqtt-server/src/main/java/cc/iotkit/server/config/CacheConfig.java

@@ -1,43 +0,0 @@
-package cc.iotkit.server.config;
-
-import com.github.benmanes.caffeine.cache.Caffeine;
-import com.google.common.collect.Lists;
-import org.springframework.cache.CacheManager;
-import org.springframework.cache.caffeine.CaffeineCache;
-import org.springframework.cache.support.SimpleCacheManager;
-import org.springframework.context.annotation.Bean;
-
-import java.util.concurrent.TimeUnit;
-
-//@Configuration
-//@EnableCaching
-public class CacheConfig {
-
-    /**
-     * 配置本地缓存
-     */
-    @Bean
-    public CacheManager cacheManager() {
-        SimpleCacheManager manager = new SimpleCacheManager();
-        manager.setCaches(Lists.newArrayList(new CaffeineCache(
-                        "device_cache",
-                        Caffeine.newBuilder()
-                                .expireAfterWrite(5, TimeUnit.MINUTES)
-                                .build()
-                ),
-                new CaffeineCache(
-                        "product_cache",
-                        Caffeine.newBuilder()
-                                .expireAfterWrite(5, TimeUnit.MINUTES)
-                                .build()
-                ),
-                new CaffeineCache(
-                        "app_design_cache",
-                        Caffeine.newBuilder()
-                                .expireAfterWrite(5, TimeUnit.MINUTES)
-                                .build()
-                )));
-        return manager;
-    }
-
-}

+ 0 - 42
device-server/mqtt-server/src/main/java/cc/iotkit/server/config/GlobalExceptionHandler.java

@@ -1,42 +0,0 @@
-package cc.iotkit.server.config;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.ControllerAdvice;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.servlet.http.HttpServletResponse;
-
-@Slf4j
-@ControllerAdvice
-public class GlobalExceptionHandler {
-
-    @ExceptionHandler(Exception.class)
-    @ResponseBody
-    public RequestResult handleException(Exception e, HttpServletResponse response) {
-        log.error("handler exception", e);
-        if(e.getMessage().contains("Unauthorized")){
-            response.setStatus(403);
-            return new RequestResult("403", "没有权限");
-        }
-        response.setStatus(500);
-        return new RequestResult("500", e.getMessage());
-    }
-
-    @NoArgsConstructor
-    @AllArgsConstructor
-    @Data
-    public static class RequestResult {
-
-        private String code;
-
-        private String message;
-
-    }
-
-}
-
-

+ 0 - 147
device-server/mqtt-server/src/main/java/cc/iotkit/server/config/MqttConfig.java

@@ -1,147 +0,0 @@
-package cc.iotkit.server.config;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.CodecUtil;
-import cc.iotkit.server.handler.MqttConsumerHandler;
-import lombok.SneakyThrows;
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.integration.annotation.ServiceActivator;
-import org.springframework.integration.channel.DirectChannel;
-import org.springframework.integration.core.MessageProducer;
-import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
-import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
-import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
-import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
-import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
-import org.springframework.messaging.MessageChannel;
-import org.springframework.messaging.MessageHandler;
-
-@Configuration
-public class MqttConfig {
-
-    /**
-     * 订阅的bean名称
-     */
-    public static final String CHANNEL_NAME_IN = "mqttInboundChannel";
-    /**
-     * 发布的bean名称
-     */
-    public static final String CHANNEL_NAME_OUT = "mqttOutboundChannel";
-
-    @Value("${mqtt.url}")
-    private String url;
-
-    @Value(("${spring.profiles.active:}"))
-    private String env;
-
-    /**
-     * MQTT连接器选项
-     *
-     * @return {@link MqttConnectOptions}
-     */
-    @Bean
-    public MqttConnectOptions getMqttConnectOptions() {
-        MqttConnectOptions options = new MqttConnectOptions();
-        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,
-        // 这里设置为true表示每次连接到服务器都以新的身份连接
-        options.setCleanSession(true);
-        // 设置连接的用户名
-        options.setUserName("admin");
-        // 设置连接的密码
-        options.setPassword("password".toCharArray());
-        options.setServerURIs(StringUtils.split(url, ","));
-        // 设置超时时间 单位为秒
-        options.setConnectionTimeout(10);
-        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线,但这个方法并没有重连的机制
-        options.setKeepAliveInterval(20);
-        return options;
-    }
-
-    /**
-     * MQTT客户端
-     *
-     * @return {@link MqttPahoClientFactory}
-     */
-    @Bean
-    public MqttPahoClientFactory mqttClientFactory() {
-        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
-        factory.setConnectionOptions(getMqttConnectOptions());
-        return factory;
-    }
-
-    /**
-     * MQTT信息通道(生产者)
-     *
-     * @return {@link MessageChannel}
-     */
-    @Bean(name = CHANNEL_NAME_OUT)
-    public MessageChannel mqttOutboundChannel() {
-        return new DirectChannel();
-    }
-
-    /**
-     * MQTT消息处理器(生产者)
-     *
-     * @return {@link MessageHandler}
-     */
-    @SneakyThrows
-    @Bean
-    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
-    public MessageHandler mqttOutbound() {
-        String clientId = "mqtt-server-producer-" + env;
-        clientId = "su_" + CodecUtil.aesEncrypt("admin_" + clientId, Constants.MQTT_SECRET);
-        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(
-                clientId,
-                mqttClientFactory());
-        messageHandler.setAsync(true);
-        return messageHandler;
-    }
-
-    /**
-     * MQTT消息订阅绑定(消费者)
-     *
-     * @return {@link MessageProducer}
-     */
-    @SneakyThrows
-    @Bean
-    public MessageProducer inbound() {
-        // 可以同时消费(订阅)多个Topic
-        String clientId = "mqtt-server-consumer-" + env;
-        clientId = "su_" + CodecUtil.aesEncrypt("admin_" + clientId, Constants.MQTT_SECRET);
-        MqttPahoMessageDrivenChannelAdapter adapter =
-                new MqttPahoMessageDrivenChannelAdapter(
-                        clientId, mqttClientFactory(),
-                        "/sys/#");
-        adapter.setCompletionTimeout(5000);
-        adapter.setConverter(new DefaultPahoMessageConverter());
-        adapter.setQos(1);
-        // 设置订阅通道
-        adapter.setOutputChannel(mqttInboundChannel());
-        return adapter;
-    }
-
-    /**
-     * MQTT信息通道(消费者)
-     *
-     * @return {@link MessageChannel}
-     */
-    @Bean(name = CHANNEL_NAME_IN)
-    public MessageChannel mqttInboundChannel() {
-        return new DirectChannel();
-    }
-
-    /**
-     * MQTT消息处理器(消费者)
-     *
-     * @return {@link MessageHandler}
-     */
-    @Bean
-    @ServiceActivator(inputChannel = CHANNEL_NAME_IN)
-    public MessageHandler handler() {
-        return new MqttConsumerHandler();
-    }
-}

+ 0 - 55
device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/BaseDao.java

@@ -1,55 +0,0 @@
-package cc.iotkit.server.dao;
-
-import org.springframework.data.domain.Sort;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-
-import java.util.List;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-import static org.springframework.data.mongodb.core.query.Query.query;
-
-public class BaseDao<T> {
-
-    protected MongoTemplate mongoTemplate;
-
-    private Class<T> cls;
-
-    public BaseDao(MongoTemplate mongoTemplate, Class<T> cls) {
-        this.mongoTemplate = mongoTemplate;
-        this.cls = cls;
-    }
-
-    public List<T> find(Criteria condition) {
-        Query query = new Query();
-        query.addCriteria(condition);
-        return mongoTemplate.find(query, cls);
-    }
-
-    public List<T> find(Criteria condition, long skip, int count, Sort.Order order) {
-        Query query = new Query();
-        query.addCriteria(condition)
-                .with(Sort.by(order))
-                .skip(skip)
-                .limit(count);
-        return mongoTemplate.find(query, cls);
-    }
-
-    public long count(Criteria condition) {
-        Query query = new Query();
-        query.addCriteria(condition);
-        return mongoTemplate.count(query, cls);
-    }
-
-    public <T> T save(String id, T entity) {
-        if (id == null) {
-            return mongoTemplate.save(entity);
-        } else {
-            mongoTemplate.updateFirst(query(where("_id").is(id)),
-                    DaoTool.update(entity), entity.getClass());
-            return (T) mongoTemplate.findById(id, entity.getClass());
-        }
-    }
-
-}

+ 0 - 53
device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DaoTool.java

@@ -1,53 +0,0 @@
-package cc.iotkit.server.dao;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.SneakyThrows;
-import org.apache.commons.beanutils.BeanMap;
-import org.springframework.data.mongodb.core.query.Update;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class DaoTool {
-
-    public static void update(Update update, List<Prop> props) {
-        for (Prop pro : props) {
-            update.set(pro.getName(), pro.getValue());
-        }
-    }
-
-    public static List<Prop> getProp(String key, Object value) {
-        List<Prop> props = new ArrayList<>();
-        if (value instanceof Map) {
-            Set<Map.Entry<String, Object>> entrySet = ((Map) value).entrySet();
-            for (Map.Entry<String, Object> entry : entrySet) {
-                props.addAll(getProp(key + "." + entry.getKey(), entry.getValue()));
-            }
-        } else if (value != null && !(value instanceof Class)) {
-            props.add(new Prop(key, value));
-        }
-        return props;
-    }
-
-    @SneakyThrows
-    public static <T> Update update(T obj) {
-        Map<Object, Object> pros = new BeanMap(obj);
-        Update update = new Update();
-        for (Map.Entry<Object, Object> entry : pros.entrySet()) {
-            update(update, DaoTool.getProp(entry.getKey().toString(), entry.getValue()));
-        }
-        return update;
-    }
-
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    static class Prop {
-        private String name;
-        private Object value;
-    }
-}

+ 0 - 62
device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DeviceDao.java

@@ -1,62 +0,0 @@
-package cc.iotkit.server.dao;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.model.device.DeviceInfo;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Repository;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-import static org.springframework.data.mongodb.core.query.Query.query;
-
-@Repository
-public class DeviceDao extends BaseDao<DeviceInfo> {
-
-    @Autowired
-    private DeviceRepository deviceRepository;
-
-    @Autowired
-    public DeviceDao(MongoTemplate mongoTemplate) {
-        super(mongoTemplate, DeviceInfo.class);
-    }
-
-    public void addDevice(DeviceInfo device) {
-        device.setCreateAt(System.currentTimeMillis());
-        mongoTemplate.insert(device);
-    }
-
-    public void updateDevice(DeviceInfo device) {
-        if (device.getDeviceId() == null) {
-            return;
-        }
-        mongoTemplate.updateFirst(query(where("deviceId").is(device.getDeviceId())),
-                DaoTool.update(device), DeviceInfo.class);
-    }
-
-    public void updateDeviceByPkAndDn(DeviceInfo device) {
-        if (device.getProductKey() == null || device.getDeviceName() == null) {
-            return;
-        }
-        mongoTemplate.updateFirst(query(where("productKey").is(device.getProductKey()).
-                        and("deviceName").is(device.getDeviceName())),
-                DaoTool.update(device), DeviceInfo.class);
-    }
-
-    @Cacheable(value = "deviceInfoCache", key = "#pk+'_'+#dn")
-    public DeviceInfo getByPkAndDn(String pk, String dn) {
-        Query query = query(where("productKey").is(pk).and("deviceName").is(dn));
-        return mongoTemplate.findOne(query, DeviceInfo.class);
-    }
-
-    public DeviceInfo getByDeviceId(String deviceId) {
-        Query query = query(where("deviceId").is(deviceId));
-        return mongoTemplate.findOne(query, DeviceInfo.class);
-    }
-
-    @Cacheable(value = Constants.DEVICE_CACHE, key = "#deviceId")
-    public DeviceInfo get(String deviceId) {
-        return deviceRepository.findById(deviceId).orElse(new DeviceInfo());
-    }
-}

+ 0 - 13
device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DeviceEventRepository.java

@@ -1,13 +0,0 @@
-package cc.iotkit.server.dao;
-
-import cc.iotkit.model.device.message.DeviceEvent;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface DeviceEventRepository extends MongoRepository<DeviceEvent, String> {
-
-    Page<DeviceEvent> findByDeviceId(String deviceId, Pageable pageable);
-}

+ 0 - 9
device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/DeviceRepository.java

@@ -1,9 +0,0 @@
-package cc.iotkit.server.dao;
-
-import cc.iotkit.model.device.DeviceInfo;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface DeviceRepository extends MongoRepository<DeviceInfo, String> {
-}

+ 0 - 9
device-server/mqtt-server/src/main/java/cc/iotkit/server/dao/ThingModelRepository.java

@@ -1,9 +0,0 @@
-package cc.iotkit.server.dao;
-
-import cc.iotkit.model.product.ThingModel;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface ThingModelRepository extends MongoRepository<ThingModel, String> {
-}

+ 0 - 63
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/DisconnectedHandler.java

@@ -1,63 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.server.dao.DeviceRepository;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.server.service.DeviceService;
-import com.fasterxml.jackson.core.type.TypeReference;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-@Slf4j
-@Component
-public class DisconnectedHandler {
-
-    @Autowired
-    private DeviceService deviceService;
-    @Autowired
-    private DeviceRepository deviceRepository;
-
-    public void handler(String msg) {
-        Disconnected disconnected = JsonUtil.parse(msg, new TypeReference<Disconnected>() {
-        });
-        String clientId = disconnected.getClientid();
-        String[] parts = clientId.split("_");
-        if (parts.length < 2) {
-            return;
-        }
-        String pk = parts[0];
-        String dn = parts[1];
-        log.info("gateway disconnected, offline,pk:{},dn:{}", pk, dn);
-
-        DeviceInfo example = new DeviceInfo();
-        example.setProductKey(pk);
-        example.setDeviceName(dn);
-        DeviceInfo device = deviceRepository.findOne(Example.of(example)).orElse(new DeviceInfo());
-        if (device.getDeviceId() == null) {
-            log.error("no device found by pk:{} and dn:{}", pk, dn);
-            return;
-        }
-        deviceService.offline(pk, dn);
-
-        example = new DeviceInfo();
-        example.setParentId(device.getDeviceId());
-        //子设备下线
-        List<DeviceInfo> children = deviceRepository.findAll(Example.of(example));
-        children.forEach(c -> deviceService.offline(c.getProductKey(), c.getDeviceName()));
-    }
-
-    @Data
-    private static class Disconnected {
-        private String reason;
-        private String clientid;
-        private String username;
-        private String peername;
-        private String sockname;
-    }
-
-}

+ 0 - 49
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/EventReportHandler.java

@@ -1,49 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.server.dao.DeviceEventRepository;
-import cc.iotkit.model.device.message.DeviceEvent;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.model.mq.Response;
-import com.fasterxml.jackson.core.type.TypeReference;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-import java.util.regex.Pattern;
-
-@Component
-public class EventReportHandler implements MqttHandler<Map<String, Object>, Response.Empty> {
-
-    private static final Pattern MATCH_REG = Pattern.compile("^/sys/\\w+/\\w+/s/event/[^_/]+$");
-
-    @Autowired
-    DeviceEventRepository deviceEventRepository;
-
-    @Override
-    public boolean compliant(String topic) {
-        return MATCH_REG.matcher(topic).matches();
-    }
-
-    @Override
-    public Request parse(String msg) {
-        return JsonUtil.parse(msg, new TypeReference<Request>() {
-        });
-    }
-
-    @Override
-    public Response.Empty handler(String topic, DeviceInfo device, Request request) {
-        String identifier = topic.substring(topic.indexOf("/event/") + 7);
-        DeviceEvent event = DeviceEvent.builder()
-                .deviceId(device.getDeviceId())
-                .identifier(identifier)
-                .request(request)
-                .type(topic.endsWith("_reply") ? "ack" : "event")
-                .createAt(System.currentTimeMillis())
-                .build();
-        deviceEventRepository.save(event);
-        return Response.empty();
-    }
-
-}

+ 0 - 162
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/MqttConsumerHandler.java

@@ -1,162 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.server.dao.DeviceDao;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.model.mq.Response;
-import cc.iotkit.server.service.DeviceService;
-import cc.iotkit.server.service.IMqttSender;
-import com.fasterxml.jackson.core.type.TypeReference;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageHandler;
-import org.springframework.messaging.MessageHeaders;
-import org.springframework.messaging.MessagingException;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Slf4j
-public class MqttConsumerHandler implements MessageHandler, ApplicationContextAware {
-
-    private List<MqttHandler> mqttHandlers = new ArrayList<>();
-
-    @Autowired
-    private DeviceDao deviceDao;
-    @Autowired
-    private IMqttSender mqttSender;
-    @Autowired
-    private DeviceService deviceService;
-    @Autowired
-    private DisconnectedHandler disconnectedHandler;
-
-    @Override
-    public void handleMessage(Message<?> msg) throws MessagingException {
-        log.info(JsonUtil.toJsonString(msg));
-        MessageHeaders headers = msg.getHeaders();
-        String topic = headers.get("mqtt_receivedTopic", String.class);
-        if (topic == null) {
-            log.error("message topic is null.");
-            return;
-        }
-
-        if (topic.equals("/sys/session/topic/unsubscribed")) {
-            topicUnsubscribed(msg.getPayload().toString());
-            return;
-        }
-
-        if (topic.equals("/sys/client/disconnected")) {
-            disconnectedHandler.handler(msg.getPayload().toString());
-            return;
-        }
-
-        String[] parts = topic.split("/");
-        if (parts.length < 5) {
-            log.error("message topic is illegal.");
-            return;
-        }
-
-        String pk = parts[2];
-        String dn = parts[3];
-        DeviceInfo device = deviceDao.getByPkAndDn(pk, dn);
-        if (device == null) {
-            log.warn("device not found by pk and dn.");
-            return;
-        }
-        String payload = msg.getPayload().toString();
-
-        //转发到deviceId对应的topic中给客户端消费
-        sendToAppClientTopic(device.getDeviceId(), topic, payload);
-
-        Object result = null;
-        Request<?> request = new Request<>();
-        try {
-            for (MqttHandler handler : mqttHandlers) {
-                if (!handler.compliant(topic)) {
-                    continue;
-                }
-                request = handler.parse(payload);
-                result = handler.handler(topic, device, request);
-            }
-        } catch (Throwable e) {
-            log.error("handler mqtt msg error.", e);
-            reply(device.getDeviceId(), topic, request.getId(), 1, "");
-            return;
-        }
-
-        if (result == null) {
-            return;
-        }
-
-        reply(device.getDeviceId(), topic, request.getId(), 0, result);
-    }
-
-    private void reply(String deviceId, String topic, String id, int code, Object result) {
-        topic = topic.replace("/s/", "/c/") + "_reply";
-        String msg = JsonUtil.toJsonString(new Response<>(id, code, result));
-        mqttSender.sendToMqtt(topic, msg);
-        sendToAppClientTopic(deviceId, topic, msg);
-    }
-
-    private void topicUnsubscribed(String msg) {
-        Unsubscribed unsubscribed = JsonUtil.parse(msg, new TypeReference<Unsubscribed>() {
-        });
-        String topic = unsubscribed.getTopic();
-        String[] parts = topic.split("/");
-        if (parts.length < 4) {
-            return;
-        }
-
-        log.info("device offline,pk:{},dn:{}", parts[2], parts[3]);
-        deviceService.offline(parts[2], parts[3]);
-    }
-
-    private void sendToAppClientTopic(String deviceId, String topic, String msg) {
-        //排除服务调用和属性设置消息
-        if (topic.contains("/c/service/") || topic.endsWith("/post_reply")) {
-            return;
-        }
-
-        //发给app端订阅消息
-        distributeMsg(Constants.TOPIC_PREFIX_APP, topic, deviceId, msg);
-        //发送给第三方接入gateway
-        distributeMsg(Constants.TOPIC_PREFIX_GATEWAY, topic, deviceId, msg);
-    }
-
-    /**
-     * 分发消息
-     */
-    void distributeMsg(String topicNamePrefix, String topic, String deviceId, String msg) {
-        /*
-        /app/xxxdeviceId/event/事件名
-        /app/xxxdeviceId/event/property/post
-        /app/xxxdeviceId/service/服务名_reply
-         */
-        String distTopic = "/" + topicNamePrefix + "/" + deviceId + "/" +
-                (topic.replaceAll("/sys/.*/s/", "")
-                        .replaceAll("/sys/.*/c/", ""));
-        log.info("send msg:{},to topic:{}", JsonUtil.toJsonString(msg), distTopic);
-        //转发到deviceId对应的topic中给客户端消费
-        mqttSender.sendToMqtt(distTopic, msg);
-    }
-
-    @Override
-    public void setApplicationContext(ApplicationContext context) throws BeansException {
-        mqttHandlers.addAll(context.getBeansOfType(MqttHandler.class).values());
-    }
-
-    @Data
-    private static class Unsubscribed {
-        private String clientid;
-        private String username;
-        private String topic;
-        private String peerhost;
-    }
-}

+ 0 - 14
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/MqttHandler.java

@@ -1,14 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.mq.Request;
-
-public interface MqttHandler<T, R> {
-
-    boolean compliant(String topic);
-
-    Request<T> parse(String msg);
-
-    R handler(String topic, DeviceInfo device, Request<T> request);
-
-}

+ 0 - 62
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/PropertyPostHandler.java

@@ -1,62 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.server.dao.DeviceEventRepository;
-import cc.iotkit.server.dao.DeviceRepository;
-import cc.iotkit.model.device.message.DeviceEvent;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.model.mq.Response;
-import com.fasterxml.jackson.core.type.TypeReference;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Slf4j
-@Component
-public class PropertyPostHandler implements MqttHandler<Map<String, Object>, Response.Empty> {
-
-    @Autowired
-    DeviceRepository deviceRepository;
-    @Autowired
-    DeviceEventRepository deviceEventRepository;
-
-    @Override
-    public boolean compliant(String topic) {
-        return topic.endsWith("/event/property/post");
-    }
-
-    @Override
-    public Request<Map<String, Object>> parse(String msg) {
-        return JsonUtil.parse(msg, new TypeReference<Request<Map<String, Object>>>() {
-        });
-    }
-
-    @Override
-    public Response.Empty handler(String topic, DeviceInfo device, Request<Map<String, Object>> request) {
-        device.setId(device.getDeviceId());
-        if (device.getProperty() == null) {
-            device.setProperty(new HashMap<>());
-        }
-        Map<String, Object> newProps = request.getParams();
-        if (newProps != null && newProps.size() > 0) {
-            request.getParams().forEach(device.getProperty()::put);
-        }
-
-        deviceRepository.save(device);
-
-        DeviceEvent event = DeviceEvent.builder()
-                .deviceId(device.getDeviceId())
-                .identifier("propertyPost")
-                .request(request)
-                .type("property")
-                .createAt(System.currentTimeMillis())
-                .build();
-        deviceEventRepository.save(event);
-        return Response.empty();
-    }
-
-}

+ 0 - 47
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/PropertyReplyHandler.java

@@ -1,47 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.server.dao.DeviceEventRepository;
-import cc.iotkit.model.device.message.DeviceEvent;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.model.mq.Response;
-import com.fasterxml.jackson.core.type.TypeReference;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-
-@Component
-public class PropertyReplyHandler implements MqttHandler<Map<String, Object>, Response.Empty> {
-
-    @Autowired
-    DeviceEventRepository deviceEventRepository;
-
-    @Override
-    public boolean compliant(String topic) {
-        return topic.endsWith("/service/property/set_reply");
-    }
-
-    @Override
-    public Request<Map<String, Object>> parse(String msg) {
-        return JsonUtil.parse(msg, new TypeReference<Request<Map<String, Object>>>() {
-        });
-    }
-
-    @Override
-    public Response.Empty handler(String topic, DeviceInfo device, Request<Map<String, Object>> request) {
-        String identifier = "propertySetReply";
-        DeviceEvent event =
-                DeviceEvent.builder()
-                .deviceId(device.getDeviceId())
-                .identifier(identifier)
-                .request(request)
-                .type("ack")
-                .createAt(System.currentTimeMillis())
-                .build();
-        deviceEventRepository.save(event);
-        return null;
-    }
-
-}

+ 0 - 36
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/RegisterHandler.java

@@ -1,36 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.device.message.DeviceRegister;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.server.service.DeviceService;
-import com.fasterxml.jackson.core.type.TypeReference;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-@Component
-public class RegisterHandler implements MqttHandler<DeviceRegister, DeviceRegister> {
-
-    @Autowired
-    private DeviceService deviceService;
-
-    @Override
-    public boolean compliant(String topic) {
-        return topic.endsWith("/register");
-    }
-
-    @Override
-    public Request<DeviceRegister> parse(String msg) {
-        return JsonUtil.parse(msg, new TypeReference<Request<DeviceRegister>>() {
-        });
-    }
-
-    @Override
-    public DeviceRegister handler(String topic, DeviceInfo device, Request<DeviceRegister> request) {
-        DeviceRegister regInfo = request.getParams();
-        deviceService.register(device.getDeviceId(), regInfo.getProductKey(),
-                regInfo.getDeviceName(), regInfo.getModel());
-        return regInfo;
-    }
-}

+ 0 - 49
device-server/mqtt-server/src/main/java/cc/iotkit/server/handler/ServiceReplyHandler.java

@@ -1,49 +0,0 @@
-package cc.iotkit.server.handler;
-
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.server.dao.DeviceEventRepository;
-import cc.iotkit.model.device.message.DeviceEvent;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.model.mq.Response;
-import com.fasterxml.jackson.core.type.TypeReference;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-import java.util.regex.Pattern;
-
-@Component
-public class ServiceReplyHandler implements MqttHandler<Map<String, Object>, Response.Empty> {
-
-    private static final Pattern MATCH_REG = Pattern.compile("^/sys/\\w+/\\w+/s/service/[^_/]+_reply$");
-
-    @Autowired
-    DeviceEventRepository deviceEventRepository;
-
-    @Override
-    public boolean compliant(String topic) {
-        return MATCH_REG.matcher(topic).matches();
-    }
-
-    @Override
-    public Request<Map<String, Object>> parse(String msg) {
-        return JsonUtil.parse(msg, new TypeReference<Request<Map<String, Object>>>() {
-        });
-    }
-
-    @Override
-    public Response.Empty handler(String topic, DeviceInfo device, Request<Map<String, Object>> request) {
-        String identifier = topic.substring(topic.indexOf("/service/") + 9);
-        DeviceEvent event = DeviceEvent.builder()
-                .deviceId(device.getDeviceId())
-                .identifier(identifier)
-                .request(request)
-                .type("ack")
-                .createAt(System.currentTimeMillis())
-                .build();
-        deviceEventRepository.save(event);
-        return null;
-    }
-
-}

+ 1 - 1
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/Application.java → device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/Application.java

@@ -1,4 +1,4 @@
-package cc.iotkit.mqttauth;
+package cc.iotkit.server.mqtt;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;

+ 19 - 0
device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/config/AutobeanConfig.java

@@ -0,0 +1,19 @@
+package cc.iotkit.server.mqtt.config;
+
+import cc.iotkit.protocol.client.DeviceBehaviourClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AutobeanConfig {
+
+    @Value("${gateway.server:}")
+    private String gatewayServer;
+
+    @Bean
+    public DeviceBehaviourClient getDeviceBehaviourClient() {
+        return new DeviceBehaviourClient(gatewayServer);
+    }
+
+}

+ 47 - 0
device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/DeviceController.java

@@ -0,0 +1,47 @@
+package cc.iotkit.server.mqtt.controller;
+
+import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.protocol.DeviceGateway;
+import cc.iotkit.protocol.DeviceMessage;
+import cc.iotkit.protocol.OtaInfo;
+import cc.iotkit.protocol.Result;
+import cc.iotkit.server.mqtt.service.MqttManager;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j
+@RestController
+public class DeviceController implements DeviceGateway {
+
+    @Autowired
+    private MqttManager mqttManager;
+
+    @Override
+    public Result sendMessage(DeviceMessage msg) {
+        try {
+            MqttMessage mqttMessage = JsonUtil.parse(msg.getContent(), MqttMessage.class);
+            mqttManager.sendMsg(mqttMessage.getTopic(), mqttMessage.getPayload());
+            return new Result(true, "");
+        } catch (Throwable e) {
+            log.error("send message error", e);
+            return new Result(false, e.getMessage());
+        }
+    }
+
+    @Override
+    public Result sendOta(OtaInfo ota) {
+        return null;
+    }
+
+    @Data
+    public static class MqttMessage {
+
+        private String topic;
+
+        private String payload;
+
+    }
+
+}

+ 9 - 30
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/controller/MqttAuthController.java → device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/MqttAuthController.java

@@ -1,15 +1,12 @@
-package cc.iotkit.mqttauth.controller;
+package cc.iotkit.server.mqtt.controller;
 
 
 import cc.iotkit.common.Constants;
 import cc.iotkit.common.utils.CodecUtil;
 import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.mqttauth.model.EmqAcl;
-import cc.iotkit.mqttauth.model.EmqAuthInfo;
-import cc.iotkit.mqttauth.service.DeviceMqttAuth;
-import cc.iotkit.mqttauth.service.MqttAuth;
-import cc.iotkit.mqttauth.service.SysMqttAuth;
-import cc.iotkit.mqttauth.service.WxMqttAuth;
+import cc.iotkit.server.mqtt.model.EmqAcl;
+import cc.iotkit.server.mqtt.model.EmqAuthInfo;
+import cc.iotkit.server.mqtt.service.DeviceAuthService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -23,11 +20,7 @@ import javax.servlet.http.HttpServletResponse;
 public class MqttAuthController {
 
     @Autowired
-    private DeviceMqttAuth deviceMqttAuth;
-    @Autowired
-    private WxMqttAuth wxMqttAuth;
-    @Autowired
-    private SysMqttAuth sysMqttAuth;
+    private DeviceAuthService deviceAuthService;
 
     @PostMapping("/mqtt/auth")
     public void auth(@RequestBody EmqAuthInfo auth) {
@@ -36,27 +29,22 @@ public class MqttAuthController {
         if (isSupperUser(clientId)) {
             return;
         }
-        MqttAuth mqttAuth = getMqttAuth(clientId);
-        mqttAuth.auth(auth);
+        deviceAuthService.auth(auth);
     }
 
     @PostMapping("/mqtt/acl")
     public void acl(@RequestBody EmqAcl acl) {
-        log.info("mqtt acl:" + JsonUtil.toJsonString(acl));
+        log.info("mqtt acl:{}", JsonUtil.toJsonString(acl));
         if (isSupperUser(acl.getClientid())) {
             return;
         }
-        MqttAuth mqttAuth = getMqttAuth(acl.getClientid());
-        mqttAuth.acl(acl);
+        deviceAuthService.acl(acl);
+        log.info("topic:{}, acl success", acl.getTopic());
     }
 
     @PostMapping("/mqtt/superuser")
     public void superuser(@RequestBody EmqAcl acl, HttpServletResponse response) {
         response.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
-//        log.info("mqtt superuser:" + JsonUtil.toJsonString(acl));
-//        if (!isSupperUser(acl.getClientid())) {
-//            throw new RuntimeException("superuser check false.");
-//        }
     }
 
     public boolean isSupperUser(String clientId) {
@@ -72,13 +60,4 @@ public class MqttAuthController {
         }
     }
 
-    private MqttAuth getMqttAuth(String clientId) {
-        if (clientId.startsWith("wx_")) {
-            return wxMqttAuth;
-        } else if (clientId.startsWith("sy_")) {
-            return sysMqttAuth;
-        }
-        return deviceMqttAuth;
-    }
-
 }

+ 41 - 0
device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/handler/DisconnectedHandler.java

@@ -0,0 +1,41 @@
+package cc.iotkit.server.mqtt.handler;
+
+import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.protocol.client.DeviceBehaviourClient;
+import com.fasterxml.jackson.core.type.TypeReference;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class DisconnectedHandler {
+
+    @Autowired
+    private DeviceBehaviourClient behaviourClient;
+
+    public void handler(String msg) {
+        Disconnected disconnected = JsonUtil.parse(msg, new TypeReference<Disconnected>() {
+        });
+        String clientId = disconnected.getClientid();
+        String[] parts = clientId.split("_");
+        if (parts.length < 2) {
+            return;
+        }
+        String pk = parts[0];
+        String dn = parts[1];
+        behaviourClient.offline(pk, dn);
+        log.info("client disconnected, offline,pk:{},dn:{}", pk, dn);
+    }
+
+    @Data
+    private static class Disconnected {
+        private String reason;
+        private String clientid;
+        private String username;
+        private String peername;
+        private String sockname;
+    }
+
+}

+ 1 - 1
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/model/EmqAcl.java → device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAcl.java

@@ -1,4 +1,4 @@
-package cc.iotkit.mqttauth.model;
+package cc.iotkit.server.mqtt.model;
 
 import lombok.Data;
 

+ 1 - 1
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/model/EmqAuthInfo.java → device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAuthInfo.java

@@ -1,4 +1,4 @@
-package cc.iotkit.mqttauth.model;
+package cc.iotkit.server.mqtt.model;
 
 import lombok.Data;
 

+ 17 - 0
device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Request.java

@@ -0,0 +1,17 @@
+package cc.iotkit.server.mqtt.model;
+
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Request<T> {
+    protected String id;
+
+    protected T params;
+}

+ 25 - 0
device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Response.java

@@ -0,0 +1,25 @@
+package cc.iotkit.server.mqtt.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Response<T> {
+
+    private String id;
+
+    private int code;
+
+    private T data;
+
+    public static Empty empty() {
+        return new Empty();
+    }
+
+    @Data
+    public static class Empty {
+    }
+}

+ 18 - 22
device-server/mqtt-auth/src/main/java/cc/iotkit/mqttauth/service/DeviceMqttAuth.java → device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/DeviceAuthService.java

@@ -1,9 +1,12 @@
-package cc.iotkit.mqttauth.service;
+package cc.iotkit.server.mqtt.service;
 
 import cc.iotkit.common.Constants;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.mqttauth.model.EmqAcl;
-import cc.iotkit.mqttauth.model.EmqAuthInfo;
+import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.protocol.RegisterInfo;
+import cc.iotkit.protocol.Result;
+import cc.iotkit.protocol.client.DeviceBehaviourClient;
+import cc.iotkit.server.mqtt.model.EmqAcl;
+import cc.iotkit.server.mqtt.model.EmqAuthInfo;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -11,14 +14,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 @Slf4j
-@Component("DeviceMqttAuth")
-public class DeviceMqttAuth implements MqttAuth {
+@Component
+public class DeviceAuthService {
+
     @Autowired
-    private DeviceService deviceService;
+    private DeviceBehaviourClient behaviourClient;
 
-    @Override
     public void auth(EmqAuthInfo auth) {
-
         String clientId = auth.getClientid();
         String[] pkDnAndModel = getPkDnAndModel(clientId);
 
@@ -27,25 +29,19 @@ public class DeviceMqttAuth implements MqttAuth {
             throw new RuntimeException("password is illegal.");
         }
 
-        DeviceInfo device = new DeviceInfo();
-        device.setProductKey(pkDnAndModel[0]);
-        device.setDeviceName(pkDnAndModel[1]);
-        device.setModel(pkDnAndModel[2]);
-        deviceService.register(device);
+        String pk = pkDnAndModel[0];
+        String dn = pkDnAndModel[1];
+        String model = pkDnAndModel[2];
+
+        Result result = behaviourClient.register(new RegisterInfo(pk, dn, model));
+        log.info("register result:{}", JsonUtil.toJsonString(result));
     }
 
-    @Override
     public void acl(EmqAcl acl) {
         String[] pkDn = getPkDnFromTopic(acl.getTopic());
         String pk = pkDn[2];
         String dn = pkDn[3];
-        DeviceInfo device = deviceService.getByPkAndDn(pk, dn);
-        if (device == null) {
-            log.error("the device is not registered,pk:{},dn:{}", pk, dn);
-            return;
-        }
-
-        deviceService.online(pk, dn);
+        behaviourClient.online(pk, dn);
     }
 
     private String[] getPkDnAndModel(String clientId) {

+ 256 - 0
device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/MqttManager.java

@@ -0,0 +1,256 @@
+package cc.iotkit.server.mqtt.service;
+
+import cc.iotkit.common.Constants;
+import cc.iotkit.common.utils.CodecUtil;
+import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.protocol.DeviceMessage;
+import cc.iotkit.protocol.RegisterInfo;
+import cc.iotkit.protocol.client.DeviceBehaviourClient;
+import cc.iotkit.server.mqtt.handler.DisconnectedHandler;
+import cc.iotkit.server.mqtt.model.Request;
+import cc.iotkit.server.mqtt.model.Response;
+import com.fasterxml.jackson.core.type.TypeReference;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.paho.client.mqttv3.*;
+import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Component
+public class MqttManager implements MqttCallback, IMqttMessageListener {
+
+    @Value("${mqtt.url}")
+    private String url;
+
+    @Value(("${spring.profiles.active:}"))
+    private String env;
+
+    private MqttClient mqttClient;
+
+    @Autowired
+    private DisconnectedHandler disconnectedHandler;
+    @Autowired
+    private DeviceBehaviourClient behaviourClient;
+
+    public MqttManager() {
+        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
+        executorService.scheduleWithFixedDelay(this::createClient, 1, 3, TimeUnit.SECONDS);
+    }
+
+    private MqttConnectOptions getMqttConnectOptions() {
+        MqttConnectOptions options = new MqttConnectOptions();
+        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,
+        // 这里设置为true表示每次连接到服务器都以新的身份连接
+        options.setCleanSession(true);
+        // 设置连接的用户名
+        options.setUserName("admin");
+        // 设置连接的密码
+        options.setPassword("password".toCharArray());
+        options.setServerURIs(StringUtils.split(url, ","));
+        // 设置超时时间 单位为秒
+        options.setConnectionTimeout(10);
+        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线,但这个方法并没有重连的机制
+        options.setKeepAliveInterval(20);
+        return options;
+    }
+
+    @SneakyThrows
+    private void createClient() {
+        try {
+            if (mqttClient == null) {
+                MemoryPersistence persistence = new MemoryPersistence();
+                String clientId = "mqtt-server-consumer-" + env;
+                clientId = "su_" + CodecUtil.aesEncrypt("admin_" + clientId, Constants.MQTT_SECRET);
+                mqttClient = new MqttClient(url, clientId, persistence);
+                mqttClient.setCallback(this);
+            }
+            if (mqttClient.isConnected()) {
+                return;
+            }
+            connect();
+        } catch (Throwable e) {
+            log.error("create mqttClient error", e);
+        }
+    }
+
+    private void connect() {
+        try {
+            log.info("Connecting to broker:{} ", url);
+            IMqttToken mqttToken = mqttClient.connectWithResult(getMqttConnectOptions());
+            if (mqttToken.isComplete()) {
+                log.info("connect mqtt-broker success");
+            } else {
+                log.error("connect mqtt-broker failed", mqttToken.getException());
+            }
+            IMqttToken response = mqttClient.subscribeWithResponse(
+                    new String[]{"/sys/+/+/s/#", "/sys/session/topic/unsubscribed", "/sys/client/disconnected"});
+            if (response.isComplete()) {
+                log.info("subscribe topics success");
+            } else {
+                log.error("subscribe topics failed", mqttToken.getException());
+            }
+        } catch (Throwable e) {
+            log.error("connect to mqtt-broker error", e);
+        }
+    }
+
+    @SneakyThrows
+    @Override
+    public void connectionLost(Throwable e) {
+        log.error("mqtt connection lost", e);
+        while (true) {
+            try {
+                Thread.sleep(1000);
+                if (mqttClient.isConnected()) {
+                    mqttClient.disconnect();
+                }
+                connect();
+                break;
+            } catch (Throwable e1) {
+                log.error("connect error,retry...", e1);
+            }
+        }
+    }
+
+    @Override
+    public void messageArrived(String topic, MqttMessage mqttMessage) {
+        handleMessage(topic, mqttMessage);
+    }
+
+    @Override
+    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
+    }
+
+    public void handleMessage(String topic, MqttMessage msg) {
+        log.info("receive msg,topic:{},msg:{}", topic, JsonUtil.toJsonString(msg));
+        if (topic == null) {
+            log.error("message topic is null.");
+            return;
+        }
+        int code = 0;
+        String mid = "";
+
+        try {
+            String payload = new String(msg.getPayload());
+
+            //取消订阅
+            if (topic.equals("/sys/session/topic/unsubscribed")) {
+                topicUnsubscribed(payload);
+                return;
+            }
+
+            //连接断开
+            if (topic.equals("/sys/client/disconnected")) {
+                disconnectedHandler.handler(payload);
+                return;
+            }
+
+            String[] parts = topic.split("/");
+            if (parts.length < 5) {
+                log.error("message topic is illegal.");
+                return;
+            }
+            String productKey = parts[2];
+            String deviceName = parts[3];
+
+            //子设备注册
+            if (topic.endsWith("/register")) {
+                RegisterRequest registerRequest = JsonUtil.parse(payload, RegisterRequest.class);
+                mid = registerRequest.getId();
+
+                RegisterInfo registerInfo = RegisterInfo.builder()
+                        .productKey(productKey)
+                        .deviceName(deviceName)
+                        .subDevices(Collections.singletonList(registerRequest.getParams()))
+                        .build();
+                behaviourClient.register(registerInfo);
+                return;
+            }
+
+            Request<?> request = JsonUtil.parse(payload, Request.class);
+            mid = request.getId();
+            MqtMsg mqtMsg = new MqtMsg(topic, request);
+
+            behaviourClient.messageReport(DeviceMessage.builder()
+                    .productKey(productKey)
+                    .deviceName(deviceName)
+                    .mid(request.getId())
+                    .content(JsonUtil.toJsonString(mqtMsg))
+                    .build());
+
+        } catch (Throwable e) {
+            log.error("message process error", e);
+            code = 500;
+        } finally {
+            reply(topic, mid, code);
+        }
+
+    }
+
+    @SneakyThrows
+    private void reply(String topic, String id, int code) {
+        //回复消息不需要再回复
+        if (topic.endsWith("_reply")) {
+            return;
+        }
+
+        topic = topic.replace("/s/", "/c/") + "_reply";
+        String msg = JsonUtil.toJsonString(new Response<>(id, code, new HashMap<>()));
+        mqttClient.publish(topic, new MqttMessage(msg.getBytes()));
+    }
+
+    private void topicUnsubscribed(String msg) {
+        Unsubscribed unsubscribed = JsonUtil.parse(msg, new TypeReference<Unsubscribed>() {
+        });
+        String topic = unsubscribed.getTopic();
+        String[] parts = topic.split("/");
+        if (parts.length < 4) {
+            return;
+        }
+
+        log.info("device offline,pk:{},dn:{}", parts[2], parts[3]);
+        behaviourClient.offline(parts[2], parts[3]);
+    }
+
+    @SneakyThrows
+    public void sendMsg(String topic, String msg) {
+        mqttClient.publish(topic, new MqttMessage(msg.getBytes()));
+    }
+
+    @Data
+    private static class Unsubscribed {
+        private String clientid;
+        private String username;
+        private String topic;
+        private String peerhost;
+    }
+
+    public static class RegisterRequest extends Request<RegisterInfo.SubDevice> {
+
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    private static class MqtMsg {
+
+        private String topic;
+
+        private Object payload;
+
+    }
+
+}

+ 0 - 219
device-server/mqtt-server/src/main/java/cc/iotkit/server/service/DeviceService.java

@@ -1,219 +0,0 @@
-package cc.iotkit.server.service;
-
-import cc.iotkit.common.exception.BizException;
-import cc.iotkit.common.exception.NotFoundException;
-import cc.iotkit.common.exception.OfflineException;
-import cc.iotkit.common.utils.DeviceUtil;
-import cc.iotkit.common.utils.JsonUtil;
-import cc.iotkit.common.utils.UniqueIdUtil;
-import cc.iotkit.deviceapi.IDeviceManager;
-import cc.iotkit.deviceapi.IDeviceService;
-import cc.iotkit.deviceapi.Service;
-import cc.iotkit.model.device.message.DeviceEvent;
-import cc.iotkit.model.device.DeviceInfo;
-import cc.iotkit.model.product.ThingModel;
-import cc.iotkit.model.mq.Request;
-import cc.iotkit.server.dao.DeviceDao;
-import cc.iotkit.server.dao.DeviceEventRepository;
-import cc.iotkit.server.dao.DeviceRepository;
-import cc.iotkit.server.dao.ThingModelRepository;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.RandomUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Slf4j
-@RestController
-public class DeviceService implements IDeviceManager, IDeviceService {
-
-    @Autowired
-    private DeviceDao deviceDao;
-    @Autowired
-    private DeviceRepository deviceRepository;
-    @Autowired
-    private ThingModelRepository thingModelRepository;
-    @Autowired
-    private ThingModelService thingModelService;
-    @Autowired
-    private DeviceEventRepository deviceEventRepository;
-
-    @Autowired
-    private IMqttSender mqttSender;
-
-    private static final String identifier_set = "property/set";
-
-    @Override
-    public DeviceInfo register(String parentId, String productKey, String deviceName, String model) {
-        DeviceInfo device = new DeviceInfo();
-        device.setParentId(parentId);
-        device.setProductKey(productKey);
-        device.setDeviceName(deviceName);
-        device.setModel(model);
-
-        DeviceInfo parentDevice = deviceDao.getByDeviceId(parentId);
-        if (parentDevice == null) {
-            throw new BizException("Parent device does not exist");
-        }
-        String uid = parentDevice.getUid();
-
-        DeviceInfo deviceInfo = deviceDao.getByPkAndDn(productKey, deviceName);
-        if (deviceInfo != null) {
-            device.setId(deviceInfo.getId());
-            device.setDeviceId(deviceInfo.getDeviceId());
-            device.setUid(uid);
-            deviceDao.updateDevice(device);
-            log.info("device register update:{}", JsonUtil.toJsonString(device));
-            return deviceInfo;
-        }
-
-        String deviceId = newDeviceId(deviceName);
-
-        device.setId(deviceId);
-        device.setDeviceId(deviceId);
-        device.setUid(uid);
-        deviceDao.addDevice(device);
-        log.info("device registered:{}", JsonUtil.toJsonString(device));
-        return device;
-    }
-
-    @Override
-    public void unbind(String deviceId) {
-        log.info("start unbind device,deviceId:{}", deviceId);
-
-        DeviceInfo device = deviceRepository.findById(deviceId)
-                .orElseThrow(() -> new RuntimeException("no device found by deviceId:" + deviceId));
-
-        String gatewayId = device.getParentId();
-        DeviceInfo gateway = deviceRepository.findById(gatewayId)
-                .orElseThrow(() -> new RuntimeException("no device found by deviceId:" + deviceId));
-
-        //数据库解绑
-        device.setParentId("");
-        deviceRepository.save(device);
-
-        //网关注销
-        String topic = "/sys/" + gateway.getProductKey() + "/" + gateway.getDeviceName() + "/c/service/deregister";
-        String requestId = UniqueIdUtil.newRequestId();
-        Map<String, Object> params = new HashMap<>();
-        params.put("productKey", device.getProductKey());
-        params.put("deviceName", device.getDeviceName());
-        CmdRequest request = new CmdRequest(requestId, params);
-        String msg = JsonUtil.toJsonString(request);
-        log.info("start send mqtt msg,topic:{},payload:{}", topic, msg);
-        mqttSender.sendToMqtt(topic, msg);
-    }
-
-    @Override
-    public String invoke(Service service) {
-        return sendMsg(service);
-    }
-
-    @Override
-    public String setProperty(String deviceId, @RequestBody Map<String, Object> properties) {
-        return sendMsg(deviceId, identifier_set, properties);
-    }
-
-    @Override
-    public String invokeService(String deviceId, String identifier, Map<String, Object> properties) {
-        return sendMsg(deviceId, identifier, properties);
-    }
-
-    public void offline(String pk, String dn) {
-        DeviceInfo device = new DeviceInfo();
-        device.setProductKey(pk);
-        device.setDeviceName(dn);
-
-        device.getState().setOnline(false);
-        device.getState().setOfflineTime(System.currentTimeMillis());
-        deviceDao.updateDeviceByPkAndDn(device);
-        log.info("device offline,pk:{},dn:{}", pk, dn);
-    }
-
-    public String sendMsg(String deviceId, String service, Map<String, Object> args) {
-        DeviceInfo device = deviceRepository.findById(deviceId)
-                .orElseThrow(() -> new NotFoundException("device not found by deviceId"));
-
-        return this.sendMsg(device, service, args);
-    }
-
-    public String sendMsg(DeviceInfo device, String service, Map<String, Object> args) {
-        if (device.getState() == null || device.getState().getOnline() != Boolean.TRUE) {
-            throw new OfflineException("device is offline");
-        }
-
-        String pk = device.getProductKey();
-        String dn = device.getDeviceName();
-
-        ThingModel thingModel = thingModelRepository.findById(pk)
-                .orElseThrow(() -> new NotFoundException("device thingModel not found"));
-
-        String topic = "/sys/" + pk + "/" + dn + "/c/service/" + service;
-        String requestId = UniqueIdUtil.newRequestId();
-
-        //参数类型转换
-        args = thingModelService.paramsParse(thingModel, service, args);
-
-        CmdRequest request = new CmdRequest(requestId, args);
-        String msg = JsonUtil.toJsonString(request);
-        log.info("start send mqtt msg,topic:{},payload:{}", topic, msg);
-        mqttSender.sendToMqtt(topic, msg);
-
-        //记录下行日志
-        DeviceEvent deviceEvent = DeviceEvent.builder()
-                .deviceId(device.getDeviceId())
-                .identifier(service.replace("property/set", "propertySet"))
-                .type("service")
-                .request(new Request<>(requestId, args))
-                .createAt(System.currentTimeMillis())
-                .build();
-        deviceEventRepository.save(deviceEvent);
-
-        return requestId;
-    }
-
-    public String sendMsg(Service service) {
-        DeviceUtil.PkDn pkDn = DeviceUtil.getPkDn(service.getDevice());
-        DeviceInfo deviceInfo = deviceDao.getByPkAndDn(pkDn.getProductKey(), pkDn.getDeviceName());
-        if ("set".equals(service.getIdentifier())) {
-            return sendMsg(deviceInfo.getDeviceId(), identifier_set, service.parseInputData());
-        } else {
-            return sendMsg(deviceInfo.getDeviceId(), service.getIdentifier(), service.parseInputData());
-        }
-    }
-
-    /**
-     * 1-13位	时间戳
-     * 14-29位	deviceNae,去除非字母和数字,不足16位补0,超过16位的mac取后16位,共16位
-     * 30-31位	mac长度,共2位
-     * 32位	随机一个0-f字符
-     */
-    private static String newDeviceId(String deviceNae) {
-        int maxDnLen = 16;
-        String dn = deviceNae.replaceAll("[^0-9A-Za-z]", "");
-        if (dn.length() > maxDnLen) {
-            dn = dn.substring(dn.length() - maxDnLen);
-        } else {
-            dn = (dn + "00000000000000000000").substring(0, maxDnLen);
-        }
-        String len = StringUtils.leftPad(deviceNae.length() + "", 2, '0');
-        String rnd = Integer.toHexString(RandomUtils.nextInt(0, 16));
-        return (System.currentTimeMillis() + "0" + dn + len + rnd).toLowerCase();
-    }
-
-
-    @Data
-    @NoArgsConstructor
-    @AllArgsConstructor
-    private static class CmdRequest {
-        private String id;
-        private Object params;
-    }
-}

+ 0 - 40
device-server/mqtt-server/src/main/java/cc/iotkit/server/service/IMqttSender.java

@@ -1,40 +0,0 @@
-package cc.iotkit.server.service;
-import cc.iotkit.server.config.MqttConfig;
-import org.springframework.integration.annotation.MessagingGateway;
-import org.springframework.integration.mqtt.support.MqttHeaders;
-import org.springframework.messaging.handler.annotation.Header;
-import org.springframework.stereotype.Component;
-
-@Component
-@MessagingGateway(defaultRequestChannel = MqttConfig.CHANNEL_NAME_OUT)
-public interface IMqttSender {
-
-    /**
-     * 发送信息到MQTT服务器
-     *
-     * @param data 发送的文本
-     */
-    void sendToMqtt(String data);
-
-    /**
-     * 发送信息到MQTT服务器
-     *
-     * @param topic 主题
-     * @param payload 消息主体
-     */
-    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic,
-                    String payload);
-
-    /**
-     * 发送信息到MQTT服务器
-     *
-     * @param topic 主题
-     * @param qos 对消息处理的几种机制。<br> 0 表示的是订阅者没收到消息不会再次发送,消息会丢失。<br>
-     * 1 表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息。<br>
-     * 2 多了一次去重的动作,确保订阅者收到的消息有一次。
-     * @param payload 消息主体
-     */
-    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic,
-                    @Header(MqttHeaders.QOS) int qos,
-                    String payload);
-}

+ 0 - 60
device-server/mqtt-server/src/main/java/cc/iotkit/server/service/ThingModelService.java

@@ -1,60 +0,0 @@
-package cc.iotkit.server.service;
-
-import cc.iotkit.model.product.ThingModel;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Component
-public class ThingModelService {
-
-    public Map<String, Object> paramsParse(ThingModel thingModel, String identifier, Map<?, ?> params) {
-        Map<String, Object> parsedParams = new HashMap<>();
-        ThingModel.Model model = thingModel.getModel();
-
-        //属性设置
-        if ("property/set".equals(identifier)) {
-            List<ThingModel.Property> properties = model.getProperties();
-            if (properties == null) {
-                return parsedParams;
-            }
-            return parseProperties(properties, params);
-        } else {
-            //服务调用
-            Map<String, ThingModel.Service> services = model.serviceMap();
-            ThingModel.Service service = services.get(identifier);
-            if (service == null) {
-                return parsedParams;
-            }
-            List<ThingModel.Parameter> parameters = service.getInputData();
-            return parseParams(parameters, params);
-        }
-    }
-
-    private Map<String, Object> parseParams(List<ThingModel.Parameter> parameters, Map<?, ?> params) {
-        Map<String, Object> parsed = new HashMap<>();
-        parameters.forEach((p -> parseField(p.getIdentifier(), p.getDataType(), params, parsed)));
-        return parsed;
-    }
-
-    private Map<String, Object> parseProperties(List<ThingModel.Property> properties, Map<?, ?> params) {
-        Map<String, Object> parsed = new HashMap<>();
-        properties.forEach((p -> parseField(p.getIdentifier(), p.getDataType(), params, parsed)));
-        return parsed;
-    }
-
-    private void parseField(String identifier, ThingModel.DataType dataType, Map<?, ?> params, Map<String, Object> parsed) {
-        Object val = params.get(identifier);
-        if (val == null) {
-            return;
-        }
-        Object result = dataType.parse(val);
-        if (result == null) {
-            return;
-        }
-        parsed.put(identifier, result);
-    }
-
-}

+ 0 - 1
device-server/pom.xml

@@ -12,7 +12,6 @@
     <artifactId>device-server</artifactId>
     <packaging>pom</packaging>
     <modules>
-        <module>mqtt-auth</module>
         <module>mqtt-server</module>
         <module>device-api</module>
         <module>mqtt-client-simulator</module>

BIN
log/error.2022-03-14.0.gz


BIN
log/error.2022-03-15.0.gz


BIN
log/error.2022-03-16.0.gz


+ 900 - 0
log/error.2022-03-16.01767963764004696.tmp

@@ -0,0 +1,900 @@
+2022-03-17 00:22:10.444 ERROR 35086 --- [nio-8086-exec-3] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.lang.IllegalArgumentException: The URI scheme, of the URI pulsar://192.168.0.112:6650/admin/v3/functions/public/iot/.UplinkTranslateFunction_mqtt-gateway, must be equal (ignoring case) to 'http', 'https', 'ws', or 'wss'
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.lambda$null$6(ClientRuntime.java:184)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.lambda$createRunnableForAsyncProcessing$7(ClientRuntime.java:156)
+	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
+	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
+	at java.util.concurrent.FutureTask.run(FutureTask.java)
+	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+	... 1 common frames omitted
+Caused by: java.lang.IllegalArgumentException: The URI scheme, of the URI pulsar://192.168.0.112:6650/admin/v3/functions/public/iot/.UplinkTranslateFunction_mqtt-gateway, must be equal (ignoring case) to 'http', 'https', 'ws', or 'wss'
+	at org.apache.pulsar.shade.org.asynchttpclient.uri.Uri.validateSupportedScheme(Uri.java:289)
+	at org.apache.pulsar.shade.org.asynchttpclient.RequestBuilderBase.computeUri(RequestBuilderBase.java:605)
+	at org.apache.pulsar.shade.org.asynchttpclient.RequestBuilderBase.build(RequestBuilderBase.java:614)
+	at org.apache.pulsar.shade.org.asynchttpclient.BoundRequestBuilder.execute(BoundRequestBuilder.java:39)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.oneShot(AsyncHttpConnector.java:316)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOrTimeOut$2(AsyncHttpConnector.java:236)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.retryOperation(AsyncHttpConnector.java:248)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.retryOrTimeOut(AsyncHttpConnector.java:236)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.apply(AsyncHttpConnector.java:201)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.lambda$null$6(ClientRuntime.java:182)
+	... 13 common frames omitted
+
+2022-03-17 00:24:19.269 ERROR 35449 --- [nio-8086-exec-1] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:29:56.110 ERROR 35449 --- [nio-8086-exec-5] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:31:07.512 ERROR 35449 --- [nio-8086-exec-6] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:33:47.330 ERROR 35449 --- [nio-8086-exec-7] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+

BIN
log/error.2022-03-17.0.gz


BIN
log/error.2022-03-18.0.gz


BIN
log/info.2022-03-14.0.gz


BIN
log/info.2022-03-15.0.gz


BIN
log/info.2022-03-16.0.gz


+ 1019 - 0
log/info.2022-03-16.01767904371465962.tmp

@@ -0,0 +1,1019 @@
+2022-03-17 00:22:07.709  INFO 35086 --- [nio-8086-exec-3] o.keycloak.adapters.KeycloakDeployment   : Loaded URLs from https://auth.iotkit.cc/realms/iotkit/.well-known/openid-configuration
+2022-03-17 00:22:08.815  INFO 35086 --- [nio-8086-exec-3] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:5, serverValue:5942935}] to dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717
+2022-03-17 00:22:10.444 ERROR 35086 --- [nio-8086-exec-3] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.lang.IllegalArgumentException: The URI scheme, of the URI pulsar://192.168.0.112:6650/admin/v3/functions/public/iot/.UplinkTranslateFunction_mqtt-gateway, must be equal (ignoring case) to 'http', 'https', 'ws', or 'wss'
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.lambda$null$6(ClientRuntime.java:184)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.lambda$createRunnableForAsyncProcessing$7(ClientRuntime.java:156)
+	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
+	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
+	at java.util.concurrent.FutureTask.run(FutureTask.java)
+	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+	... 1 common frames omitted
+Caused by: java.lang.IllegalArgumentException: The URI scheme, of the URI pulsar://192.168.0.112:6650/admin/v3/functions/public/iot/.UplinkTranslateFunction_mqtt-gateway, must be equal (ignoring case) to 'http', 'https', 'ws', or 'wss'
+	at org.apache.pulsar.shade.org.asynchttpclient.uri.Uri.validateSupportedScheme(Uri.java:289)
+	at org.apache.pulsar.shade.org.asynchttpclient.RequestBuilderBase.computeUri(RequestBuilderBase.java:605)
+	at org.apache.pulsar.shade.org.asynchttpclient.RequestBuilderBase.build(RequestBuilderBase.java:614)
+	at org.apache.pulsar.shade.org.asynchttpclient.BoundRequestBuilder.execute(BoundRequestBuilder.java:39)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.oneShot(AsyncHttpConnector.java:316)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOrTimeOut$2(AsyncHttpConnector.java:236)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.retryOperation(AsyncHttpConnector.java:248)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.retryOrTimeOut(AsyncHttpConnector.java:236)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.apply(AsyncHttpConnector.java:201)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.lambda$null$6(ClientRuntime.java:182)
+	... 13 common frames omitted
+
+2022-03-17 00:23:44.681  INFO 35086 --- [ionShutdownHook] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED paused.
+2022-03-17 00:23:49.731  INFO 35086 --- [ionShutdownHook] .m.i.MqttPahoMessageDrivenChannelAdapter : stopped bean 'inbound'; defined in: 'class path resource [cc/iotkit/ruleengine/config/RuleConfiguration.class]'; from source: 'cc.iotkit.ruleengine.config.RuleConfiguration.inbound()'
+2022-03-17 00:23:49.732  INFO 35086 --- [ionShutdownHook] o.s.i.endpoint.EventDrivenConsumer       : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
+2022-03-17 00:23:49.732  INFO 35086 --- [ionShutdownHook] o.s.i.channel.PublishSubscribeChannel    : Channel 'application.errorChannel' has 0 subscriber(s).
+2022-03-17 00:23:49.732  INFO 35086 --- [ionShutdownHook] o.s.i.endpoint.EventDrivenConsumer       : stopped bean '_org.springframework.integration.errorLogger'
+2022-03-17 00:23:49.733  INFO 35086 --- [ionShutdownHook] o.s.i.endpoint.EventDrivenConsumer       : Removing {message-handler:ruleConfiguration.handler.serviceActivator} as a subscriber to the 'mqttInboundChannel' channel
+2022-03-17 00:23:49.733  INFO 35086 --- [ionShutdownHook] o.s.integration.channel.DirectChannel    : Channel 'application.mqttInboundChannel' has 0 subscriber(s).
+2022-03-17 00:23:49.733  INFO 35086 --- [ionShutdownHook] o.s.i.endpoint.EventDrivenConsumer       : stopped bean 'ruleConfiguration.handler.serviceActivator'
+2022-03-17 00:23:49.741  INFO 35086 --- [ionShutdownHook] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED shutting down.
+2022-03-17 00:23:49.741  INFO 35086 --- [ionShutdownHook] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED paused.
+2022-03-17 00:23:49.742  INFO 35086 --- [ionShutdownHook] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED shutdown complete.
+2022-03-17 00:23:49.743  INFO 35086 --- [ionShutdownHook] o.s.s.quartz.SchedulerFactoryBean        : Shutting down Quartz Scheduler
+2022-03-17 00:23:55.525  INFO 35449 --- [           main] cc.iotkit.manager.Application            : Starting Application using Java 1.8.0_261 on songjiangangdeMacBook-Pro.local with PID 35449 (/Users/sjg/home/gitee/open-source/iotkit-parent/manager/target/classes started by sjg in /Users/sjg/home/gitee/open-source/iotkit-parent)
+2022-03-17 00:23:55.529 DEBUG 35449 --- [           main] cc.iotkit.manager.Application            : Running with Spring Boot v2.6.2, Spring v5.3.14
+2022-03-17 00:23:55.529  INFO 35449 --- [           main] cc.iotkit.manager.Application            : The following profiles are active: dev
+2022-03-17 00:23:56.897  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
+2022-03-17 00:23:56.898  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
+2022-03-17 00:23:57.180  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 275 ms. Found 1 Elasticsearch repository interfaces.
+2022-03-17 00:23:57.296  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
+2022-03-17 00:23:57.296  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data MongoDB repositories in DEFAULT mode.
+2022-03-17 00:23:57.422  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 125 ms. Found 20 MongoDB repository interfaces.
+2022-03-17 00:23:57.690  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
+2022-03-17 00:23:57.692  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
+2022-03-17 00:23:57.701  INFO 35449 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 Reactive Elasticsearch repository interfaces.
+2022-03-17 00:23:58.019  INFO 35449 --- [           main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
+2022-03-17 00:23:58.048  INFO 35449 --- [           main] faultConfiguringBeanFactoryPostProcessor : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
+2022-03-17 00:23:58.264  INFO 35449 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=cfb87af3-c30c-3a03-8b33-421165292980
+2022-03-17 00:23:58.602  INFO 35449 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.integration.config.IntegrationManagementConfiguration' of type [org.springframework.integration.config.IntegrationManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
+2022-03-17 00:23:58.626  INFO 35449 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationChannelResolver' of type [org.springframework.integration.support.channel.BeanFactoryChannelResolver] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
+2022-03-17 00:23:59.221  INFO 35449 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8086 (http)
+2022-03-17 00:23:59.237  INFO 35449 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
+2022-03-17 00:23:59.238  INFO 35449 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
+2022-03-17 00:23:59.370  INFO 35449 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
+2022-03-17 00:23:59.370  INFO 35449 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3717 ms
+2022-03-17 00:23:59.800  INFO 35449 --- [           main] org.mongodb.driver.cluster               : Cluster created with settings {hosts=[dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms'}
+2022-03-17 00:23:59.984  WARN 35449 --- [           main] o.s.data.convert.CustomConversions       : Registering converter from class java.time.LocalDateTime to class org.joda.time.LocalDateTime as reading converter although it doesn't convert from a store-supported type! You might want to check your annotation setup at the converter implementation.
+2022-03-17 00:24:00.039  INFO 35449 --- [iyuncs.com:3717] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:2, serverValue:5943240}] to dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717
+2022-03-17 00:24:00.039  INFO 35449 --- [iyuncs.com:3717] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:1, serverValue:5943239}] to dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717
+2022-03-17 00:24:00.039  INFO 35449 --- [iyuncs.com:3717] org.mongodb.driver.cluster               : Monitor thread successfully connected to server with description ServerDescription{address=dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717, type=SHARD_ROUTER, state=CONNECTED, ok=true, minWireVersion=0, maxWireVersion=8, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=72114855}
+2022-03-17 00:24:00.128  WARN 35449 --- [           main] o.s.data.convert.CustomConversions       : Registering converter from class java.time.LocalDateTime to class org.joda.time.LocalDateTime as reading converter although it doesn't convert from a store-supported type! You might want to check your annotation setup at the converter implementation.
+2022-03-17 00:24:02.145  WARN 35449 --- [           main] .m.SimpleElasticsearchPersistentProperty : Unsupported type 'class java.lang.Long' for date property 'occur'.
+2022-03-17 00:24:02.148  WARN 35449 --- [           main] .m.SimpleElasticsearchPersistentProperty : Unsupported type 'class java.lang.Long' for date property 'time'.
+2022-03-17 00:24:02.310  INFO 35449 --- [pool-3-thread-1] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:3, serverValue:5943246}] to dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717
+2022-03-17 00:24:02.471  WARN 35449 --- [           main] org.elasticsearch.client.RestClient      : request [HEAD http://192.168.0.112:9200/thing_model_messages?ignore_throttled=false&ignore_unavailable=false&expand_wildcards=open%2Cclosed&allow_no_indices=false] returned 1 warnings: [299 Elasticsearch-8.1.0-3700f7679f7d95e36da0b43762189bab189bc53a "[ignore_throttled] parameter is deprecated because frozen indices have been deprecated. Consider cold or frozen tiers in place of frozen indices."]
+2022-03-17 00:24:02.871  WARN 35449 --- [           main] .i.n.r.d.DnsServerAddressStreamProviders : Can not find org.apache.pulsar.shade.io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider in the classpath, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS.
+2022-03-17 00:24:03.770  INFO 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : [[id: 0xae4892c5, L:/192.168.0.109:54411 - R:/192.168.0.112:6650]] Connected to server
+2022-03-17 00:24:04.593  INFO 35449 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@503b5337, org.springframework.security.web.context.SecurityContextPersistenceFilter@65e4eba5, org.springframework.security.web.header.HeaderWriterFilter@56511eda, org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter@6abe62bb, org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter@11c3d22f, org.springframework.security.web.authentication.logout.LogoutFilter@14c1cba6, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@be56353, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1ae69abe, org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter@29c25bbc, org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter@30704f85, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@265361a, org.springframework.security.web.session.SessionManagementFilter@760f4310, org.springframework.security.web.access.ExceptionTranslationFilter@70c6c6a7, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@5fc3dfc1]
+2022-03-17 00:24:04.660  INFO 35449 --- [           main] org.quartz.impl.StdSchedulerFactory      : Using default implementation for ThreadExecutor
+2022-03-17 00:24:04.682  INFO 35449 --- [           main] org.quartz.core.SchedulerSignalerImpl    : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
+2022-03-17 00:24:04.682  INFO 35449 --- [           main] org.quartz.core.QuartzScheduler          : Quartz Scheduler v.2.3.2 created.
+2022-03-17 00:24:04.684  INFO 35449 --- [           main] org.quartz.simpl.RAMJobStore             : RAMJobStore initialized.
+2022-03-17 00:24:04.685  INFO 35449 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.3.2) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED'
+  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
+  NOT STARTED.
+  Currently in standby mode.
+  Number of jobs executed: 0
+  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
+  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
+
+2022-03-17 00:24:04.685  INFO 35449 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
+2022-03-17 00:24:04.685  INFO 35449 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.3.2
+2022-03-17 00:24:04.685  INFO 35449 --- [           main] org.quartz.core.QuartzScheduler          : JobFactory set to: cc.iotkit.ruleengine.config.JobFactory@331fe6d4
+2022-03-17 00:24:05.310  INFO 35449 --- [pool-4-thread-1] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:4, serverValue:5943253}] to dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717
+2022-03-17 00:24:05.556  INFO 35449 --- [pool-4-thread-1] cc.iotkit.ruleengine.scene.SceneManager  : got scene 460f0805-503f-428a-936c-c5e7278024d5 to init
+2022-03-17 00:24:05.653  INFO 35449 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
+2022-03-17 00:24:05.654  INFO 35449 --- [           main] o.s.i.channel.PublishSubscribeChannel    : Channel 'application.errorChannel' has 1 subscriber(s).
+2022-03-17 00:24:05.654  INFO 35449 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started bean '_org.springframework.integration.errorLogger'
+2022-03-17 00:24:05.654  INFO 35449 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {message-handler:ruleConfiguration.handler.serviceActivator} as a subscriber to the 'mqttInboundChannel' channel
+2022-03-17 00:24:05.654  INFO 35449 --- [           main] o.s.integration.channel.DirectChannel    : Channel 'application.mqttInboundChannel' has 1 subscriber(s).
+2022-03-17 00:24:05.654  INFO 35449 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started bean 'ruleConfiguration.handler.serviceActivator'
+2022-03-17 00:24:05.670  INFO 35449 --- [pool-4-thread-1] cc.iotkit.ruleengine.scene.SceneManager  : got scene bef61d60-f78f-4ab4-a1a8-dc4f1bab4978 to init
+2022-03-17 00:24:06.055  INFO 35449 --- [           main] .m.i.MqttPahoMessageDrivenChannelAdapter : started bean 'inbound'; defined in: 'class path resource [cc/iotkit/ruleengine/config/RuleConfiguration.class]'; from source: 'cc.iotkit.ruleengine.config.RuleConfiguration.inbound()'
+2022-03-17 00:24:06.073  INFO 35449 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8086 (http) with context path ''
+2022-03-17 00:24:06.587  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.592  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.593  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.599  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.599  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.603  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.632  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.635  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.636  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.641  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.642  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.697  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.702  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.809  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.811  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.812  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.817  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.818  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.819  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.833  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.834  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.837  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.840  WARN 35449 --- [           main] d.s.r.o.OperationImplicitParameterReader : Unable to interpret the implicit parameter configuration with dataType: String, dataTypeClass: class java.lang.Void
+2022-03-17 00:24:06.920  INFO 35449 --- [           main] o.s.s.quartz.SchedulerFactoryBean        : Starting Quartz Scheduler now
+2022-03-17 00:24:06.920  INFO 35449 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED started.
+2022-03-17 00:24:06.930  INFO 35449 --- [           main] cc.iotkit.manager.Application            : Started Application in 12.648 seconds (JVM running for 13.495)
+2022-03-17 00:24:14.552  INFO 35449 --- [nio-8086-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
+2022-03-17 00:24:14.553  INFO 35449 --- [nio-8086-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
+2022-03-17 00:24:14.558  INFO 35449 --- [nio-8086-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 5 ms
+2022-03-17 00:24:15.726  INFO 35449 --- [nio-8086-exec-1] o.keycloak.adapters.KeycloakDeployment   : Loaded URLs from https://auth.iotkit.cc/realms/iotkit/.well-known/openid-configuration
+2022-03-17 00:24:16.809  INFO 35449 --- [nio-8086-exec-1] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:5, serverValue:5943283}] to dds-wz9rfynv908bptqw-pub.mongodb.rds.aliyuncs.com:3717
+2022-03-17 00:24:19.269 ERROR 35449 --- [nio-8086-exec-1] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:29:56.110 ERROR 35449 --- [nio-8086-exec-5] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:31:07.512 ERROR 35449 --- [nio-8086-exec-6] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:32:01.292  INFO 35449 --- [r-client-io-1-1] org.apache.pulsar.client.impl.ClientCnx  : [id: 0xae4892c5, L:/192.168.0.109:54411 ! R:/192.168.0.112:6650] Disconnected
+2022-03-17 00:32:14.472  WARN 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : Failed to open connection to 192.168.0.112:6650 : org.apache.pulsar.shade.io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.0.112:6650
+2022-03-17 00:32:14.577  WARN 35449 --- [al-listener-3-1] o.a.p.c.impl.BinaryProtoLookupService    : [namespace: public/iot] Could not get connection while getTopicsUnderNamespace -- Will try again in 100 ms
+2022-03-17 00:32:24.581  WARN 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : Failed to open connection to 192.168.0.112:6650 : org.apache.pulsar.shade.io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.0.112:6650
+2022-03-17 00:32:24.785  WARN 35449 --- [al-listener-3-1] o.a.p.c.impl.BinaryProtoLookupService    : [namespace: public/iot] Could not get connection while getTopicsUnderNamespace -- Will try again in 197 ms
+2022-03-17 00:32:34.789  WARN 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : Failed to open connection to 192.168.0.112:6650 : org.apache.pulsar.shade.io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.0.112:6650
+2022-03-17 00:32:35.181  WARN 35449 --- [al-listener-3-1] o.a.p.c.impl.BinaryProtoLookupService    : [namespace: public/iot] Could not get connection while getTopicsUnderNamespace -- Will try again in 391 ms
+2022-03-17 00:32:45.187  WARN 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : Failed to open connection to 192.168.0.112:6650 : org.apache.pulsar.shade.io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.0.112:6650
+2022-03-17 00:32:45.953  WARN 35449 --- [al-listener-3-1] o.a.p.c.impl.BinaryProtoLookupService    : [namespace: public/iot] Could not get connection while getTopicsUnderNamespace -- Will try again in 765 ms
+2022-03-17 00:32:55.955  WARN 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : Failed to open connection to 192.168.0.112:6650 : org.apache.pulsar.shade.io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.0.112:6650
+2022-03-17 00:32:57.456  WARN 35449 --- [al-listener-3-1] o.a.p.c.impl.BinaryProtoLookupService    : [namespace: public/iot] Could not get connection while getTopicsUnderNamespace -- Will try again in 1498 ms
+2022-03-17 00:32:59.602  INFO 35449 --- [r-client-io-1-1] o.a.pulsar.client.impl.ConnectionPool    : [[id: 0x745631fb, L:/192.168.0.109:58210 - R:/192.168.0.112:6650]] Connected to server
+2022-03-17 00:33:47.330 ERROR 35449 --- [nio-8086-exec-7] c.i.m.config.GlobalExceptionHandler      : handler exception
+
+cc.iotkit.common.exception.BizException: add protocol gateway error
+	at cc.iotkit.manager.controller.ProtocolController.addGateway(ProtocolController.java:38)
+	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.lang.reflect.Method.invoke(Method.java:498)
+	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
+	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
+	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
+	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
+	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
+	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
+	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
+	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
+	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
+	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
+	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:57)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:61)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
+	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
+	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
+	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:74)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:92)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
+	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.successfulAuthentication(KeycloakAuthenticationProcessingFilter.java:214)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:233)
+	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
+	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
+	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
+	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
+	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
+	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
+	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
+	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
+	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
+	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
+	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
+	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
+	at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
+	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
+	at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
+	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
+	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
+	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
+	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
+	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
+	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
+	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
+	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
+	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
+	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
+	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+	at java.lang.Thread.run(Thread.java:748)
+Caused by: org.apache.pulsar.client.admin.PulsarAdminException: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.BaseResource.getApiException(BaseResource.java:247)
+	at org.apache.pulsar.client.admin.internal.FunctionsImpl$2.failed(FunctionsImpl.java:154)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyInvocation$1.failed(JerseyInvocation.java:882)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:247)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:242)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:178)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:292)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:274)
+	at org.apache.pulsar.shade.org.glassfish.jersey.internal.Errors.process(Errors.java:244)
+	at org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
+	at org.apache.pulsar.shade.org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:178)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$apply$1(AsyncHttpConnector.java:204)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:263)
+	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774)
+	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750)
+	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
+	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.NettyResponseFuture.abort(NettyResponseFuture.java:273)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.abort(NettyRequestSender.java:473)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.request.NettyRequestSender.handleUnexpectedClosedChannel(NettyRequestSender.java:484)
+	at org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelInactive(AsyncHttpClientHandler.java:145)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler.channelInactive(ChunkedWriteHandler.java:137)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder.channelInactive(HttpContentDecoder.java:235)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:418)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)
+	at org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)
+	at org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:326)
+	at org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)
+	at org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)
+	at org.apache.pulsar.shade.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
+	at org.apache.pulsar.shade.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
+	at org.apache.pulsar.shade.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
+	at org.apache.pulsar.shade.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
+	... 1 common frames omitted
+Caused by: java.util.concurrent.CompletionException: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
+	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
+	at java.util.concurrent.CompletableFuture.orApply(CompletableFuture.java:1385)
+	at java.util.concurrent.CompletableFuture$OrApply.tryFire(CompletableFuture.java:1364)
+	... 43 common frames omitted
+Caused by: org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector$RetryException: Could not complete the operation. Number of retries has been exhausted. Failed reason: Remotely closed
+	at org.apache.pulsar.client.admin.internal.http.AsyncHttpConnector.lambda$retryOperation$4(AsyncHttpConnector.java:265)
+	... 40 common frames omitted
+Caused by: org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException: Remotely closed
+	at org.apache.pulsar.shade.org.asynchttpclient.exception.RemotelyClosedException.INSTANCE(Unknown Source)
+
+2022-03-17 00:39:21.706  INFO 35449 --- [ionShutdownHook] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED paused.

BIN
log/info.2022-03-17.0.gz


BIN
log/info.2022-03-18.0.gz


+ 5 - 0
manager/pom.xml

@@ -143,6 +143,11 @@
             <artifactId>dao</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>cc.iotkit</groupId>
+            <artifactId>gateway-server</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 1 - 1
manager/src/main/java/cc/iotkit/manager/Application.java

@@ -5,7 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 
 @EnableFeignClients(basePackages = {"cc.iotkit.deviceapi"})
-@SpringBootApplication(scanBasePackages = {"cc.iotkit.manager", "cc.iotkit.dao", "cc.iotkit.ruleengine"})
+@SpringBootApplication(scanBasePackages = {"cc.iotkit"})
 public class Application {
 
     public static void main(String[] args) {

+ 2 - 1
manager/src/main/java/cc/iotkit/manager/config/KeycloakSecurityConfig.java

@@ -53,7 +53,8 @@ public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter
         super.configure(http);
         http
                 .authorizeRequests()
-                .antMatchers("/*.html", "/favicon.ico","/v2/api-docs", "/webjars/**", "/swagger-resources/**", "/*.js").permitAll()
+                .antMatchers("/*.html", "/favicon.ico", "/v2/api-docs", "/webjars/**", "/swagger-resources/**", "/*.js").permitAll()
+                .antMatchers("/device_behaviour/**").permitAll()
                 .antMatchers("/**/save*").hasRole("iot_write")
                 .antMatchers("/**/del*").hasRole("iot_write")
                 .antMatchers("/**/add*").hasRole("iot_write")

+ 4 - 4
manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java

@@ -1,6 +1,6 @@
 package cc.iotkit.manager.controller;
 
-import cc.iotkit.dao.DeviceDao;
+import cc.iotkit.dao.DeviceCache;
 import cc.iotkit.dao.DeviceEventDao;
 import cc.iotkit.dao.DeviceEventRepository;
 import cc.iotkit.dao.DeviceRepository;
@@ -36,7 +36,7 @@ public class DeviceController {
     @Autowired
     private DeviceEventDao deviceEventDao;
     @Autowired
-    private DeviceDao deviceDao;
+    private DeviceCache deviceCache;
     @Autowired
     private DataOwnerService dataOwnerService;
     @Autowired
@@ -78,8 +78,8 @@ public class DeviceController {
         if (online != null) {
             condition.and("state.online").is(online);
         }
-        return new PagingData<>(deviceDao.count(condition),
-                deviceDao.find(condition, (page - 1) * limit, limit, Sort.Order.desc("createAt")));
+        return new PagingData<>(deviceCache.count(condition),
+                deviceCache.find(condition, (page - 1) * limit, limit, Sort.Order.desc("createAt")));
     }
 
     @GetMapping("/{deviceId}/children")

+ 4 - 5
manager/src/main/java/cc/iotkit/manager/controller/ProductController.java

@@ -50,7 +50,6 @@ public class ProductController {
 
     @PostMapping("/save")
     public void save(Product product) {
-        product.setId(product.getCode());
         dataOwnerService.checkOwnerSave(productRepository, product);
 
         if (product.getCreateAt() == null) {
@@ -66,19 +65,19 @@ public class ProductController {
 
     @GetMapping("/thingModel/{productKey}")
     public ThingModel getThingModel(@PathVariable("productKey") String productKey) {
-        productKey = getProduct(productKey).getCode();
+        productKey = getProduct(productKey).getId();
         return thingModelRepository.findById(productKey).orElse(new ThingModel(productKey));
     }
 
     @PostMapping("/thingModel/save")
     public void saveThingModel(String productKey, String model) {
-        productKey = getProduct(productKey).getCode();
+        productKey = getProduct(productKey).getId();
         thingModelRepository.save(new ThingModel(productKey, productKey, JsonUtil.parse(model, ThingModel.Model.class)));
     }
 
     @DeleteMapping("/thingModel/{productKey}")
     public void deleteThingModel(String productKey) {
-        productKey = getProduct(productKey).getCode();
+        productKey = getProduct(productKey).getId();
         thingModelRepository.deleteById(productKey);
     }
 
@@ -104,7 +103,7 @@ public class ProductController {
     @PostMapping("/uploadImg/{productKey}")
     public String uploadImg(@PathVariable("productKey") String productKey,
                             @RequestParam("file") MultipartFile file) {
-        productKey = getProduct(productKey).getCode();
+        productKey = getProduct(productKey).getId();
 
         String fileName = file.getOriginalFilename();
         String end = fileName.substring(fileName.lastIndexOf("."));

+ 126 - 0
manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java

@@ -0,0 +1,126 @@
+package cc.iotkit.manager.controller;
+
+import cc.iotkit.common.exception.BizException;
+import cc.iotkit.common.utils.ReflectUtil;
+import cc.iotkit.dao.ProtocolGatewayRepository;
+import cc.iotkit.dao.UserInfoRepository;
+import cc.iotkit.manager.service.DataOwnerService;
+import cc.iotkit.manager.utils.AuthUtil;
+import cc.iotkit.model.Paging;
+import cc.iotkit.model.UserInfo;
+import cc.iotkit.model.protocol.ProtocolGateway;
+import cc.iotkit.protocol.server.service.GatewayService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Optional;
+
+@Slf4j
+@RestController
+@RequestMapping("/protocol")
+public class ProtocolController {
+
+    @Value("${gateway.function-jar}")
+    private String functionJar;
+
+    @Autowired
+    private ProtocolGatewayRepository gatewayRepository;
+
+    @Autowired
+    private GatewayService gatewayService;
+
+    @Autowired
+    private DataOwnerService dataOwnerService;
+
+    @Autowired
+    private UserInfoRepository userInfoRepository;
+
+    @PostMapping("/addGateway")
+    public void addGateway(ProtocolGateway gateway) {
+        Optional<ProtocolGateway> optGateway = gatewayRepository.findById(gateway.getId());
+        if (optGateway.isPresent()) {
+            throw new BizException("gateway already exists");
+        }
+        try {
+            Optional<UserInfo> optUser = userInfoRepository.findById(AuthUtil.getUserId());
+            if (!optUser.isPresent()) {
+                throw new BizException("user does not exists");
+            }
+
+            gateway.setScript("new (function () {this.decode = function (msg) {return null; };})().decode(msg)");
+            gateway.setCreateAt(System.currentTimeMillis());
+            gateway.setUid(AuthUtil.getUserId());
+            gateway.setUuid(optUser.get().getUid());
+            gatewayService.saveFunction(gateway.getUuid(), gateway.getId(), gateway.getScript(), functionJar);
+            gatewayRepository.save(gateway);
+        } catch (Throwable e) {
+            throw new BizException("add protocol gateway error", e);
+        }
+    }
+
+    @PostMapping("/saveGateway")
+    public void saveGateway(ProtocolGateway gateway) {
+        Optional<ProtocolGateway> optGateway = gatewayRepository.findById(gateway.getId());
+        if (!optGateway.isPresent()) {
+            throw new BizException("the gateway does not exists");
+        }
+        Optional<UserInfo> optUser = userInfoRepository.findById(AuthUtil.getUserId());
+        if (!optUser.isPresent()) {
+            throw new BizException("user does not exists");
+        }
+
+        ProtocolGateway oldGateway = optGateway.get();
+        gateway = ReflectUtil.copyNoNulls(gateway, oldGateway);
+        dataOwnerService.checkOwner(gateway);
+        try {
+            gatewayRepository.save(gateway);
+            gatewayService.saveFunction(gateway.getUuid(), gateway.getId(), gateway.getScript(), functionJar);
+        } catch (Throwable e) {
+            throw new BizException("add protocol gateway error", e);
+        }
+    }
+
+    @PostMapping("/saveGatewayScript")
+    public void saveGatewayScript(@RequestBody ProtocolGateway gateway) {
+        Optional<ProtocolGateway> optGateway = gatewayRepository.findById(gateway.getId());
+        if (!optGateway.isPresent()) {
+            throw new BizException("the gateway does not exists");
+        }
+        dataOwnerService.checkOwner(gateway);
+        ProtocolGateway oldGateway = optGateway.get();
+        oldGateway.setScript(gateway.getScript());
+        try {
+            gatewayService.saveFunction(oldGateway.getUuid(), oldGateway.getId(),
+                    "new (function (){" + oldGateway.getScript() + "})()", functionJar);
+            gatewayRepository.save(oldGateway);
+        } catch (Throwable e) {
+            throw new BizException("save protocol gateway script error", e);
+        }
+    }
+
+    @PostMapping("/deleteGateway/{id}")
+    public void deleteGateway(@PathVariable("id") String id) {
+        dataOwnerService.checkOwner(gatewayRepository, id);
+        try {
+            gatewayRepository.deleteById(id);
+            gatewayService.deleteFunction(AuthUtil.getUserId(), id);
+        } catch (Throwable e) {
+            throw new BizException("delete protocol gateway error", e);
+        }
+    }
+
+    @PostMapping("/gateways/{size}/{page}")
+    public Paging<ProtocolGateway> getGateways(
+            @PathVariable("size") int size,
+            @PathVariable("page") int page) {
+        Page<ProtocolGateway> gateways = gatewayRepository.findAll(
+                PageRequest.of(page - 1, size, Sort.by(Sort.Order.desc("createAt"))));
+        return new Paging<>(gateways.getTotalElements(), gateways.getContent());
+    }
+
+}

+ 4 - 10
manager/src/main/java/cc/iotkit/manager/controller/RuleEngineController.java

@@ -40,9 +40,6 @@ public class RuleEngineController {
     @Autowired
     private SceneLogRepository sceneLogRepository;
 
-    @Autowired
-    private SceneLogDao sceneLogDao;
-
     @Autowired
     private DataOwnerService dataOwnerService;
 
@@ -52,9 +49,6 @@ public class RuleEngineController {
     @Autowired
     private SceneManager sceneManager;
 
-    @Autowired
-    private TaskLogDao taskLogDao;
-
     @Autowired
     private TaskLogRepository taskLogRepository;
 
@@ -132,7 +126,7 @@ public class RuleEngineController {
         dataOwnerService.checkOwner(sceneInfo);
         sceneInfoRepository.delete(sceneInfo);
         sceneManager.remove(sceneInfo.getId());
-        sceneLogDao.deleteLogs(sceneId);
+        sceneLogRepository.deleteBySceneId(sceneId);
     }
 
     @PostMapping("/scene/{sceneId}/logs/{size}/{page}")
@@ -150,7 +144,7 @@ public class RuleEngineController {
 
     @DeleteMapping("/scene/{sceneId}/logs/clear")
     public void clearSceneLogs(@PathVariable("sceneId") String sceneId) {
-        sceneLogDao.deleteLogs(sceneId);
+        sceneLogRepository.deleteBySceneId(sceneId);
     }
 
     @PostMapping("/tasks")
@@ -230,7 +224,7 @@ public class RuleEngineController {
         dataOwnerService.checkOwner(taskInfo);
         taskManager.deleteTask(taskId, "delete by " + AuthUtil.getUserId());
         taskInfoRepository.deleteById(taskId);
-        taskLogDao.deleteLogs(taskId);
+        taskLogRepository.deleteByTaskId(taskId);
     }
 
     @PostMapping("/task/{taskId}/logs/{size}/{page}")
@@ -248,7 +242,7 @@ public class RuleEngineController {
 
     @DeleteMapping("/task/{taskId}/logs/clear")
     public void clearTaskLogs(@PathVariable("taskId") String taskId) {
-        taskLogDao.deleteLogs(taskId);
+        taskLogRepository.deleteByTaskId(taskId);
     }
 
 }

+ 4 - 4
manager/src/main/java/cc/iotkit/manager/controller/SpaceController.java

@@ -30,9 +30,9 @@ public class SpaceController {
     @Autowired
     private DeviceRepository deviceRepository;
     @Autowired
-    private DeviceDao deviceDao;
+    private DeviceCache deviceCache;
     @Autowired
-    private ProductDao productDao;
+    private ProductCache productCache;
 
     @PostMapping("/list")
     public PagingData<SpaceInfo> getDevices(int page,
@@ -58,8 +58,8 @@ public class SpaceController {
         List<SpaceDeviceVo> deviceVos = new ArrayList<>();
         List<SpaceDevice> devices = spaceDeviceRepository.findAll(Example.of(SpaceDevice.builder().uid(userId).build()));
         devices.forEach(sd -> {
-            DeviceInfo deviceInfo = deviceDao.get(sd.getDeviceId());
-            Product product = productDao.get(deviceInfo.getProductKey());
+            DeviceInfo deviceInfo = deviceCache.findByDeviceId(sd.getDeviceId());
+            Product product = productCache.findById(deviceInfo.getProductKey());
             deviceVos.add(SpaceDeviceVo.builder()
                     .deviceId(sd.getDeviceId())
                     .name(sd.getName())

+ 27 - 16
manager/src/main/java/cc/iotkit/manager/controller/UserInfoController.java

@@ -6,11 +6,11 @@ import cc.iotkit.common.utils.ReflectUtil;
 import cc.iotkit.dao.UserInfoRepository;
 import cc.iotkit.manager.service.AligenieService;
 import cc.iotkit.manager.service.KeycloakAdminService;
+import cc.iotkit.manager.service.PulsarAdminService;
 import cc.iotkit.manager.utils.AuthUtil;
 import cc.iotkit.model.UserInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.domain.Example;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -29,15 +29,18 @@ public class UserInfoController extends DbBaseController<UserInfoRepository, Use
     private final KeycloakAdminService keycloakAdminService;
     private final UserInfoRepository userInfoRepository;
     private final AligenieService aligenieService;
+    private final PulsarAdminService pulsarAdminService;
 
     @Autowired
     public UserInfoController(UserInfoRepository userInfoRepository,
                               KeycloakAdminService keycloakAdminService,
-                              AligenieService aligenieService) {
+                              AligenieService aligenieService,
+                              PulsarAdminService pulsarAdminService) {
         super(userInfoRepository);
         this.keycloakAdminService = keycloakAdminService;
         this.userInfoRepository = userInfoRepository;
         this.aligenieService = aligenieService;
+        this.pulsarAdminService = pulsarAdminService;
     }
 
     /**
@@ -46,8 +49,7 @@ public class UserInfoController extends DbBaseController<UserInfoRepository, Use
     @PreAuthorize("hasRole('iot_admin')")
     @GetMapping("/platform/users")
     public List<UserInfo> getPlatformUsers() {
-        return userInfoRepository.findAll(Example.of(UserInfo.builder()
-                .type(UserInfo.USER_TYPE_PLATFORM).build()));
+        return userInfoRepository.findByType(UserInfo.USER_TYPE_PLATFORM);
     }
 
     /**
@@ -55,13 +57,26 @@ public class UserInfoController extends DbBaseController<UserInfoRepository, Use
      */
     @PostMapping("/platform/user/add")
     public void addPlatformUser(@RequestBody UserInfo user) {
-        user.setId(UUID.randomUUID().toString());
-        user.setType(UserInfo.USER_TYPE_PLATFORM);
-        user.setOwnerId(AuthUtil.getUserId());
-        user.setRoles(Arrays.asList(Constants.ROLE_SYSTEM));
-        user.setCreateAt(System.currentTimeMillis());
-        keycloakAdminService.createUser(user, Constants.PWD_SYSTEM_USER);
-        userInfoRepository.save(user);
+        try {
+            user.setId(UUID.randomUUID().toString());
+            user.setType(UserInfo.USER_TYPE_PLATFORM);
+            user.setOwnerId(AuthUtil.getUserId());
+            user.setRoles(Arrays.asList(Constants.ROLE_SYSTEM));
+            user.setCreateAt(System.currentTimeMillis());
+            UserInfo keycloakUser = keycloakAdminService.getUser(user.getUid());
+            if (keycloakUser != null) {
+                user.setId(keycloakUser.getId());
+                keycloakAdminService.updateUser(user);
+            } else {
+                keycloakAdminService.createUser(user, Constants.PWD_SYSTEM_USER);
+            }
+            if (!pulsarAdminService.tenantExists(user.getUid())) {
+                pulsarAdminService.createTenant(user.getUid());
+            }
+            userInfoRepository.save(user);
+        } catch (Throwable e) {
+            throw new BizException("add platform user error", e);
+        }
     }
 
     /**
@@ -69,11 +84,7 @@ public class UserInfoController extends DbBaseController<UserInfoRepository, Use
      */
     @GetMapping("/client/users")
     public List<UserInfo> clientUsers() {
-        return userInfoRepository.findAll(Example.of(
-                UserInfo.builder()
-                        .type(UserInfo.USER_TYPE_CLIENT)
-                        .ownerId(AuthUtil.getUserId())
-                        .build()));
+        return userInfoRepository.findByTypeAndOwnerId(UserInfo.USER_TYPE_CLIENT, AuthUtil.getUserId());
     }
 
     /**

+ 5 - 5
manager/src/main/java/cc/iotkit/manager/controller/aligenie/AligenieProductController.java

@@ -2,7 +2,7 @@ package cc.iotkit.manager.controller.aligenie;
 
 import cc.iotkit.dao.AligenieProductDao;
 import cc.iotkit.dao.AligenieProductRepository;
-import cc.iotkit.dao.ProductDao;
+import cc.iotkit.dao.ProductCache;
 import cc.iotkit.manager.controller.DbBaseController;
 import cc.iotkit.manager.model.aligenie.AligenieProductVo;
 import cc.iotkit.manager.service.DataOwnerService;
@@ -23,18 +23,18 @@ import java.util.List;
 @RequestMapping("/aligenie/product")
 public class AligenieProductController extends DbBaseController<AligenieProductRepository, AligenieProduct> {
 
-    private final ProductDao productDao;
+    private final ProductCache productCache;
     private final AligenieProductDao aligenieProductDao;
     private final DataOwnerService dataOwnerService;
 
 
     @Autowired
     public AligenieProductController(AligenieProductRepository aligenieProductRepository,
-                                     ProductDao productDao,
+                                     ProductCache productCache,
                                      AligenieProductDao aligenieProductDao,
                                      DataOwnerService dataOwnerService) {
         super(aligenieProductRepository);
-        this.productDao = productDao;
+        this.productCache = productCache;
         this.aligenieProductDao = aligenieProductDao;
         this.dataOwnerService = dataOwnerService;
     }
@@ -49,7 +49,7 @@ public class AligenieProductController extends DbBaseController<AligenieProductR
                                 .build()));
 
         for (AligenieProduct ap : aligenieProducts) {
-            Product product = productDao.get(ap.getProductKey());
+            Product product = productCache.findById(ap.getProductKey());
             productVos.add(new AligenieProductVo(ap, product.getName()));
         }
         return productVos;

+ 10 - 7
manager/src/main/java/cc/iotkit/manager/controller/api/MessageController.java

@@ -1,7 +1,7 @@
 package cc.iotkit.manager.controller.api;
 
-import cc.iotkit.dao.DeviceDao;
-import cc.iotkit.dao.ProductDao;
+import cc.iotkit.dao.DeviceCache;
+import cc.iotkit.dao.ProductCache;
 import cc.iotkit.dao.UserActionLogRepository;
 import cc.iotkit.manager.model.vo.MessageVo;
 import cc.iotkit.manager.utils.AuthUtil;
@@ -31,9 +31,9 @@ public class MessageController {
     @Autowired
     private UserActionLogRepository userActionLogRepository;
     @Autowired
-    private ProductDao productDao;
+    private ProductCache productCache;
     @Autowired
-    private DeviceDao deviceDao;
+    private DeviceCache deviceCache;
 
     @ApiOperation("取系统消息")
     @PostMapping("/getSysMessages")
@@ -67,9 +67,12 @@ public class MessageController {
         StringBuffer logMsg = new StringBuffer();
         if (log instanceof DeviceEvent) {
             DeviceEvent de = (DeviceEvent) log;
-            DeviceInfo device = deviceDao.getByDeviceId(de.getDeviceId());
-            ThingModel.Model model = productDao.getThingModel(device.getProductKey())
-                    .getModel();
+            DeviceInfo device = deviceCache.findByDeviceId(de.getDeviceId());
+            ThingModel thingModel = productCache.getThingModel(device.getProductKey());
+            if (thingModel == null) {
+                return logMsg.toString();
+            }
+            ThingModel.Model model = thingModel.getModel();
             logMsg.append("将【").append(target).append("】");
 
             String identifier = de.getIdentifier();

+ 4 - 4
manager/src/main/java/cc/iotkit/manager/controller/api/SpaceController.java

@@ -39,9 +39,9 @@ public class SpaceController {
     @Autowired
     private ProductRepository productRepository;
     @Autowired
-    private ProductDao productDao;
+    private ProductCache productCache;
     @Autowired
-    private DeviceDao deviceDao;
+    private DeviceCache deviceCache;
     @Autowired
     private SpaceDeviceService spaceDeviceService;
 
@@ -170,8 +170,8 @@ public class SpaceController {
     }
 
     private SpaceDeviceVo buildSpaceDeviceVo(String id, String deviceId, String uid, String name, String spaceName) {
-        DeviceInfo deviceInfo = deviceDao.get(deviceId);
-        Product product = productDao.get(deviceInfo.getProductKey());
+        DeviceInfo deviceInfo = deviceCache.findByDeviceId(deviceId);
+        Product product = productCache.findById(deviceInfo.getProductKey());
         return SpaceDeviceVo.builder()
                 .id(id)
                 .uid(uid)

+ 3 - 3
manager/src/main/java/cc/iotkit/manager/service/AligenieService.java

@@ -2,7 +2,7 @@ package cc.iotkit.manager.service;
 
 import cc.iotkit.dao.AligenieDeviceRepository;
 import cc.iotkit.dao.AligenieProductDao;
-import cc.iotkit.dao.DeviceDao;
+import cc.iotkit.dao.DeviceCache;
 import cc.iotkit.dao.SpaceDeviceRepository;
 import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.space.SpaceDevice;
@@ -28,7 +28,7 @@ public class AligenieService {
     private AligenieProductDao aligenieProductDao;
 
     @Autowired
-    private DeviceDao deviceDao;
+    private DeviceCache deviceCache;
 
     public void syncDevice(UserInfo user) {
         if (!user.getUsePlatforms().isAligenie()) {
@@ -58,7 +58,7 @@ public class AligenieService {
 
             //不存在设备,新增
             if (aligenieDevice == null) {
-                DeviceInfo deviceInfo = deviceDao.get(spaceDevice.getDeviceId());
+                DeviceInfo deviceInfo = deviceCache.findByDeviceId(spaceDevice.getDeviceId());
                 AligenieProduct aligenieProduct = aligenieProductDao.getAligenieProduct(deviceInfo.getProductKey());
                 if(aligenieProduct==null){
                     continue;

+ 14 - 6
manager/src/main/java/cc/iotkit/manager/service/DataOwnerService.java

@@ -18,6 +18,9 @@ public class DataOwnerService {
         return data;
     }
 
+    /**
+     * 检查数据中的uid与当前登录用户是否一致
+     */
     public <T extends Owned> T checkOwner(T data) {
         //管理员不限制
         if (AuthUtil.isAdmin()) {
@@ -37,19 +40,21 @@ public class DataOwnerService {
         throw new BizException("无权限操作");
     }
 
-    public <T extends Owned> void checkOwner(MongoRepository<T, String> repository, T data) {
+    /**
+     * 从库中取对应数据Id的数据中的uid是否与当前登录用户一致
+     */
+    public <T extends Owned> void checkOwner(MongoRepository<T, String> repository, String id) {
         //管理员不限制
         if (AuthUtil.isAdmin()) {
             return;
         }
 
-        String dataId = data.getId();
-        //没有数据id为新数据
-        if (StringUtils.isBlank(dataId)) {
+        //数据id为空的新数据
+        if (StringUtils.isBlank(id)) {
             return;
         }
 
-        T old = repository.findById(dataId).orElse(null);
+        T old = repository.findById(id).orElse(null);
         //新数据
         if (old == null) {
             return;
@@ -63,8 +68,11 @@ public class DataOwnerService {
         throw new BizException("无权限操作");
     }
 
+    /**
+     * 从库中取对应数据Id的数据中的uid是否与当前登录用户一致,并把当前用户id设置到数据中
+     */
     public <T extends Owned> void checkOwnerSave(MongoRepository<T, String> repository, T data) {
-        checkOwner(repository, data);
+        checkOwner(repository, data.getId());
         data.setUid(AuthUtil.getUserId());
     }
 

+ 2 - 2
manager/src/main/java/cc/iotkit/manager/service/DeviceService.java

@@ -1,7 +1,7 @@
 package cc.iotkit.manager.service;
 
 import cc.iotkit.common.exception.NotFoundException;
-import cc.iotkit.dao.DeviceDao;
+import cc.iotkit.dao.DeviceCache;
 import cc.iotkit.dao.DeviceEventRepository;
 import cc.iotkit.dao.DeviceRepository;
 import cc.iotkit.dao.ThingModelRepository;
@@ -23,7 +23,7 @@ import java.util.Map;
 public class DeviceService {
 
     @Autowired
-    private DeviceDao deviceDao;
+    private DeviceCache deviceCache;
     @Autowired
     private DeviceRepository deviceRepository;
     @Autowired

+ 17 - 1
manager/src/main/java/cc/iotkit/manager/service/KeycloakAdminService.java

@@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.util.Arrays;
+import java.util.List;
 
 @Slf4j
 @Service
@@ -49,7 +50,7 @@ public class KeycloakAdminService {
         return keycloak;
     }
 
-    public void createUser(UserInfo user,String pwd) {
+    public void createUser(UserInfo user, String pwd) {
         Keycloak keycloak = getKeycloak();
         UsersResource usersResource = keycloak.realm(realm)
                 .users();
@@ -96,6 +97,21 @@ public class KeycloakAdminService {
         userResource.update(userRepresentation);
     }
 
+    public UserInfo getUser(String uid) {
+        Keycloak keycloak = getKeycloak();
+        List<UserRepresentation> users = keycloak.realm(realm)
+                .users().search(uid);
+        if (users.size() == 0) {
+            return null;
+        }
+        UserRepresentation user = users.get(0);
+
+        return UserInfo.builder()
+                .id(user.getId())
+                .uid(uid)
+                .build();
+    }
+
     public void resetUserPwd(String id, String pwd) {
         Keycloak keycloak = getKeycloak();
         UserResource userResource = keycloak.realm(realm)

+ 51 - 0
manager/src/main/java/cc/iotkit/manager/service/PulsarAdminService.java

@@ -0,0 +1,51 @@
+package cc.iotkit.manager.service;
+
+import cc.iotkit.common.utils.JsonUtil;
+import org.apache.pulsar.client.admin.PulsarAdmin;
+import org.apache.pulsar.client.admin.PulsarAdminException;
+import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.pulsar.common.policies.data.TenantInfo;
+import org.apache.pulsar.shade.com.google.common.collect.Sets;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.HashSet;
+
+@Service
+public class PulsarAdminService {
+
+    @Value("${pulsar.service}")
+    private String pulsarServiceUrl;
+
+    private PulsarAdmin pulsarAdmin;
+
+    private PulsarAdmin getPulsarAdmin() throws PulsarClientException {
+        if (pulsarAdmin == null) {
+            pulsarAdmin = PulsarAdmin.builder()
+                    .serviceHttpUrl(pulsarServiceUrl)
+                    .build();
+        }
+        return pulsarAdmin;
+    }
+
+    public boolean tenantExists(String uid) throws PulsarAdminException, PulsarClientException {
+        PulsarAdmin pulsarAdmin = getPulsarAdmin();
+        return pulsarAdmin.tenants().getTenants().contains(uid);
+    }
+
+    public void createTenant(String uid) throws PulsarClientException, PulsarAdminException {
+        PulsarAdmin pulsarAdmin = getPulsarAdmin();
+        pulsarAdmin.tenants().createTenant(uid, TenantInfo.builder()
+                .adminRoles(new HashSet<>())
+                .allowedClusters(Sets.newHashSet("standalone"))
+                .build());
+
+        pulsarAdmin.namespaces().createNamespace(uid + "/default");
+    }
+
+    public void deleteTenant(String uid) throws PulsarClientException, PulsarAdminException {
+        PulsarAdmin pulsarAdmin = getPulsarAdmin();
+        pulsarAdmin.tenants().deleteTenant(uid);
+    }
+
+}

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä