-
-
+
+
-
- Your ThingsBoard account feature was disabled
- |
+  |
-
- | We have disabled the ${apiFeature} for your account because ThingsBoard has already ${apiLimitValueLabel}.
+ |
+ | Your ThingsBoard account feature was disabled |
+
+
+
+ 
+ We have disabled the ${apiFeature} for your account because ThingsBoard has already ${apiLimitValueLabel}.
+
|
- | Please contact your system administrator to resolve the issue.
- |
+ Please contact your system administrator to resolve the issue. |
- | — The ThingsBoard
- |
+ — The ThingsBoard |
@@ -144,16 +134,10 @@
|
-
+
diff --git a/application/src/main/resources/templates/state.enabled.ftl b/application/src/main/resources/templates/state.enabled.ftl
index 0a7841f871..e03f38bba3 100644
--- a/application/src/main/resources/templates/state.enabled.ftl
+++ b/application/src/main/resources/templates/state.enabled.ftl
@@ -103,34 +103,27 @@
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;"
bgcolor="#f6f6f6">
-
+
-
-
+
+
-
- Your ThingsBoard account feature was enabled
- |
+  |
-
- | We have enabled the ${apiFeature} for your account and ThingsBoard is already able to ${apiLabel} messages.
+ |
+ | Your ThingsBoard account feature was enabled |
+
+
+
+ 
+ We have enabled the ${apiFeature} for your account and ThingsBoard is already able to ${apiLabel} messages.
+
|
- | — The ThingsBoard
- |
+ — The ThingsBoard |
@@ -138,16 +131,10 @@
|
-
+
diff --git a/application/src/main/resources/templates/state.warning.ftl b/application/src/main/resources/templates/state.warning.ftl
index 1ce29100a7..67fc557e87 100644
--- a/application/src/main/resources/templates/state.warning.ftl
+++ b/application/src/main/resources/templates/state.warning.ftl
@@ -103,41 +103,30 @@
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;"
bgcolor="#f6f6f6">
-
+
-
-
+
+
-
- Your ThingsBoard account feature may be disabled soon
- |
+  |
-
-
- ThingsBoard has already ${apiValueLabel}. ${apiFeature} will be disabled for your account once the limit will be reached.
+ |
+ | Warning: your ThingsBoard account feature may be disabled soon |
+
+
+
+ 
+ ThingsBoard has already ${apiValueLabel}. ${apiFeature} will be disabled for your account once the limit will be reached.
+
|
- | Please contact your system administrator to resolve the issue.
- |
+ Please contact your system administrator to resolve the issue. |
- | — The ThingsBoard
- |
+ — The ThingsBoard |
@@ -145,16 +134,10 @@
|
-
+
diff --git a/common/actor/pom.xml b/common/actor/pom.xml
index 9258ee75a4..9dea3c57a3 100644
--- a/common/actor/pom.xml
+++ b/common/actor/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml
index 650b05c04e..d50399525e 100644
--- a/common/dao-api/pom.xml
+++ b/common/dao-api/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java
index 5d038b2d31..660f1a5f35 100644
--- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java
+++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java
@@ -15,9 +15,6 @@
*/
package org.thingsboard.server.dao.device;
-import com.google.common.util.concurrent.ListenableFuture;
-import org.thingsboard.server.common.data.Device;
-import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
import org.thingsboard.server.dao.device.provision.ProvisionRequest;
import org.thingsboard.server.dao.device.provision.ProvisionResponse;
diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java
index 735e23e73a..ea3d65eb49 100644
--- a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java
+++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java
@@ -16,9 +16,12 @@
package org.thingsboard.server.dao.tenant;
import org.thingsboard.server.common.data.TenantProfile;
+import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
+import java.util.function.Consumer;
+
public interface TbTenantProfileCache {
TenantProfile get(TenantId tenantId);
@@ -31,4 +34,8 @@ public interface TbTenantProfileCache {
void evict(TenantId id);
+ void addListener(TenantId tenantId, EntityId listenerId, Consumer profileListener);
+
+ void removeListener(TenantId tenantId, EntityId listenerId);
+
}
diff --git a/common/data/pom.xml b/common/data/pom.xml
index fc1311ab02..b2dd156acb 100644
--- a/common/data/pom.xml
+++ b/common/data/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java
index 17035f337b..3b6acce6f3 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java
@@ -18,9 +18,8 @@ package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
-import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
+import java.util.TreeMap;
@Data
public class DeviceProfileAlarm {
@@ -28,7 +27,7 @@ public class DeviceProfileAlarm {
private String id;
private String alarmType;
- private LinkedHashMap createRules;
+ private TreeMap createRules;
private AlarmRule clearRule;
// Hidden in advanced settings
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/AwsSnsSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java
similarity index 94%
rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/AwsSnsSmsProviderConfiguration.java
rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java
index 74cd5486a1..2acad17a0f 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/AwsSnsSmsProviderConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.rule.engine.api.sms.config;
+package org.thingsboard.server.common.data.sms.config;
import lombok.Data;
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderConfiguration.java
similarity index 95%
rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderConfiguration.java
rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderConfiguration.java
index 8feec6ff40..8b1984e9b4 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderConfiguration.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.rule.engine.api.sms.config;
+package org.thingsboard.server.common.data.sms.config;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderType.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderType.java
similarity index 92%
rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderType.java
rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderType.java
index e698dd4783..f60d917cf1 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderType.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderType.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.rule.engine.api.sms.config;
+package org.thingsboard.server.common.data.sms.config;
public enum SmsProviderType {
AWS_SNS,
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TestSmsRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java
similarity index 93%
rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TestSmsRequest.java
rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java
index 3d00f9e580..23c44be48c 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TestSmsRequest.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.rule.engine.api.sms.config;
+package org.thingsboard.server.common.data.sms.config;
import lombok.Data;
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TwilioSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java
similarity index 94%
rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TwilioSmsProviderConfiguration.java
rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java
index 2e0585e466..6f9b226711 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TwilioSmsProviderConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.thingsboard.rule.engine.api.sms.config;
+package org.thingsboard.server.common.data.sms.config;
import lombok.Data;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java
index 28ef5cae13..054f78766b 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java
@@ -45,6 +45,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
private long maxEmails;
private long maxSms;
+ private int defaultStorageTtlDays;
+
private double warnThreshold;
@Override
diff --git a/common/message/pom.xml b/common/message/pom.xml
index 17a0679630..bcff40ce4d 100644
--- a/common/message/pom.xml
+++ b/common/message/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/pom.xml b/common/pom.xml
index 52685d3891..5ceae3ea57 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
common
diff --git a/common/queue/pom.xml b/common/queue/pom.xml
index aaf46710f7..54cd24f66d 100644
--- a/common/queue/pom.xml
+++ b/common/queue/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java
index c683ed846d..5cceb43324 100644
--- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java
+++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java
@@ -195,9 +195,11 @@ public class HashPartitionService implements PartitionService {
if (current.getServiceTypesList().contains(serviceType.name())) {
result.add(current.getServiceId());
}
- for (ServiceInfo serviceInfo : currentOtherServices) {
- if (serviceInfo.getServiceTypesList().contains(serviceType.name())) {
- result.add(serviceInfo.getServiceId());
+ if (currentOtherServices != null) {
+ for (ServiceInfo serviceInfo : currentOtherServices) {
+ if (serviceInfo.getServiceTypesList().contains(serviceType.name())) {
+ result.add(serviceInfo.getServiceId());
+ }
}
}
return result;
diff --git a/common/stats/pom.xml b/common/stats/pom.xml
index 10c3ccb040..8cf70c7498 100644
--- a/common/stats/pom.xml
+++ b/common/stats/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml
index 3b04a20abe..e775286bdd 100644
--- a/common/transport/coap/pom.xml
+++ b/common/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java
index afb83f513f..a6813e488d 100644
--- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java
+++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java
@@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.CoapServer;
import org.eclipse.californium.core.network.CoapEndpoint;
+import org.eclipse.californium.core.network.config.NetworkConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
@@ -46,7 +47,7 @@ public class CoapTransportService {
public void init() throws UnknownHostException {
log.info("Starting CoAP transport...");
log.info("Starting CoAP transport server");
- this.server = new CoapServer();
+ this.server = new CoapServer(NetworkConfig.createStandardWithoutFile());
createResources();
InetAddress addr = InetAddress.getByName(coapTransportContext.getHost());
InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort());
diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml
index 040f7c372e..ab60e6d4eb 100644
--- a/common/transport/http/pom.xml
+++ b/common/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml
index 8a02c940a7..8b043b8c2e 100644
--- a/common/transport/mqtt/pom.xml
+++ b/common/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
index cabc61cab6..0df14d4655 100644
--- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
+++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
@@ -179,6 +179,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
}
} else {
+ ctx.close();
throw new RuntimeException("Unsupported topic for provisioning requests!");
}
} catch (RuntimeException | AdaptorException e) {
diff --git a/common/transport/pom.xml b/common/transport/pom.xml
index fbdb10d081..22b17989c9 100644
--- a/common/transport/pom.xml
+++ b/common/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml
index 168c991eb6..d61963053e 100644
--- a/common/transport/transport-api/pom.xml
+++ b/common/transport/transport-api/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/util/pom.xml b/common/util/pom.xml
index 076eff152a..474db1270e 100644
--- a/common/util/pom.xml
+++ b/common/util/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
common
org.thingsboard.common
diff --git a/dao/pom.xml b/dao/pom.xml
index ec4960eb5f..907ddb7150 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
dao
diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
index 29eaad31fb..e8375d8065 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
@@ -78,6 +78,8 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
public static final String INCORRECT_PAGE_LINK = "Incorrect page link ";
public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId ";
public static final String INCORRECT_ASSET_ID = "Incorrect assetId ";
+ public static final String TB_SERVICE_QUEUE = "TbServiceQueue";
+
@Autowired
private AssetDao assetDao;
@@ -329,8 +331,10 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
protected void validateCreate(TenantId tenantId, Asset asset) {
DefaultTenantProfileConfiguration profileConfiguration =
(DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration();
- long maxAssets = profileConfiguration.getMaxAssets();
- validateNumberOfEntitiesPerTenant(tenantId, assetDao, maxAssets, EntityType.ASSET);
+ if (!TB_SERVICE_QUEUE.equals(asset.getType())) {
+ long maxAssets = profileConfiguration.getMaxAssets();
+ validateNumberOfEntitiesPerTenant(tenantId, assetDao, maxAssets, EntityType.ASSET);
+ }
}
@Override
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java
index a6e016c418..da2bc9e687 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java
@@ -122,5 +122,5 @@ public interface AssetRepository extends PagingAndSortingRepository findTenantAssetTypes(@Param("tenantId") UUID tenantId);
- Long countByTenantId(UUID tenantId);
+ Long countByTenantIdAndTypeIsNot(UUID tenantId, String type);
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java
index d2a5167b43..b56a3eb3a9 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java
@@ -39,6 +39,8 @@ import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
+import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE;
+
/**
* Created by Valerii Sosliuk on 5/19/2017.
*/
@@ -179,6 +181,6 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im
@Override
public Long countByTenantId(TenantId tenantId) {
- return assetRepository.countByTenantId(tenantId.getId());
+ return assetRepository.countByTenantIdAndTypeIsNot(tenantId.getId(), TB_SERVICE_QUEUE);
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java
index adf05e0f74..b468019872 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java
@@ -19,16 +19,15 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
+import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
-import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
-import org.thingsboard.server.dao.tenant.TenantProfileService;
-import org.thingsboard.server.dao.tenant.TenantService;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
@Service
@Slf4j
@@ -40,6 +39,7 @@ public class DefaultTbTenantProfileCache implements TbTenantProfileCache {
private final ConcurrentMap tenantProfilesMap = new ConcurrentHashMap<>();
private final ConcurrentMap tenantsMap = new ConcurrentHashMap<>();
+ private final ConcurrentMap>> profileListeners = new ConcurrentHashMap<>();
public DefaultTbTenantProfileCache(TenantProfileService tenantProfileService, TenantService tenantService) {
this.tenantProfileService = tenantProfileService;
@@ -85,17 +85,56 @@ public class DefaultTbTenantProfileCache implements TbTenantProfileCache {
public void put(TenantProfile profile) {
if (profile.getId() != null) {
tenantProfilesMap.put(profile.getId(), profile);
+ notifyTenantListeners(profile);
}
}
@Override
public void evict(TenantProfileId profileId) {
tenantProfilesMap.remove(profileId);
+ notifyTenantListeners(get(profileId));
+ }
+
+ public void notifyTenantListeners(TenantProfile tenantProfile) {
+ if (tenantProfile != null) {
+ tenantsMap.forEach(((tenantId, tenantProfileId) -> {
+ if (tenantProfileId.equals(tenantProfile.getId())) {
+ ConcurrentMap> tenantListeners = profileListeners.get(tenantId);
+ if (tenantListeners != null) {
+ tenantListeners.forEach((id, listener) -> listener.accept(tenantProfile));
+ }
+ }
+ }));
+ }
}
@Override
public void evict(TenantId tenantId) {
tenantsMap.remove(tenantId);
+ TenantProfile tenantProfile = get(tenantId);
+ if (tenantProfile != null) {
+ ConcurrentMap> tenantListeners = profileListeners.get(tenantId);
+ if (tenantListeners != null) {
+ tenantListeners.forEach((id, listener) -> listener.accept(tenantProfile));
+ }
+ }
+ }
+
+ @Override
+ public void addListener(TenantId tenantId, EntityId listenerId, Consumer profileListener) {
+ //Force cache of the tenant id.
+ get(tenantId);
+ if (profileListener != null) {
+ profileListeners.computeIfAbsent(tenantId, id -> new ConcurrentHashMap<>()).put(listenerId, profileListener);
+ }
+ }
+
+ @Override
+ public void removeListener(TenantId tenantId, EntityId listenerId) {
+ ConcurrentMap> tenantListeners = profileListeners.get(tenantId);
+ if (tenantListeners != null) {
+ tenantListeners.remove(listenerId);
+ }
}
}
diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml
index 74948b0e84..339b60741f 100644
--- a/msa/black-box-tests/pom.xml
+++ b/msa/black-box-tests/pom.xml
@@ -21,7 +21,7 @@
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json
index 1f498922cd..af75855eaf 100644
--- a/msa/js-executor/package.json
+++ b/msa/js-executor/package.json
@@ -1,7 +1,7 @@
{
"name": "thingsboard-js-executor",
"private": true,
- "version": "3.2.0",
+ "version": "3.2.1",
"description": "ThingsBoard JavaScript Executor Microservice",
"main": "server.js",
"bin": "server.js",
diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml
index ea286c58ba..692b371275 100644
--- a/msa/js-executor/pom.xml
+++ b/msa/js-executor/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/pom.xml b/msa/pom.xml
index 7419141995..cfdf6ed79f 100644
--- a/msa/pom.xml
+++ b/msa/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
msa
diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml
index 2d42d8f6dd..ad700779a9 100644
--- a/msa/tb-node/pom.xml
+++ b/msa/tb-node/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/tb/docker-cassandra/start-db.sh b/msa/tb/docker-cassandra/start-db.sh
index fa80f6db57..8491a979d2 100644
--- a/msa/tb/docker-cassandra/start-db.sh
+++ b/msa/tb/docker-cassandra/start-db.sh
@@ -27,7 +27,11 @@ fi
exec setsid nohup postgres >> ${PGLOG}/postgres.log 2>&1 &
if [ ! -f ${firstlaunch} ]; then
- psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard"
+ sleep 2
+ while ! psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard"
+ do
+ sleep 1
+ done
fi
cassandra_data_dir=${CASSANDRA_DATA}
diff --git a/msa/tb/docker-postgres/start-db.sh b/msa/tb/docker-postgres/start-db.sh
index 6119daf2f9..618dae77da 100644
--- a/msa/tb/docker-postgres/start-db.sh
+++ b/msa/tb/docker-postgres/start-db.sh
@@ -27,5 +27,9 @@ fi
exec setsid nohup postgres >> ${PGLOG}/postgres.log 2>&1 &
if [ ! -f ${firstlaunch} ]; then
- psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard"
-fi
+ sleep 2
+ while ! psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard"
+ do
+ sleep 1
+ done
+fi
\ No newline at end of file
diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml
index f41a3afd1e..d1901a3e33 100644
--- a/msa/tb/pom.xml
+++ b/msa/tb/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml
index 0b3ab420e8..ad09511f36 100644
--- a/msa/transport/coap/pom.xml
+++ b/msa/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml
index 5621fd6bdc..97196bb879 100644
--- a/msa/transport/http/pom.xml
+++ b/msa/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml
index 24f8350706..79a26aeef3 100644
--- a/msa/transport/mqtt/pom.xml
+++ b/msa/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml
index e000241608..5a8b79d9d9 100644
--- a/msa/transport/pom.xml
+++ b/msa/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json
index d839f97a33..792926a86d 100644
--- a/msa/web-ui/package.json
+++ b/msa/web-ui/package.json
@@ -1,7 +1,7 @@
{
"name": "thingsboard-web-ui",
"private": true,
- "version": "3.2.0",
+ "version": "3.2.1",
"description": "ThingsBoard Web UI Microservice",
"main": "server.js",
"bin": "server.js",
diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml
index f9ef249ce1..2902ea1c85 100644
--- a/msa/web-ui/pom.xml
+++ b/msa/web-ui/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml
index 58524a1a08..e917ce23f7 100644
--- a/netty-mqtt/pom.xml
+++ b/netty-mqtt/pom.xml
@@ -19,11 +19,11 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
netty-mqtt
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
jar
Netty MQTT Client
diff --git a/pom.xml b/pom.xml
index 1bfa507196..62c16da7e2 100755
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
pom
Thingsboard
diff --git a/rest-client/pom.xml b/rest-client/pom.xml
index a7b97610d1..89f6b33a02 100644
--- a/rest-client/pom.xml
+++ b/rest-client/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
rest-client
diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
index 0a92d4b1a8..e79bb2b713 100644
--- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
+++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
@@ -109,6 +109,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
import org.thingsboard.server.common.data.security.model.SecuritySettings;
import org.thingsboard.server.common.data.security.model.UserPasswordPolicy;
+import org.thingsboard.server.common.data.sms.config.TestSmsRequest;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
@@ -218,7 +219,11 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
}
public void sendTestMail(AdminSettings adminSettings) {
- restTemplate.postForEntity(baseURL + "/api/admin/settings/testMail", adminSettings, AdminSettings.class);
+ restTemplate.postForLocation(baseURL + "/api/admin/settings/testMail", adminSettings);
+ }
+
+ public void sendTestSms(TestSmsRequest testSmsRequest) {
+ restTemplate.postForLocation(baseURL + "/api/admin/settings/testSms", testSmsRequest);
}
public Optional getSecuritySettings() {
@@ -1714,6 +1719,10 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
return restTemplate.postForEntity(baseURL + "/api/oauth2/config", oauth2Params, OAuth2ClientsParams.class).getBody();
}
+ public String getLoginProcessingUrl() {
+ return restTemplate.getForEntity(baseURL + "/api/oauth2/loginProcessingUrl", String.class).getBody();
+ }
+
public void handleOneWayDeviceRPCRequest(DeviceId deviceId, JsonNode requestBody) {
restTemplate.postForLocation(baseURL + "/api/plugins/rpc/oneway/{deviceId}", requestBody, deviceId.getId());
}
diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml
index 197c4e500d..43bd3859af 100644
--- a/rule-engine/pom.xml
+++ b/rule-engine/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
rule-engine
diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml
index 1a4c0b8506..448b5f8760 100644
--- a/rule-engine/rule-engine-api/pom.xml
+++ b/rule-engine/rule-engine-api/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
rule-engine
org.thingsboard.rule-engine
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java
index fb34383a9d..01b82931a6 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java
+++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java
@@ -15,7 +15,7 @@
*/
package org.thingsboard.rule.engine.api;
-import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest;
+import org.thingsboard.server.common.data.sms.config.TestSmsRequest;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
index eb494af569..8dd9add1bd 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
+++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
@@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.ApiUsageRecordKey;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
+import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.DeviceId;
@@ -237,7 +238,11 @@ public interface TbContext {
void clearRuleNodeStates();
+ void addTenantProfileListener(Consumer listener);
+
void addDeviceProfileListeners(Consumer listener, BiConsumer deviceListener);
- void removeProfileListener();
+ void removeListeners();
+
+ TenantProfile getTenantProfile();
}
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java
index 39daa48983..5930601c22 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java
+++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java
@@ -15,7 +15,7 @@
*/
package org.thingsboard.rule.engine.api.sms;
-import org.thingsboard.rule.engine.api.sms.config.SmsProviderConfiguration;
+import org.thingsboard.server.common.data.sms.config.SmsProviderConfiguration;
public interface SmsSenderFactory {
diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml
index 6253b39fc1..9fb02ec1f0 100644
--- a/rule-engine/rule-engine-components/pom.xml
+++ b/rule-engine/rule-engine-components/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
rule-engine
org.thingsboard.rule-engine
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java
index fa7538bce6..27852316af 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java
@@ -54,7 +54,8 @@ import java.util.concurrent.TimeUnit;
relationTypes = {"Alarm Created", "Alarm Updated", "Alarm Severity Updated", "Alarm Cleared", "Success", "Failure"},
configClazz = TbDeviceProfileNodeConfiguration.class,
nodeDescription = "Process device messages based on device profile settings",
- nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. Generates ",
+ nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. The output relation type is either " +
+ "'Alarm Created', 'Alarm Updated', 'Alarm Severity Updated' and 'Alarm Cleared' or simply 'Success' if no alarms were affected.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbDeviceProfileConfig"
)
@@ -119,7 +120,6 @@ public class TbDeviceProfileNode implements TbNode {
} else {
removeDeviceState(deviceId);
}
-
} else {
if (EntityType.DEVICE.equals(originatorType)) {
DeviceId deviceId = new DeviceId(msg.getOriginator().getId());
@@ -149,7 +149,7 @@ public class TbDeviceProfileNode implements TbNode {
@Override
public void destroy() {
- ctx.removeProfileListener();
+ ctx.removeListeners();
deviceStates.clear();
}
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java
index 14720aa342..7bbe1d9217 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java
@@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.sms;
import lombok.Data;
import org.thingsboard.rule.engine.api.NodeConfiguration;
-import org.thingsboard.rule.engine.api.sms.config.SmsProviderConfiguration;
+import org.thingsboard.server.common.data.sms.config.SmsProviderConfiguration;
@Data
public class TbSendSmsNodeConfiguration implements NodeConfiguration {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java
index a415e08695..e803392d5b 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java
@@ -24,6 +24,7 @@ import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
+import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
@@ -31,10 +32,12 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
+import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
@Slf4j
@RuleNode(
@@ -50,10 +53,20 @@ import java.util.Map;
public class TbMsgTimeseriesNode implements TbNode {
private TbMsgTimeseriesNodeConfiguration config;
+ private TbContext ctx;
+ private long tenantProfileDefaultStorageTtl;
@Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
this.config = TbNodeUtils.convert(configuration, TbMsgTimeseriesNodeConfiguration.class);
+ this.ctx = ctx;
+ ctx.addTenantProfileListener(this::onTenantProfileUpdate);
+ onTenantProfileUpdate(ctx.getTenantProfile());
+ }
+
+ void onTenantProfileUpdate(TenantProfile tenantProfile) {
+ DefaultTenantProfileConfiguration configuration = (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration();
+ tenantProfileDefaultStorageTtl = TimeUnit.DAYS.toSeconds(configuration.getDefaultStorageTtlDays());
}
@Override
@@ -77,6 +90,9 @@ public class TbMsgTimeseriesNode implements TbNode {
}
String ttlValue = msg.getMetaData().getValue("TTL");
long ttl = !StringUtils.isEmpty(ttlValue) ? Long.parseLong(ttlValue) : config.getDefaultTTL();
+ if (ttl == 0L) {
+ ttl = tenantProfileDefaultStorageTtl;
+ }
ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), tsKvEntryList, ttl, new TelemetryNodeCallback(ctx, msg));
}
@@ -96,6 +112,7 @@ public class TbMsgTimeseriesNode implements TbNode {
@Override
public void destroy() {
+ ctx.removeListeners();
}
}
diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java
index ae6bd7ebbd..39c16247fa 100644
--- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java
+++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java
@@ -23,17 +23,13 @@ import org.junit.runner.RunWith;
import org.mockito.AdditionalAnswers;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
-import org.springframework.util.StringUtils;
import org.thingsboard.rule.engine.api.RuleEngineAlarmService;
import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.server.common.data.DeviceProfile;
-import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.device.profile.AlarmCondition;
import org.thingsboard.server.common.data.device.profile.AlarmRule;
@@ -52,11 +48,10 @@ import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.session.SessionMsgType;
-import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.timeseries.TimeseriesService;
import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.TreeMap;
import java.util.UUID;
import static org.mockito.Mockito.verify;
@@ -140,7 +135,7 @@ public class TbDeviceProfileNodeTest {
DeviceProfileAlarm dpa = new DeviceProfileAlarm();
dpa.setId("highTemperatureAlarmID");
dpa.setAlarmType("highTemperatureAlarm");
- dpa.setCreateRules(new LinkedHashMap<>(Collections.singletonMap(AlarmSeverity.CRITICAL, alarmRule)));
+ dpa.setCreateRules(new TreeMap<>(Collections.singletonMap(AlarmSeverity.CRITICAL, alarmRule)));
KeyFilter lowTempFilter = new KeyFilter();
lowTempFilter.setKey(new EntityKey(EntityKeyType.TIME_SERIES, "temperature"));
diff --git a/tools/pom.xml b/tools/pom.xml
index 14fd8b01b7..b3fce1373f 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
tools
diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml
index 1b7abf06db..94cb8e88a9 100644
--- a/transport/coap/pom.xml
+++ b/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/http/pom.xml b/transport/http/pom.xml
index f5ae869c75..59cfef95f0 100644
--- a/transport/http/pom.xml
+++ b/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml
index a1a45f54b8..b2ba041e0b 100644
--- a/transport/mqtt/pom.xml
+++ b/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/pom.xml b/transport/pom.xml
index 429c953a46..d477fc7de2 100644
--- a/transport/pom.xml
+++ b/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
transport
diff --git a/ui-ngx/package.json b/ui-ngx/package.json
index 8e3ede2934..bf05109bb6 100644
--- a/ui-ngx/package.json
+++ b/ui-ngx/package.json
@@ -1,6 +1,6 @@
{
"name": "thingsboard",
- "version": "3.2.0",
+ "version": "3.2.1",
"scripts": {
"ng": "ng",
"start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --host 0.0.0.0 --open",
diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml
index 14b9317e4a..0420401dbe 100644
--- a/ui-ngx/pom.xml
+++ b/ui-ngx/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.2.0-SNAPSHOT
+ 3.2.1-SNAPSHOT
thingsboard
org.thingsboard
diff --git a/ui-ngx/src/app/core/auth/auth.service.ts b/ui-ngx/src/app/core/auth/auth.service.ts
index 1f8788d821..3d4a203252 100644
--- a/ui-ngx/src/app/core/auth/auth.service.ts
+++ b/ui-ngx/src/app/core/auth/auth.service.ts
@@ -282,8 +282,7 @@ export class AuthService {
if (publicId) {
return this.publicLogin(publicId).pipe(
mergeMap((response) => {
- this.updateAndValidateToken(response.token, 'jwt_token', false);
- this.updateAndValidateToken(response.refreshToken, 'refresh_token', false);
+ this.updateAndValidateTokens(response.token, response.refreshToken, false);
return this.procceedJwtTokenValidate();
}),
catchError((err) => {
@@ -317,8 +316,7 @@ export class AuthService {
};
return this.http.post('/api/auth/login', loginRequest, defaultHttpOptions()).pipe(
mergeMap((loginResponse: LoginResponse) => {
- this.updateAndValidateToken(loginResponse.token, 'jwt_token', false);
- this.updateAndValidateToken(loginResponse.refreshToken, 'refresh_token', false);
+ this.updateAndValidateTokens(loginResponse.token, loginResponse.refreshToken, false);
return this.procceedJwtTokenValidate();
}
)
@@ -439,7 +437,7 @@ export class AuthService {
}));
}
- public refreshJwtToken(): Observable {
+ public refreshJwtToken(loadUserElseStoreJwtToken = true): Observable {
let response: Observable = this.refreshTokenSubject;
if (this.refreshTokenSubject === null) {
this.refreshTokenSubject = new ReplaySubject(1);
@@ -456,7 +454,11 @@ export class AuthService {
};
const refreshObservable = this.http.post('/api/auth/token', refreshTokenRequest, defaultHttpOptions());
refreshObservable.subscribe((loginResponse: LoginResponse) => {
- this.setUserFromJwtToken(loginResponse.token, loginResponse.refreshToken, false);
+ if (loadUserElseStoreJwtToken) {
+ this.setUserFromJwtToken(loginResponse.token, loginResponse.refreshToken, false);
+ } else {
+ this.updateAndValidateTokens(loginResponse.token, loginResponse.refreshToken, true);
+ }
this.refreshTokenSubject.next(loginResponse);
this.refreshTokenSubject.complete();
this.refreshTokenSubject = null;
@@ -474,7 +476,7 @@ export class AuthService {
const subject = new ReplaySubject();
if (!AuthService.isTokenValid('jwt_token')) {
if (doRefresh) {
- this.refreshJwtToken().subscribe(
+ this.refreshJwtToken(!doRefresh).subscribe(
() => {
subject.next();
subject.complete();
@@ -505,8 +507,7 @@ export class AuthService {
this.notifyUnauthenticated();
}
} else {
- this.updateAndValidateToken(jwtToken, 'jwt_token', true);
- this.updateAndValidateToken(refreshToken, 'refresh_token', true);
+ this.updateAndValidateTokens(jwtToken, refreshToken, true);
if (notify) {
this.notifyUserLoaded(false);
this.loadUser(false).subscribe(
@@ -525,6 +526,11 @@ export class AuthService {
}
}
+ private updateAndValidateTokens(jwtToken, refreshToken, notify: boolean) {
+ this.updateAndValidateToken(jwtToken, 'jwt_token', notify);
+ this.updateAndValidateToken(refreshToken, 'refresh_token', notify);
+ }
+
public parsePublicId(): string {
const token = AuthService.getJwtToken();
if (token) {
diff --git a/ui-ngx/src/app/core/http/dashboard.service.ts b/ui-ngx/src/app/core/http/dashboard.service.ts
index 42ba3834c9..61435747b3 100644
--- a/ui-ngx/src/app/core/http/dashboard.service.ts
+++ b/ui-ngx/src/app/core/http/dashboard.service.ts
@@ -130,7 +130,7 @@ export class DashboardService {
const publicCustomerId = publicCustomers[0].customerId.id;
let url = this.window.location.protocol + '//' + this.window.location.hostname;
const port = this.window.location.port;
- if (port !== '80' && port !== '443') {
+ if (port && port.length > 0 && port !== '80' && port !== '443') {
url += ':' + port;
}
url += `/dashboard/${dashboard.id.id}?publicId=${publicCustomerId}`;
diff --git a/ui-ngx/src/app/core/services/menu.models.ts b/ui-ngx/src/app/core/services/menu.models.ts
index 028a0f5380..ad29c17258 100644
--- a/ui-ngx/src/app/core/services/menu.models.ts
+++ b/ui-ngx/src/app/core/services/menu.models.ts
@@ -23,6 +23,7 @@ export interface MenuSection extends HasUUID{
type: MenuSectionType;
path: string;
icon: string;
+ notExact?: boolean;
isMdiIcon?: boolean;
height?: string;
pages?: Array;
diff --git a/ui-ngx/src/app/core/services/menu.service.ts b/ui-ngx/src/app/core/services/menu.service.ts
index e30d993d92..6184050142 100644
--- a/ui-ngx/src/app/core/services/menu.service.ts
+++ b/ui-ngx/src/app/core/services/menu.service.ts
@@ -288,6 +288,14 @@ export class MenuService {
type: 'link',
path: '/auditLogs',
icon: 'track_changes'
+ },
+ {
+ id: guid(),
+ name: 'api-usage.api-usage',
+ type: 'link',
+ path: '/usage',
+ icon: 'insert_chart',
+ notExact: true
}
);
return sections;
@@ -374,6 +382,11 @@ export class MenuService {
name: 'audit-log.audit-logs',
icon: 'track_changes',
path: '/auditLogs'
+ },
+ {
+ name: 'api-usage.api-usage',
+ icon: 'insert_chart',
+ path: '/usage'
}
]
}
diff --git a/ui-ngx/src/app/core/services/utils.service.ts b/ui-ngx/src/app/core/services/utils.service.ts
index 3613c0f484..faaee28a80 100644
--- a/ui-ngx/src/app/core/services/utils.service.ts
+++ b/ui-ngx/src/app/core/services/utils.service.ts
@@ -21,17 +21,18 @@ import { Inject, Injectable, NgZone } from '@angular/core';
import { WINDOW } from '@core/services/window.service';
import { ExceptionData } from '@app/shared/models/error.models';
import {
+ baseUrl,
createLabelFromDatasource,
deepClone,
deleteNullProperties,
guid,
isDefined,
- isDefinedAndNotNull,
+ isDefinedAndNotNull, isString,
isUndefined
} from '@core/utils';
import { WindowMessage } from '@shared/models/window-message.model';
import { TranslateService } from '@ngx-translate/core';
-import { customTranslationsPrefix } from '@app/shared/models/constants';
+import { customTranslationsPrefix, i18nPrefix } from '@app/shared/models/constants';
import { DataKey, Datasource, DatasourceType, KeyInfo } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models';
import { DataKeyType } from '@app/shared/models/telemetry/telemetry.models';
@@ -42,6 +43,8 @@ import jsonSchemaDefaults from 'json-schema-defaults';
import materialIconsCodepoints from '!raw-loader!material-design-icons/iconfont/codepoints';
import { Observable, of, ReplaySubject } from 'rxjs';
+const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g');
+
const predefinedFunctions: { [func: string]: string } = {
Sin: 'return Math.round(1000*Math.sin(time/5000));',
Cos: 'return Math.round(1000*Math.cos(time/5000));',
@@ -107,8 +110,8 @@ export class UtilsService {
materialIcons: Array = [];
constructor(@Inject(WINDOW) private window: Window,
- private zone: NgZone,
- private translate: TranslateService) {
+ private zone: NgZone,
+ private translate: TranslateService) {
let frame: Element = null;
try {
frame = window.frameElement;
@@ -221,8 +224,31 @@ export class UtilsService {
}
public customTranslation(translationValue: string, defaultValue: string): string {
+ if (translationValue && isString(translationValue)) {
+ if (translationValue.includes(`{${i18nPrefix}`)) {
+ const matches = translationValue.match(i18nRegExp);
+ let result = translationValue;
+ for (const match of matches) {
+ const translationId = match.substring(6, match.length - 1);
+ result = result.replace(match, this.doTranslate(translationId, match));
+ }
+ return result;
+ } else {
+ return this.doTranslate(translationValue, defaultValue, customTranslationsPrefix);
+ }
+ } else {
+ return translationValue;
+ }
+ }
+
+ private doTranslate(translationValue: string, defaultValue: string, prefix?: string): string {
let result: string;
- const translationId = customTranslationsPrefix + translationValue;
+ let translationId;
+ if (prefix) {
+ translationId = prefix + translationValue;
+ } else {
+ translationId = translationValue;
+ }
const translation = this.translate.instant(translationId);
if (translation !== translationId) {
result = translation + '';
@@ -384,7 +410,7 @@ export class UtilsService {
}
public updateQueryParam(name: string, value: string | null) {
- const baseUrl = [this.window.location.protocol, '//', this.window.location.host, this.window.location.pathname].join('');
+ const baseUrlPart = [baseUrl(), this.window.location.pathname].join('');
const urlQueryString = this.window.location.search;
let newParam = '';
let params = '';
@@ -404,7 +430,11 @@ export class UtilsService {
} else if (newParam) {
params = '?' + newParam;
}
- this.window.history.replaceState({}, '', baseUrl + params);
+ this.window.history.replaceState({}, '', baseUrlPart + params);
+ }
+
+ public baseUrl(): string {
+ return baseUrl();
}
public deepClone(target: T, ignoreFields?: string[]): T {
diff --git a/ui-ngx/src/app/core/utils.ts b/ui-ngx/src/app/core/utils.ts
index bf58d8c2c8..862e3a5bfd 100644
--- a/ui-ngx/src/app/core/utils.ts
+++ b/ui-ngx/src/app/core/utils.ts
@@ -385,6 +385,15 @@ export function padValue(val: any, dec: number): string {
return strVal;
}
+export function baseUrl(): string {
+ let url = window.location.protocol + '//' + window.location.hostname;
+ const port = window.location.port;
+ if (port && port.length > 0 && port !== '80' && port !== '443') {
+ url += ':' + port;
+ }
+ return url;
+}
+
export function sortObjectKeys(obj: T): T {
return Object.keys(obj).sort().reduce((acc, key) => {
acc[key] = obj[key];
diff --git a/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts
index 99b4a82960..1297802fc3 100644
--- a/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts
+++ b/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts
@@ -14,12 +14,12 @@
/// limitations under the License.
///
-import { Component, Input, OnDestroy, OnInit } from '@angular/core';
+import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { EntityId } from '@shared/models/id/entity-id';
import { DeviceService } from '@core/http/device.service';
import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models';
import { isDefinedAndNotNull, isEqual } from '@core/utils';
-import { BehaviorSubject, Subject } from 'rxjs';
+import { BehaviorSubject, Subject, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, mergeMap, tap } from 'rxjs/operators';
import { EntityType } from '@shared/models/entity-type.models';
import { ActionNotificationShow } from '@core/notification/notification.actions';
@@ -32,12 +32,10 @@ import { TranslateService } from '@ngx-translate/core';
templateUrl: './copy-device-credentials.component.html',
styleUrls: []
})
-export class CopyDeviceCredentialsComponent implements OnDestroy {
+export class CopyDeviceCredentialsComponent implements OnInit, OnDestroy {
private deviceId$ = new BehaviorSubject(null);
- private credentials$ = new Subject();
-
private tooltipMessage: string;
public hideButton = true;
@@ -56,13 +54,14 @@ export class CopyDeviceCredentialsComponent implements OnDestroy {
@Input() disabled: boolean;
@Input()
- set credentials(credential: DeviceCredentials) {
- this.credentials$.next(credential);
- }
+ credentials$: Subject;
+
+ private credentialsSubscription: Subscription = null;
constructor(private store: Store,
private translate: TranslateService,
- private deviceService: DeviceService
+ private deviceService: DeviceService,
+ private cd: ChangeDetectorRef
) {
this.deviceId$.pipe(
filter(device => isDefinedAndNotNull(device) && device.entityType === EntityType.DEVICE),
@@ -73,19 +72,23 @@ export class CopyDeviceCredentialsComponent implements OnDestroy {
this.processingValue(deviceCredentials);
this.loading = false;
});
+ }
- this.credentials$.pipe(
+ ngOnInit(): void {
+ this.credentialsSubscription = this.credentials$.pipe(
filter(credential => isDefinedAndNotNull(credential)),
distinctUntilChanged((prev, curr) => isEqual(prev, curr))
).subscribe(deviceCredentials => {
- console.warn(deviceCredentials);
this.processingValue(deviceCredentials);
+ this.cd.detectChanges();
});
}
ngOnDestroy(): void {
this.deviceId$.unsubscribe();
- this.credentials$.unsubscribe();
+ if (this.credentialsSubscription !== null) {
+ this.credentialsSubscription.unsubscribe();
+ }
}
private processingValue(credential: DeviceCredentials): void {
@@ -125,4 +128,5 @@ export class CopyDeviceCredentialsComponent implements OnDestroy {
horizontalPosition: 'right'
}));
}
+
}
diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html
index 3468442b50..a803f4ad53 100644
--- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html
+++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html
@@ -44,8 +44,6 @@
{{ 'device-profile.alarm-type-unique' | translate }}
-
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
index fa0029b46f..bc31b653b5 100644
--- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
+++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
@@ -148,6 +148,18 @@
{{ 'tenant-profile.max-d-p-storage-days-range' | translate}}
+
+ tenant-profile.default-storage-ttl-days
+
+
+ {{ 'tenant-profile.default-storage-ttl-days-required' | translate}}
+
+
+ {{ 'tenant-profile.default-storage-ttl-days-range' | translate}}
+
+
tenant-profile.max-rule-node-executions-per-message
{
this.updateModel();
diff --git a/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts b/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts
index 6539780e02..e15fc7f0eb 100644
--- a/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts
@@ -71,7 +71,7 @@ const customPrettyActionCompletions: TbEditorCompletions = {
}
},
...customActionCompletions
-}
+};
export const CustomActionEditorCompleter = new TbEditorCompleter(customActionCompletions);
export const CustomPrettyActionEditorCompleter = new TbEditorCompleter(customPrettyActionCompletions);
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html
index d269fbbe92..54ddd6fc80 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html
@@ -61,7 +61,7 @@
-
@@ -96,7 +96,7 @@
width: (actionCellDescriptors.length * 40) + 'px' }">
-
-
{{ column.title }}
@@ -57,7 +57,7 @@
width: (actionCellDescriptors.length * 40) + 'px' }">
- | | |