Browse Source

Merge branch 'master' into feature/dynamic-oauth2-new-table

# Conflicts:
#	common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
pull/3557/head
vzikratyi 6 years ago
parent
commit
985e0350d8
  1. 21
      application/src/main/data/json/tenant/rule_chains/root_rule_chain.json
  2. 0
      application/src/main/data/upgrade/3.1.1/schema_update_after.sql
  3. 0
      application/src/main/data/upgrade/3.1.1/schema_update_before.sql
  4. 24
      application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
  5. 4
      application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
  6. 7
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  7. 6
      application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
  8. 130
      application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java
  9. 2
      application/src/main/java/org/thingsboard/server/service/profile/DefaultTbDeviceProfileCache.java
  10. 7
      application/src/main/resources/thingsboard.yml
  11. 30
      application/src/test/java/org/thingsboard/server/mqtt/AbstractMqttIntegrationTest.java
  12. 8
      application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestIntegrationTest.java
  13. 9
      application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/AbstractMqttAttributesUpdatesIntegrationTest.java
  14. 35
      application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimDeviceTest.java
  15. 1
      application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimJsonDeviceTest.java
  16. 4
      application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimProtoDeviceTest.java
  17. 24
      application/src/test/java/org/thingsboard/server/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java
  18. 15
      application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/AbstractMqttAttributesIntegrationTest.java
  19. 23
      application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java
  20. 6
      application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesJsonIntegrationTest.java
  21. 5
      application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesProtoIntegrationTest.java
  22. 2
      common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
  23. 4
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java
  24. 4
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
  25. 51
      dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java
  26. 10
      dao/src/main/java/org/thingsboard/server/dao/util/mapping/JacksonUtil.java
  27. 4
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java
  28. 2
      rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js
  29. 2
      transport/mqtt/src/main/resources/tb-mqtt-transport.yml
  30. 4
      ui-ngx/e2e/tsconfig.e2e.json
  31. 2
      ui-ngx/extra-webpack.config.js
  32. 86
      ui-ngx/package.json
  33. 4
      ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.html
  34. 1
      ui-ngx/src/app/modules/home/components/details-panel.component.scss
  35. 1
      ui-ngx/src/app/modules/home/components/filter/filter-text.component.scss
  36. 2
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.scss
  37. 1
      ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.scss
  38. 1
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.scss
  39. 2
      ui-ngx/src/app/modules/home/components/widget/widget.component.html
  40. 2
      ui-ngx/src/app/modules/home/home.component.ts
  41. 1
      ui-ngx/src/app/modules/home/menu/side-menu.component.scss
  42. 4
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-widget-select.component.html
  43. 2
      ui-ngx/src/app/modules/home/pages/dashboard/layout/dashboard-layout.component.html
  44. 1
      ui-ngx/src/app/modules/home/pages/home-links/home-links.component.scss
  45. 1
      ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.scss
  46. 4
      ui-ngx/src/app/modules/home/pages/widget/widget-library.component.html
  47. 1
      ui-ngx/src/app/modules/login/pages/login/login.component.scss
  48. 1
      ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.scss
  49. 5
      ui-ngx/src/app/shared/components/json-form/react/json-form.scss
  50. 1
      ui-ngx/src/app/shared/components/kv-map.component.scss
  51. 2
      ui-ngx/src/app/shared/components/logo.component.ts
  52. 4
      ui-ngx/src/app/shared/components/nav-tree.component.ts
  53. 10
      ui-ngx/src/styles.scss
  54. 2
      ui-ngx/src/tsconfig.app.json
  55. 2
      ui-ngx/src/tsconfig.spec.json
  56. 45
      ui-ngx/tsconfig.base.json
  57. 61
      ui-ngx/tsconfig.json
  58. 2040
      ui-ngx/yarn.lock

21
application/src/main/data/json/tenant/rule_chains/root_rule_chain.json

@ -8,7 +8,7 @@
"configuration": null "configuration": null
}, },
"metadata": { "metadata": {
"firstNodeIndex": 2, "firstNodeIndex": 6,
"nodes": [ "nodes": [
{ {
"additionalInfo": { "additionalInfo": {
@ -82,9 +82,28 @@
"configuration": { "configuration": {
"timeoutInSeconds": 60 "timeoutInSeconds": 60
} }
},
{
"additionalInfo": {
"description": "Process incoming messages from devices with the alarm rules defined in the device profile. Dispatch all incoming messages with \"Success\" relation type.",
"layoutX": 204,
"layoutY": 240
},
"type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode",
"name": "Device Profile Node",
"debugMode": false,
"configuration": {
"persistAlarmRulesState": false,
"fetchAlarmRulesStateOnStart": false
}
} }
], ],
"connections": [ "connections": [
{
"fromIndex": 6,
"toIndex": 2,
"type": "Success"
},
{ {
"fromIndex": 2, "fromIndex": 2,
"toIndex": 4, "toIndex": 4,

0
application/src/main/data/upgrade/3.1.2/schema_update_after.sql → application/src/main/data/upgrade/3.1.1/schema_update_after.sql

0
application/src/main/data/upgrade/3.1.2/schema_update_before.sql → application/src/main/data/upgrade/3.1.1/schema_update_before.sql

24
application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java

@ -125,7 +125,7 @@ class DefaultTbContext implements TbContext {
@Override @Override
public void enqueue(TbMsg tbMsg, String queueName, Runnable onSuccess, Consumer<Throwable> onFailure) { public void enqueue(TbMsg tbMsg, String queueName, Runnable onSuccess, Consumer<Throwable> onFailure) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg, queueName);
enqueue(tpi, tbMsg, onFailure, onSuccess); enqueue(tpi, tbMsg, onFailure, onSuccess);
} }
@ -142,46 +142,54 @@ class DefaultTbContext implements TbContext {
@Override @Override
public void enqueueForTellFailure(TbMsg tbMsg, String failureMessage) { public void enqueueForTellFailure(TbMsg tbMsg, String failureMessage) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg);
enqueueForTellNext(tpi, tbMsg, Collections.singleton(TbRelationTypes.FAILURE), failureMessage, null, null); enqueueForTellNext(tpi, tbMsg, Collections.singleton(TbRelationTypes.FAILURE), failureMessage, null, null);
} }
@Override @Override
public void enqueueForTellNext(TbMsg tbMsg, String relationType) { public void enqueueForTellNext(TbMsg tbMsg, String relationType) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg);
enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, null, null); enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, null, null);
} }
@Override @Override
public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes) { public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg);
enqueueForTellNext(tpi, tbMsg, relationTypes, null, null, null); enqueueForTellNext(tpi, tbMsg, relationTypes, null, null, null);
} }
@Override @Override
public void enqueueForTellNext(TbMsg tbMsg, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) { public void enqueueForTellNext(TbMsg tbMsg, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg);
enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, onSuccess, onFailure); enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, onSuccess, onFailure);
} }
@Override @Override
public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg);
enqueueForTellNext(tpi, tbMsg, relationTypes, null, onSuccess, onFailure); enqueueForTellNext(tpi, tbMsg, relationTypes, null, onSuccess, onFailure);
} }
@Override @Override
public void enqueueForTellNext(TbMsg tbMsg, String queueName, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) { public void enqueueForTellNext(TbMsg tbMsg, String queueName, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg, queueName);
enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, onSuccess, onFailure); enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, onSuccess, onFailure);
} }
@Override @Override
public void enqueueForTellNext(TbMsg tbMsg, String queueName, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { public void enqueueForTellNext(TbMsg tbMsg, String queueName, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) {
TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator()); TopicPartitionInfo tpi = resolvePartition(tbMsg, queueName);
enqueueForTellNext(tpi, tbMsg, relationTypes, null, onSuccess, onFailure); enqueueForTellNext(tpi, tbMsg, relationTypes, null, onSuccess, onFailure);
} }
private TopicPartitionInfo resolvePartition(TbMsg tbMsg, String queueName) {
return mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator());
}
private TopicPartitionInfo resolvePartition(TbMsg tbMsg) {
return resolvePartition(tbMsg, tbMsg.getQueueName());
}
private void enqueueForTellNext(TopicPartitionInfo tpi, TbMsg source, Set<String> relationTypes, String failureMessage, Runnable onSuccess, Consumer<Throwable> onFailure) { private void enqueueForTellNext(TopicPartitionInfo tpi, TbMsg source, Set<String> relationTypes, String failureMessage, Runnable onSuccess, Consumer<Throwable> onFailure) {
RuleChainId ruleChainId = nodeCtx.getSelf().getRuleChainId(); RuleChainId ruleChainId = nodeCtx.getSelf().getRuleChainId();
RuleNodeId ruleNodeId = nodeCtx.getSelf().getId(); RuleNodeId ruleNodeId = nodeCtx.getSelf().getId();

4
application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java

@ -47,6 +47,7 @@ import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
import org.thingsboard.server.common.msg.queue.RuleEngineException; import org.thingsboard.server.common.msg.queue.RuleEngineException;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -116,6 +117,9 @@ public class TenantActor extends RuleChainManagerActor {
if (msg.getMsgType().equals(MsgType.QUEUE_TO_RULE_ENGINE_MSG)) { if (msg.getMsgType().equals(MsgType.QUEUE_TO_RULE_ENGINE_MSG)) {
QueueToRuleEngineMsg queueMsg = (QueueToRuleEngineMsg) msg; QueueToRuleEngineMsg queueMsg = (QueueToRuleEngineMsg) msg;
queueMsg.getTbMsg().getCallback().onSuccess(); queueMsg.getTbMsg().getCallback().onSuccess();
} else if (msg.getMsgType().equals(MsgType.TRANSPORT_TO_DEVICE_ACTOR_MSG)){
TransportToDeviceActorMsgWrapper transportMsg = (TransportToDeviceActorMsgWrapper) msg;
transportMsg.getCallback().onSuccess();
} }
return true; return true;
} }

7
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -176,13 +176,12 @@ public class ThingsboardInstallService {
log.info("Upgrading ThingsBoard from version 3.1.0 to 3.1.1 ..."); log.info("Upgrading ThingsBoard from version 3.1.0 to 3.1.1 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.1.0"); databaseEntitiesUpgradeService.upgradeDatabase("3.1.0");
case "3.1.1": case "3.1.1":
log.info("Upgrading ThingsBoard from version 3.1.1 to 3.1.2 ..."); log.info("Upgrading ThingsBoard from version 3.1.1 to 3.2.0 ...");
if (databaseTsUpgradeService != null) { if (databaseTsUpgradeService != null) {
databaseTsUpgradeService.upgradeDatabase("3.1.1"); databaseTsUpgradeService.upgradeDatabase("3.1.1");
} }
case "3.1.2": databaseEntitiesUpgradeService.upgradeDatabase("3.1.1");
log.info("Upgrading ThingsBoard from version 3.1.2 to 3.2.0 ..."); dataUpdateService.updateData("3.1.1");
databaseEntitiesUpgradeService.upgradeDatabase("3.1.2");
log.info("Updating system data..."); log.info("Updating system data...");
systemDataLoaderService.updateSystemWidgets(); systemDataLoaderService.updateSystemWidgets();
systemDataLoaderService.createOAuth2Templates(); systemDataLoaderService.createOAuth2Templates();

6
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java

@ -324,7 +324,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.info("Schema updated."); log.info("Schema updated.");
} }
break; break;
case "3.1.2": case "3.1.1":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
log.info("Updating schema ..."); log.info("Updating schema ...");
if (isOldSchema(conn, 3001000)) { if (isOldSchema(conn, 3001000)) {
@ -352,7 +352,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
} catch (Exception e) { } catch (Exception e) {
} }
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.2", "schema_update_before.sql"); schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.1", "schema_update_before.sql");
loadSql(schemaUpdateFile, conn); loadSql(schemaUpdateFile, conn);
log.info("Creating default tenant profiles..."); log.info("Creating default tenant profiles...");
@ -385,7 +385,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.info("Updating device profiles..."); log.info("Updating device profiles...");
conn.createStatement().execute("call update_device_profiles()"); conn.createStatement().execute("call update_device_profiles()");
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.2", "schema_update_after.sql"); schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.1", "schema_update_after.sql");
loadSql(schemaUpdateFile, conn); loadSql(schemaUpdateFile, conn);
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3002000;"); conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3002000;");

130
application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java

@ -15,6 +15,8 @@
*/ */
package org.thingsboard.server.service.install.update; package org.thingsboard.server.service.install.update;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -23,9 +25,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration;
import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.SearchTextBased; import org.thingsboard.server.common.data.SearchTextBased;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.id.UUIDBased;
@ -35,10 +41,13 @@ import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import org.thingsboard.server.service.install.InstallScripts; import org.thingsboard.server.service.install.InstallScripts;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -49,6 +58,7 @@ import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.apache.commons.lang.StringUtils.isBlank; import static org.apache.commons.lang.StringUtils.isBlank;
import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper;
@Service @Service
@Profile("install") @Profile("install")
@ -81,6 +91,10 @@ public class DefaultDataUpdateService implements DataUpdateService {
log.info("Updating data from version 3.0.1 to 3.1.0 ..."); log.info("Updating data from version 3.0.1 to 3.1.0 ...");
tenantsEntityViewsUpdater.updateEntities(null); tenantsEntityViewsUpdater.updateEntities(null);
break; break;
case "3.1.1":
log.info("Updating data from version 3.1.1 to 3.2.0 ...");
tenantsRootRuleChainUpdater.updateEntities(null);
break;
default: default:
throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion);
} }
@ -107,6 +121,60 @@ public class DefaultDataUpdateService implements DataUpdateService {
} }
}; };
private PaginatedUpdater<String, Tenant> tenantsRootRuleChainUpdater =
new PaginatedUpdater<String, Tenant>() {
@Override
protected PageData<Tenant> findEntities(String region, PageLink pageLink) {
return tenantService.findTenants(pageLink);
}
@Override
protected void updateEntity(Tenant tenant) {
try {
RuleChain ruleChain = ruleChainService.getRootTenantRuleChain(tenant.getId());
if (ruleChain == null) {
installScripts.createDefaultRuleChains(tenant.getId());
} else {
RuleChainMetaData md = ruleChainService.loadRuleChainMetaData(tenant.getId(), ruleChain.getId());
int oldIdx = md.getFirstNodeIndex();
int newIdx = md.getNodes().size();
if (md.getNodes().size() < oldIdx) {
// Skip invalid rule chains
return;
}
RuleNode oldFirstNode = md.getNodes().get(oldIdx);
if (oldFirstNode.getType().equals(TbDeviceProfileNode.class.getName())) {
// No need to update the rule node twice.
return;
}
RuleNode ruleNode = new RuleNode();
ruleNode.setRuleChainId(ruleChain.getId());
ruleNode.setName("Device Profile Node");
ruleNode.setType(TbDeviceProfileNode.class.getName());
ruleNode.setDebugMode(false);
TbDeviceProfileNodeConfiguration ruleNodeConfiguration = new TbDeviceProfileNodeConfiguration().defaultConfiguration();
ruleNode.setConfiguration(JacksonUtil.valueToTree(ruleNodeConfiguration));
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
additionalInfo.put("description", "Process incoming messages from devices with the alarm rules defined in the device profile. Dispatch all incoming messages with \"Success\" relation type.");
additionalInfo.put("layoutX", 204);
additionalInfo.put("layoutY", 240);
ruleNode.setAdditionalInfo(additionalInfo);
md.getNodes().add(ruleNode);
md.setFirstNodeIndex(newIdx);
md.addConnectionInfo(newIdx, oldIdx, "Success");
ruleChainService.saveRuleChainMetaData(tenant.getId(), md);
}
} catch (Exception e) {
log.error("Unable to update Tenant", e);
}
}
};
private PaginatedUpdater<String, Tenant> tenantsEntityViewsUpdater = private PaginatedUpdater<String, Tenant> tenantsEntityViewsUpdater =
new PaginatedUpdater<String, Tenant>() { new PaginatedUpdater<String, Tenant>() {
@ -121,30 +189,30 @@ public class DefaultDataUpdateService implements DataUpdateService {
} }
}; };
private void updateTenantEntityViews(TenantId tenantId) { private void updateTenantEntityViews(TenantId tenantId) {
PageLink pageLink = new PageLink(100); PageLink pageLink = new PageLink(100);
PageData<EntityView> pageData = entityViewService.findEntityViewByTenantId(tenantId, pageLink); PageData<EntityView> pageData = entityViewService.findEntityViewByTenantId(tenantId, pageLink);
boolean hasNext = true; boolean hasNext = true;
while (hasNext) { while (hasNext) {
List<ListenableFuture<List<Void>>> updateFutures = new ArrayList<>(); List<ListenableFuture<List<Void>>> updateFutures = new ArrayList<>();
for (EntityView entityView : pageData.getData()) { for (EntityView entityView : pageData.getData()) {
updateFutures.add(updateEntityViewLatestTelemetry(entityView)); updateFutures.add(updateEntityViewLatestTelemetry(entityView));
} }
try { try {
Futures.allAsList(updateFutures).get(); Futures.allAsList(updateFutures).get();
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException e) {
log.error("Failed to copy latest telemetry to entity view", e); log.error("Failed to copy latest telemetry to entity view", e);
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
pageData = entityViewService.findEntityViewByTenantId(tenantId, pageLink); pageData = entityViewService.findEntityViewByTenantId(tenantId, pageLink);
} else { } else {
hasNext = false; hasNext = false;
} }
} }
} }
private ListenableFuture<List<Void>> updateEntityViewLatestTelemetry(EntityView entityView) { private ListenableFuture<List<Void>> updateEntityViewLatestTelemetry(EntityView entityView) {
EntityViewId entityId = entityView.getId(); EntityViewId entityId = entityView.getId();
@ -160,13 +228,13 @@ public class DefaultDataUpdateService implements DataUpdateService {
keysFuture = Futures.immediateFuture(keys); keysFuture = Futures.immediateFuture(keys);
} }
ListenableFuture<List<TsKvEntry>> latestFuture = Futures.transformAsync(keysFuture, fetchKeys -> { ListenableFuture<List<TsKvEntry>> latestFuture = Futures.transformAsync(keysFuture, fetchKeys -> {
List<ReadTsKvQuery> queries = fetchKeys.stream().filter(key -> !isBlank(key)).map(key -> new BaseReadTsKvQuery(key, startTs, endTs, 1, "DESC")).collect(Collectors.toList()); List<ReadTsKvQuery> queries = fetchKeys.stream().filter(key -> !isBlank(key)).map(key -> new BaseReadTsKvQuery(key, startTs, endTs, 1, "DESC")).collect(Collectors.toList());
if (!queries.isEmpty()) { if (!queries.isEmpty()) {
return tsService.findAll(TenantId.SYS_TENANT_ID, entityView.getEntityId(), queries); return tsService.findAll(TenantId.SYS_TENANT_ID, entityView.getEntityId(), queries);
} else { } else {
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
}, MoreExecutors.directExecutor()); }, MoreExecutors.directExecutor());
return Futures.transformAsync(latestFuture, latestValues -> { return Futures.transformAsync(latestFuture, latestValues -> {
if (latestValues != null && !latestValues.isEmpty()) { if (latestValues != null && !latestValues.isEmpty()) {
ListenableFuture<List<Void>> saveFuture = tsService.saveLatest(TenantId.SYS_TENANT_ID, entityId, latestValues); ListenableFuture<List<Void>> saveFuture = tsService.saveLatest(TenantId.SYS_TENANT_ID, entityId, latestValues);

2
application/src/main/java/org/thingsboard/server/service/profile/DefaultTbDeviceProfileCache.java

@ -50,9 +50,9 @@ public class DefaultTbDeviceProfileCache implements TbDeviceProfileCache {
public DeviceProfile get(TenantId tenantId, DeviceProfileId deviceProfileId) { public DeviceProfile get(TenantId tenantId, DeviceProfileId deviceProfileId) {
DeviceProfile profile = deviceProfilesMap.get(deviceProfileId); DeviceProfile profile = deviceProfilesMap.get(deviceProfileId);
if (profile == null) { if (profile == null) {
deviceProfileFetchLock.lock();
profile = deviceProfilesMap.get(deviceProfileId); profile = deviceProfilesMap.get(deviceProfileId);
if (profile == null) { if (profile == null) {
deviceProfileFetchLock.lock();
try { try {
profile = deviceProfileService.findDeviceProfileById(tenantId, deviceProfileId); profile = deviceProfileService.findDeviceProfileById(tenantId, deviceProfileId);
if (profile != null) { if (profile != null) {

7
application/src/main/resources/thingsboard.yml

@ -385,6 +385,9 @@ updates:
# Enable/disable updates checking. # Enable/disable updates checking.
enabled: "${UPDATES_ENABLED:true}" enabled: "${UPDATES_ENABLED:true}"
# spring freemarker configuration
spring.freemarker.checkTemplateLocation: "false"
# spring CORS configuration # spring CORS configuration
spring.mvc.cors: spring.mvc.cors:
mappings: mappings:
@ -424,7 +427,7 @@ spring:
database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}" database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}"
datasource: datasource:
driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}" driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}"
url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_32}" url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard}"
username: "${SPRING_DATASOURCE_USERNAME:postgres}" username: "${SPRING_DATASOURCE_USERNAME:postgres}"
password: "${SPRING_DATASOURCE_PASSWORD:postgres}" password: "${SPRING_DATASOURCE_PASSWORD:postgres}"
hikari: hikari:
@ -551,6 +554,8 @@ transport:
key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}" key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"
# Type of the key store # Type of the key store
key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}" key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}"
# Skip certificate validity check for client certificates.
skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
# Local CoAP transport parameters # Local CoAP transport parameters
coap: coap:
# Enable/disable coap transport protocol. # Enable/disable coap transport protocol.

30
application/src/test/java/org/thingsboard/server/mqtt/AbstractMqttIntegrationTest.java

@ -42,6 +42,7 @@ import org.thingsboard.server.gen.transport.TransportProtos;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@ -213,4 +214,33 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest
return builder.build(); return builder.build();
} }
protected <T> T doExecuteWithRetriesAndInterval(SupplierWithThrowable<T> supplier, int retries, int intervalMs) throws Exception {
int count = 0;
T result = null;
Throwable lastException = null;
while (count < retries) {
try {
result = supplier.get();
if (result != null) {
return result;
}
} catch (Throwable e) {
lastException = e;
}
count++;
if (count < retries) {
Thread.sleep(intervalMs);
}
}
if (lastException != null) {
throw new RuntimeException(lastException);
} else {
return result;
}
}
@FunctionalInterface
public interface SupplierWithThrowable<T> {
T get() throws Throwable;
}
} }

8
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestIntegrationTest.java

@ -84,10 +84,14 @@ public abstract class AbstractMqttAttributesRequestIntegrationTest extends Abstr
postGatewayDeviceClientAttributes(client); postGatewayDeviceClientAttributes(client);
Thread.sleep(1000); Device savedDevice = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + "Gateway Device Request Attributes", Device.class),
20,
100);
Device savedDevice = doGet("/api/tenant/devices?deviceName=" + "Gateway Device Request Attributes", Device.class);
assertNotNull(savedDevice); assertNotNull(savedDevice);
Thread.sleep(1000);
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
Thread.sleep(1000); Thread.sleep(1000);

9
application/src/test/java/org/thingsboard/server/mqtt/attributes/updates/AbstractMqttAttributesUpdatesIntegrationTest.java

@ -84,7 +84,7 @@ public abstract class AbstractMqttAttributesUpdatesIntegrationTest extends Abstr
client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, MqttQoS.AT_MOST_ONCE.value()); client.subscribe(MqttTopics.DEVICE_ATTRIBUTES_TOPIC, MqttQoS.AT_MOST_ONCE.value());
Thread.sleep(2000); Thread.sleep(1000);
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
onUpdateCallback.getLatch().await(3, TimeUnit.SECONDS); onUpdateCallback.getLatch().await(3, TimeUnit.SECONDS);
@ -127,14 +127,15 @@ public abstract class AbstractMqttAttributesUpdatesIntegrationTest extends Abstr
publishMqttMsg(client, connectPayloadBytes, MqttTopics.GATEWAY_CONNECT_TOPIC); publishMqttMsg(client, connectPayloadBytes, MqttTopics.GATEWAY_CONNECT_TOPIC);
Thread.sleep(1000); Device savedDevice = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + "Gateway Device Subscribe to attribute updates", Device.class),
20,
100);
Device savedDevice = doGet("/api/tenant/devices?deviceName=" + "Gateway Device Subscribe to attribute updates", Device.class);
assertNotNull(savedDevice); assertNotNull(savedDevice);
client.subscribe(MqttTopics.GATEWAY_ATTRIBUTES_TOPIC, MqttQoS.AT_MOST_ONCE.value()); client.subscribe(MqttTopics.GATEWAY_ATTRIBUTES_TOPIC, MqttQoS.AT_MOST_ONCE.value());
Thread.sleep(2000); Thread.sleep(1000);
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
onUpdateCallback.getLatch().await(3, TimeUnit.SECONDS); onUpdateCallback.getLatch().await(3, TimeUnit.SECONDS);

35
application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimDeviceTest.java

@ -75,25 +75,21 @@ public abstract class AbstractMqttClaimDeviceTest extends AbstractMqttIntegratio
} }
@Test @Test
@Ignore
public void testClaimingDevice() throws Exception { public void testClaimingDevice() throws Exception {
processTestClaimingDevice(false); processTestClaimingDevice(false);
} }
@Test @Test
@Ignore
public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { public void testClaimingDeviceWithoutSecretAndDuration() throws Exception {
processTestClaimingDevice(true); processTestClaimingDevice(true);
} }
@Test @Test
@Ignore
public void testGatewayClaimingDevice() throws Exception { public void testGatewayClaimingDevice() throws Exception {
processTestGatewayClaimingDevice("Test claiming gateway device", false); processTestGatewayClaimingDevice("Test claiming gateway device", false);
} }
@Test @Test
@Ignore
public void testGatewayClaimingDeviceWithoutSecretAndDuration() throws Exception { public void testGatewayClaimingDeviceWithoutSecretAndDuration() throws Exception {
processTestGatewayClaimingDevice("Test claiming gateway device empty payload", true); processTestGatewayClaimingDevice("Test claiming gateway device empty payload", true);
} }
@ -116,8 +112,6 @@ public abstract class AbstractMqttClaimDeviceTest extends AbstractMqttIntegratio
protected void validateClaimResponse(boolean emptyPayload, MqttAsyncClient client, byte[] payloadBytes, byte[] failurePayloadBytes) throws Exception { protected void validateClaimResponse(boolean emptyPayload, MqttAsyncClient client, byte[] payloadBytes, byte[] failurePayloadBytes) throws Exception {
client.publish(MqttTopics.DEVICE_CLAIM_TOPIC, new MqttMessage(failurePayloadBytes)); client.publish(MqttTopics.DEVICE_CLAIM_TOPIC, new MqttMessage(failurePayloadBytes));
Thread.sleep(2000);
loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD); loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD);
ClaimRequest claimRequest; ClaimRequest claimRequest;
if (!emptyPayload) { if (!emptyPayload) {
@ -126,14 +120,21 @@ public abstract class AbstractMqttClaimDeviceTest extends AbstractMqttIntegratio
claimRequest = new ClaimRequest(null); claimRequest = new ClaimRequest(null);
} }
ClaimResponse claimResponse = doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest()); ClaimResponse claimResponse = doExecuteWithRetriesAndInterval(
() -> doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest()),
20,
100
);
assertEquals(claimResponse, ClaimResponse.FAILURE); assertEquals(claimResponse, ClaimResponse.FAILURE);
client.publish(MqttTopics.DEVICE_CLAIM_TOPIC, new MqttMessage(payloadBytes)); client.publish(MqttTopics.DEVICE_CLAIM_TOPIC, new MqttMessage(payloadBytes));
Thread.sleep(2000); ClaimResult claimResult = doExecuteWithRetriesAndInterval(
() -> doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResult.class, status().isOk()),
ClaimResult claimResult = doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResult.class, status().isOk()); 20,
100
);
assertEquals(claimResult.getResponse(), ClaimResponse.SUCCESS); assertEquals(claimResult.getResponse(), ClaimResponse.SUCCESS);
Device claimedDevice = claimResult.getDevice(); Device claimedDevice = claimResult.getDevice();
assertNotNull(claimedDevice); assertNotNull(claimedDevice);
@ -147,9 +148,12 @@ public abstract class AbstractMqttClaimDeviceTest extends AbstractMqttIntegratio
protected void validateGatewayClaimResponse(String deviceName, boolean emptyPayload, MqttAsyncClient client, byte[] failurePayloadBytes, byte[] payloadBytes) throws Exception { protected void validateGatewayClaimResponse(String deviceName, boolean emptyPayload, MqttAsyncClient client, byte[] failurePayloadBytes, byte[] payloadBytes) throws Exception {
client.publish(MqttTopics.GATEWAY_CLAIM_TOPIC, new MqttMessage(failurePayloadBytes)); client.publish(MqttTopics.GATEWAY_CLAIM_TOPIC, new MqttMessage(failurePayloadBytes));
Thread.sleep(2000); Device savedDevice = doExecuteWithRetriesAndInterval(
() -> doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class),
20,
100
);
Device savedDevice = doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class);
assertNotNull(savedDevice); assertNotNull(savedDevice);
loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD); loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD);
@ -165,9 +169,12 @@ public abstract class AbstractMqttClaimDeviceTest extends AbstractMqttIntegratio
client.publish(MqttTopics.GATEWAY_CLAIM_TOPIC, new MqttMessage(payloadBytes)); client.publish(MqttTopics.GATEWAY_CLAIM_TOPIC, new MqttMessage(payloadBytes));
Thread.sleep(2000); ClaimResult claimResult = doExecuteWithRetriesAndInterval(
() -> doPostClaimAsync("/api/customer/device/" + deviceName + "/claim", claimRequest, ClaimResult.class, status().isOk()),
20,
100
);
ClaimResult claimResult = doPostClaimAsync("/api/customer/device/" + deviceName + "/claim", claimRequest, ClaimResult.class, status().isOk());
assertEquals(claimResult.getResponse(), ClaimResponse.SUCCESS); assertEquals(claimResult.getResponse(), ClaimResponse.SUCCESS);
Device claimedDevice = claimResult.getDevice(); Device claimedDevice = claimResult.getDevice();
assertNotNull(claimedDevice); assertNotNull(claimedDevice);

1
application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimJsonDeviceTest.java

@ -52,7 +52,6 @@ public abstract class AbstractMqttClaimJsonDeviceTest extends AbstractMqttClaimD
} }
@Test @Test
@Ignore
public void testGatewayClaimingDeviceWithoutSecretAndDuration() throws Exception { public void testGatewayClaimingDeviceWithoutSecretAndDuration() throws Exception {
processTestGatewayClaimingDevice("Test claiming gateway device empty payload Json", true); processTestGatewayClaimingDevice("Test claiming gateway device empty payload Json", true);
} }

4
application/src/test/java/org/thingsboard/server/mqtt/claim/AbstractMqttClaimProtoDeviceTest.java

@ -37,25 +37,21 @@ public abstract class AbstractMqttClaimProtoDeviceTest extends AbstractMqttClaim
public void afterTest() throws Exception { super.afterTest(); } public void afterTest() throws Exception { super.afterTest(); }
@Test @Test
@Ignore
public void testClaimingDevice() throws Exception { public void testClaimingDevice() throws Exception {
processTestClaimingDevice(false); processTestClaimingDevice(false);
} }
@Test @Test
@Ignore
public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { public void testClaimingDeviceWithoutSecretAndDuration() throws Exception {
processTestClaimingDevice(true); processTestClaimingDevice(true);
} }
@Test @Test
@Ignore
public void testGatewayClaimingDevice() throws Exception { public void testGatewayClaimingDevice() throws Exception {
processTestGatewayClaimingDevice("Test claiming gateway device Proto", false); processTestGatewayClaimingDevice("Test claiming gateway device Proto", false);
} }
@Test @Test
@Ignore
public void testGatewayClaimingDeviceWithoutSecretAndDuration() throws Exception { public void testGatewayClaimingDeviceWithoutSecretAndDuration() throws Exception {
processTestGatewayClaimingDevice("Test claiming gateway device empty payload Proto", true); processTestGatewayClaimingDevice("Test claiming gateway device empty payload Proto", true);
} }

24
application/src/test/java/org/thingsboard/server/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java

@ -84,7 +84,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, MqttQoS.AT_MOST_ONCE.value()); client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, MqttQoS.AT_MOST_ONCE.value());
Thread.sleep(2000); Thread.sleep(1000);
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}";
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();
@ -109,7 +109,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
TestMqttCallback callback = new TestMqttCallback(client, latch); TestMqttCallback callback = new TestMqttCallback(client, latch);
client.setCallback(callback); client.setCallback(callback);
Thread.sleep(2000); Thread.sleep(1000);
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();
@ -132,9 +132,11 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
protected void validateOneWayRpcGatewayResponse(String deviceName, MqttAsyncClient client, byte[] payloadBytes) throws Exception { protected void validateOneWayRpcGatewayResponse(String deviceName, MqttAsyncClient client, byte[] payloadBytes) throws Exception {
publishMqttMsg(client, payloadBytes, MqttTopics.GATEWAY_CONNECT_TOPIC); publishMqttMsg(client, payloadBytes, MqttTopics.GATEWAY_CONNECT_TOPIC);
Thread.sleep(2000); Device savedDevice = doExecuteWithRetriesAndInterval(
() -> getDeviceByName(deviceName),
Device savedDevice = getDeviceByName(deviceName); 20,
100
);
assertNotNull(savedDevice); assertNotNull(savedDevice);
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -143,7 +145,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
client.subscribe(MqttTopics.GATEWAY_RPC_TOPIC, MqttQoS.AT_MOST_ONCE.value()); client.subscribe(MqttTopics.GATEWAY_RPC_TOPIC, MqttQoS.AT_MOST_ONCE.value());
Thread.sleep(2000); Thread.sleep(1000);
String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}"; String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}";
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();
@ -156,9 +158,11 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
protected void validateTwoWayRpcGateway(String deviceName, MqttAsyncClient client, byte[] payloadBytes) throws Exception { protected void validateTwoWayRpcGateway(String deviceName, MqttAsyncClient client, byte[] payloadBytes) throws Exception {
publishMqttMsg(client, payloadBytes, MqttTopics.GATEWAY_CONNECT_TOPIC); publishMqttMsg(client, payloadBytes, MqttTopics.GATEWAY_CONNECT_TOPIC);
Thread.sleep(2000); Device savedDevice = doExecuteWithRetriesAndInterval(
() -> getDeviceByName(deviceName),
Device savedDevice = getDeviceByName(deviceName); 20,
100
);
assertNotNull(savedDevice); assertNotNull(savedDevice);
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -167,7 +171,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
client.subscribe(MqttTopics.GATEWAY_RPC_TOPIC, MqttQoS.AT_MOST_ONCE.value()); client.subscribe(MqttTopics.GATEWAY_RPC_TOPIC, MqttQoS.AT_MOST_ONCE.value());
Thread.sleep(2000); Thread.sleep(1000);
String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}"; String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}";
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();

15
application/src/test/java/org/thingsboard/server/mqtt/telemetry/attributes/AbstractMqttAttributesIntegrationTest.java

@ -75,7 +75,7 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt
DeviceId deviceId = savedDevice.getId(); DeviceId deviceId = savedDevice.getId();
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 2000; long end = System.currentTimeMillis() + 5000;
List<String> actualKeys = null; List<String> actualKeys = null;
while (start <= end) { while (start <= end) {
@ -106,13 +106,20 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt
publishMqttMsg(client, payload, MqttTopics.GATEWAY_ATTRIBUTES_TOPIC); publishMqttMsg(client, payload, MqttTopics.GATEWAY_ATTRIBUTES_TOPIC);
Thread.sleep(2000); Device firstDevice = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + firstDeviceName, Device.class),
20,
100);
Device firstDevice = doGet("/api/tenant/devices?deviceName=" + firstDeviceName, Device.class);
assertNotNull(firstDevice); assertNotNull(firstDevice);
Device secondDevice = doGet("/api/tenant/devices?deviceName=" + secondDeviceName, Device.class);
Device secondDevice = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + secondDeviceName, Device.class),
20,
100);
assertNotNull(secondDevice); assertNotNull(secondDevice);
Thread.sleep(2000);
List<String> firstDeviceActualKeys = doGetAsync("/api/plugins/telemetry/DEVICE/" + firstDevice.getId() + "/keys/attributes/CLIENT_SCOPE", List.class); List<String> firstDeviceActualKeys = doGetAsync("/api/plugins/telemetry/DEVICE/" + firstDevice.getId() + "/keys/attributes/CLIENT_SCOPE", List.class);
Set<String> firstDeviceActualKeySet = new HashSet<>(firstDeviceActualKeys); Set<String> firstDeviceActualKeySet = new HashSet<>(firstDeviceActualKeys);

23
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java

@ -88,10 +88,12 @@ public abstract class AbstractMqttTimeseriesIntegrationTest extends AbstractMqtt
MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken);
publishMqttMsg(client, payload.getBytes(), MqttTopics.GATEWAY_CONNECT_TOPIC); publishMqttMsg(client, payload.getBytes(), MqttTopics.GATEWAY_CONNECT_TOPIC);
Thread.sleep(2000);
String deviceName = "Device A"; String deviceName = "Device A";
Device device = doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class);
Device device = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class),
20,
100);
assertNotNull(device); assertNotNull(device);
} }
@ -102,7 +104,7 @@ public abstract class AbstractMqttTimeseriesIntegrationTest extends AbstractMqtt
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 2000; long end = System.currentTimeMillis() + 5000;
List<String> actualKeys = null; List<String> actualKeys = null;
while (start <= end) { while (start <= end) {
@ -139,13 +141,20 @@ public abstract class AbstractMqttTimeseriesIntegrationTest extends AbstractMqtt
publishMqttMsg(client, payload, topic); publishMqttMsg(client, payload, topic);
Thread.sleep(2000); Device firstDevice = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + firstDeviceName, Device.class),
20,
100);
Device firstDevice = doGet("/api/tenant/devices?deviceName=" + firstDeviceName, Device.class);
assertNotNull(firstDevice); assertNotNull(firstDevice);
Device secondDevice = doGet("/api/tenant/devices?deviceName=" + secondDeviceName, Device.class);
Device secondDevice = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + secondDeviceName, Device.class),
20,
100);
assertNotNull(secondDevice); assertNotNull(secondDevice);
Thread.sleep(2000);
List<String> firstDeviceActualKeys = doGetAsync("/api/plugins/telemetry/DEVICE/" + firstDevice.getId() + "/keys/timeseries", List.class); List<String> firstDeviceActualKeys = doGetAsync("/api/plugins/telemetry/DEVICE/" + firstDevice.getId() + "/keys/timeseries", List.class);
Set<String> firstDeviceActualKeySet = new HashSet<>(firstDeviceActualKeys); Set<String> firstDeviceActualKeySet = new HashSet<>(firstDeviceActualKeys);

6
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesJsonIntegrationTest.java

@ -73,10 +73,10 @@ public abstract class AbstractMqttTimeseriesJsonIntegrationTest extends Abstract
MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken);
publishMqttMsg(client, payload.getBytes(), MqttTopics.GATEWAY_CONNECT_TOPIC); publishMqttMsg(client, payload.getBytes(), MqttTopics.GATEWAY_CONNECT_TOPIC);
Thread.sleep(2000);
String deviceName = "Device A"; String deviceName = "Device A";
Device device = doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class); Device device = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class),
20,
100);
assertNotNull(device); assertNotNull(device);
} }
} }

5
application/src/test/java/org/thingsboard/server/mqtt/telemetry/timeseries/AbstractMqttTimeseriesProtoIntegrationTest.java

@ -81,9 +81,10 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken);
publishMqttMsg(client, connectMsgProto.toByteArray(), MqttTopics.GATEWAY_CONNECT_TOPIC); publishMqttMsg(client, connectMsgProto.toByteArray(), MqttTopics.GATEWAY_CONNECT_TOPIC);
Thread.sleep(2000); Device device = doExecuteWithRetriesAndInterval(() -> doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class),
20,
100);
Device device = doGet("/api/tenant/devices?deviceName=" + deviceName, Device.class);
assertNotNull(device); assertNotNull(device);
} }

2
common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java

@ -19,5 +19,5 @@ package org.thingsboard.server.common.data;
* @author Andrew Shvayka * @author Andrew Shvayka
*/ */
public enum EntityType { public enum EntityType {
TENANT, TENANT_PROFILE, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, DEVICE_PROFILE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, OAUTH2_CLIENT_REGISTRATION, OAUTH2_CLIENT_REGISTRATION_INFO, OAUTH2_CLIENT_REGISTRATION_TEMPLATE TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE
} }

4
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java

@ -51,6 +51,10 @@ public class MqttTransportContext extends TransportContext {
@Value("${transport.mqtt.netty.max_payload_size}") @Value("${transport.mqtt.netty.max_payload_size}")
private Integer maxPayloadSize; private Integer maxPayloadSize;
@Getter
@Value("${transport.mqtt.netty.skip_validity_check_for_client_cert:false}")
private boolean skipValidityCheckForClientCert;
@Getter @Getter
@Setter @Setter
private SslHandler sslHandler; private SslHandler sslHandler;

4
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java

@ -68,6 +68,7 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.Date;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED;
@ -386,6 +387,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate cert) { private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate cert) {
try { try {
if(!context.isSkipValidityCheckForClientCert()){
cert.checkValidity();
}
String strCert = SslUtil.getX509CertificateString(cert); String strCert = SslUtil.getX509CertificateString(cert);
String sha3Hash = EncryptionUtil.getSha3Hash(strCert); String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
transportService.process(DeviceTransportType.MQTT, ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(), transportService.process(DeviceTransportType.MQTT, ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),

51
dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java

@ -225,9 +225,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
" INNER JOIN related_entities re ON" + " INNER JOIN related_entities re ON" +
" r.$in_id = re.$out_id and r.$in_type = re.$out_type and" + " r.$in_id = re.$out_id and r.$in_type = re.$out_type and" +
" relation_type_group = 'COMMON' %s)" + " relation_type_group = 'COMMON' %s)" +
" SELECT re.$out_id entity_id, re.$out_type entity_type, re.lvl lvl" + " SELECT re.$out_id entity_id, re.$out_type entity_type, max(re.lvl) lvl" +
" from related_entities re" + " from related_entities re" +
" %s ) entity"; " %s GROUP BY entity_id, entity_type) entity";
private static final String HIERARCHICAL_TO_QUERY_TEMPLATE = HIERARCHICAL_QUERY_TEMPLATE.replace("$in", "to").replace("$out", "from"); private static final String HIERARCHICAL_TO_QUERY_TEMPLATE = HIERARCHICAL_QUERY_TEMPLATE.replace("$in", "to").replace("$out", "from");
private static final String HIERARCHICAL_FROM_QUERY_TEMPLATE = HIERARCHICAL_QUERY_TEMPLATE.replace("$in", "from").replace("$out", "to"); private static final String HIERARCHICAL_FROM_QUERY_TEMPLATE = HIERARCHICAL_QUERY_TEMPLATE.replace("$in", "from").replace("$out", "to");
@ -457,8 +457,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
private String entitySearchQuery(QueryContext ctx, EntitySearchQueryFilter entityFilter, EntityType entityType, List<String> types) { private String entitySearchQuery(QueryContext ctx, EntitySearchQueryFilter entityFilter, EntityType entityType, List<String> types) {
EntityId rootId = entityFilter.getRootEntity(); EntityId rootId = entityFilter.getRootEntity();
//TODO: fetch last level only.
//TODO: fetch distinct records.
String lvlFilter = getLvlFilter(entityFilter.getMaxLevel()); String lvlFilter = getLvlFilter(entityFilter.getMaxLevel());
String selectFields = "SELECT tenant_id, customer_id, id, created_time, type, name, additional_info " String selectFields = "SELECT tenant_id, customer_id, id, created_time, type, name, additional_info "
+ (entityType.equals(EntityType.ENTITY_VIEW) ? "" : ", label ") + (entityType.equals(EntityType.ENTITY_VIEW) ? "" : ", label ")
@ -469,8 +467,21 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
ctx.addStringParameter("where_relation_type", entityFilter.getRelationType()); ctx.addStringParameter("where_relation_type", entityFilter.getRelationType());
whereFilter += " re.relation_type = :where_relation_type AND"; whereFilter += " re.relation_type = :where_relation_type AND";
} }
String toOrFrom = (entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from");
whereFilter += " re." + (entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from") + "_type = :where_entity_type"; whereFilter += " re." + (entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from") + "_type = :where_entity_type";
if (entityFilter.isFetchLastLevelOnly()) {
String fromOrTo = (entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "from" : "to");
StringBuilder notExistsPart = new StringBuilder();
notExistsPart.append(" NOT EXISTS (SELECT 1 from relation nr where ")
.append("nr.").append(fromOrTo).append("_id").append(" = re.").append(toOrFrom).append("_id")
.append(" and ")
.append("nr.").append(fromOrTo).append("_type").append(" = re.").append(toOrFrom).append("_type");
if (!StringUtils.isEmpty(entityFilter.getRelationType())) {
notExistsPart.append(" and nr.relation_type = :where_relation_type");
}
notExistsPart.append(")");
whereFilter += " and ( re.lvl = " + entityFilter.getMaxLevel() + " OR " + notExistsPart.toString() + ")";
}
from = String.format(from, lvlFilter, whereFilter); from = String.format(from, lvlFilter, whereFilter);
String query = "( " + selectFields + from + ")"; String query = "( " + selectFields + from + ")";
if (types != null && !types.isEmpty()) { if (types != null && !types.isEmpty()) {
@ -500,16 +511,15 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
ctx.addStringParameter("relation_root_type", rootId.getEntityType().name()); ctx.addStringParameter("relation_root_type", rootId.getEntityType().name());
StringBuilder whereFilter = new StringBuilder(); StringBuilder whereFilter = new StringBuilder();
;
boolean noConditions = true; boolean noConditions = true;
boolean single = entityFilter.getFilters() != null && entityFilter.getFilters().size() == 1;
if (entityFilter.getFilters() != null && !entityFilter.getFilters().isEmpty()) { if (entityFilter.getFilters() != null && !entityFilter.getFilters().isEmpty()) {
boolean single = entityFilter.getFilters().size() == 1;
int entityTypeFilterIdx = 0; int entityTypeFilterIdx = 0;
for (EntityTypeFilter etf : entityFilter.getFilters()) { for (EntityTypeFilter etf : entityFilter.getFilters()) {
String etfCondition = buildEtfCondition(ctx, etf, entityFilter.getDirection(), entityTypeFilterIdx++); String etfCondition = buildEtfCondition(ctx, etf, entityFilter.getDirection(), entityTypeFilterIdx++);
if (!etfCondition.isEmpty()) { if (!etfCondition.isEmpty()) {
if (noConditions) { if (noConditions) {
whereFilter.append(" WHERE ");
noConditions = false; noConditions = false;
} else { } else {
whereFilter.append(" OR "); whereFilter.append(" OR ");
@ -525,12 +535,33 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
} }
} }
if (noConditions) { if (noConditions) {
whereFilter.append(" WHERE re.") whereFilter.append(" re.")
.append(entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from") .append(entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from")
.append("_type in (:where_entity_types").append(")"); .append("_type in (:where_entity_types").append(")");
ctx.addStringListParameter("where_entity_types", Arrays.stream(RELATION_QUERY_ENTITY_TYPES).map(EntityType::name).collect(Collectors.toList())); ctx.addStringListParameter("where_entity_types", Arrays.stream(RELATION_QUERY_ENTITY_TYPES).map(EntityType::name).collect(Collectors.toList()));
} }
from = String.format(from, lvlFilter, whereFilter);
if (!noConditions && !single) {
whereFilter = new StringBuilder().append("(").append(whereFilter).append(")");
}
if (entityFilter.isFetchLastLevelOnly()) {
String toOrFrom = (entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from");
String fromOrTo = (entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "from" : "to");
StringBuilder notExistsPart = new StringBuilder();
notExistsPart.append(" NOT EXISTS (SELECT 1 from relation nr WHERE ");
notExistsPart.append(whereFilter.toString());
notExistsPart
.append(" and ")
.append("nr.").append(fromOrTo).append("_id").append(" = re.").append(toOrFrom).append("_id")
.append(" and ")
.append("nr.").append(fromOrTo).append("_type").append(" = re.").append(toOrFrom).append("_type");
notExistsPart.append(")");
whereFilter.append(" and ( re.lvl = ").append(entityFilter.getMaxLevel()).append(" OR ").append(notExistsPart.toString()).append(")");
}
from = String.format(from, lvlFilter, " WHERE " + whereFilter);
return "( " + selectFields + from + ")"; return "( " + selectFields + from + ")";
} }

10
dao/src/main/java/org/thingsboard/server/dao/util/mapping/JacksonUtil.java

@ -18,7 +18,7 @@ package org.thingsboard.server.dao.util.mapping;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.thingsboard.server.common.data.alarm.Alarm; import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException; import java.io.IOException;
@ -66,12 +66,16 @@ public class JacksonUtil {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }
} }
public static ObjectNode newObjectNode(){
return OBJECT_MAPPER.createObjectNode();
}
public static <T> T clone(T value) { public static <T> T clone(T value) {
return fromString(toString(value), (Class<T>) value.getClass()); return fromString(toString(value), (Class<T>) value.getClass());
} }
public static <T> JsonNode valueToTree(T alarm) { public static <T> JsonNode valueToTree(T value) {
return OBJECT_MAPPER.valueToTree(alarm); return OBJECT_MAPPER.valueToTree(value);
} }
} }

4
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java

@ -53,7 +53,9 @@ import java.util.concurrent.TimeUnit;
relationTypes = {"Alarm Created", "Alarm Updated", "Alarm Severity Updated", "Alarm Cleared", "Success", "Failure"}, relationTypes = {"Alarm Created", "Alarm Updated", "Alarm Severity Updated", "Alarm Cleared", "Success", "Failure"},
configClazz = TbDeviceProfileNodeConfiguration.class, configClazz = TbDeviceProfileNodeConfiguration.class,
nodeDescription = "Process device messages based on device profile settings", 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. Generates ",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbDeviceProfileConfig"
) )
public class TbDeviceProfileNode implements TbNode { public class TbDeviceProfileNode implements TbNode {
private static final String PERIODIC_MSG_TYPE = "TbDeviceProfilePeriodicMsg"; private static final String PERIODIC_MSG_TYPE = "TbDeviceProfilePeriodicMsg";

2
rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js

File diff suppressed because one or more lines are too long

2
transport/mqtt/src/main/resources/tb-mqtt-transport.yml

@ -66,6 +66,8 @@ transport:
key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}" key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"
# Type of the key store # Type of the key store
key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}" key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}"
# Skip certificate validity check for client certificates.
skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
sessions: sessions:
inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}"
report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:30000}" report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:30000}"

4
ui-ngx/e2e/tsconfig.e2e.json

@ -1,5 +1,5 @@
{ {
"extends": "../tsconfig.base.json", "extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../out-tsc/app", "outDir": "../out-tsc/app",
"module": "commonjs", "module": "commonjs",
@ -10,4 +10,4 @@
"node" "node"
] ]
} }
} }

2
ui-ngx/extra-webpack.config.js

@ -32,7 +32,7 @@ module.exports = {
SUPPORTED_LANGS: JSON.stringify(langs), SUPPORTED_LANGS: JSON.stringify(langs),
}), }),
new CompressionPlugin({ new CompressionPlugin({
filename: "[path].gz[query]", filename: "[path][base].gz[query]",
algorithm: "gzip", algorithm: "gzip",
test: /\.js$|\.css$|\.html$|\.svg?.+$|\.jpg$|\.ttf?.+$|\.woff?.+$|\.eot?.+$|\.json$/, test: /\.js$|\.css$|\.html$|\.svg?.+$|\.jpg$|\.ttf?.+$|\.woff?.+$|\.eot?.+$|\.json$/,
threshold: 10240, threshold: 10240,

86
ui-ngx/package.json

@ -12,33 +12,33 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^10.0.9", "@angular/animations": "^10.1.5",
"@angular/cdk": "^10.1.3", "@angular/cdk": "^10.2.4",
"@angular/common": "^10.0.9", "@angular/common": "^10.1.5",
"@angular/compiler": "^10.0.9", "@angular/compiler": "^10.1.5",
"@angular/core": "^10.0.9", "@angular/core": "^10.1.5",
"@angular/flex-layout": "^10.0.0-beta.32", "@angular/flex-layout": "^10.0.0-beta.32",
"@angular/forms": "^10.0.9", "@angular/forms": "^10.1.5",
"@angular/material": "^10.1.3", "@angular/material": "^10.2.4",
"@angular/platform-browser": "^10.0.9", "@angular/platform-browser": "^10.1.5",
"@angular/platform-browser-dynamic": "^10.0.9", "@angular/platform-browser-dynamic": "^10.1.5",
"@angular/router": "^10.0.9", "@angular/router": "^10.1.5",
"@auth0/angular-jwt": "^5.0.1", "@auth0/angular-jwt": "^5.0.1",
"@date-io/date-fns": "^2.6.1", "@date-io/date-fns": "^2.6.1",
"@flowjs/flow.js": "^2.14.1", "@flowjs/flow.js": "^2.14.1",
"@flowjs/ngx-flow": "^0.4.4", "@flowjs/ngx-flow": "^0.4.4",
"@juggle/resize-observer": "^3.1.3", "@juggle/resize-observer": "^3.1.3",
"@mat-datetimepicker/core": "^5.0.1", "@mat-datetimepicker/core": "^5.1.0",
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1", "@material-ui/icons": "^4.9.1",
"@material-ui/pickers": "^3.2.10", "@material-ui/pickers": "^3.2.10",
"@ngrx/effects": "^10.0.0", "@ngrx/effects": "^10.0.1",
"@ngrx/store": "^10.0.0", "@ngrx/store": "^10.0.1",
"@ngrx/store-devtools": "^10.0.0", "@ngrx/store-devtools": "^10.0.1",
"@ngx-translate/core": "^13.0.0", "@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "^6.0.0", "@ngx-translate/http-loader": "^6.0.0",
"ace-builds": "^1.4.12", "ace-builds": "^1.4.12",
"angular-gridster2": "^10.1.3", "angular-gridster2": "^10.1.6",
"angular2-hotkeys": "^2.2.0", "angular2-hotkeys": "^2.2.0",
"canvas-gauges": "^2.1.7", "canvas-gauges": "^2.1.7",
"compass-sass-mixins": "^0.12.7", "compass-sass-mixins": "^0.12.7",
@ -48,8 +48,8 @@
"flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master", "flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"jquery": "^3.5.1", "jquery": "^3.5.1",
"jquery.terminal": "^2.16.0", "jquery.terminal": "^2.18.3",
"js-beautify": "^1.12.0", "js-beautify": "^1.13.0",
"json-schema-defaults": "^0.4.0", "json-schema-defaults": "^0.4.0",
"jstree": "^3.3.10", "jstree": "^3.3.10",
"jstree-bootstrap-theme": "^1.0.1", "jstree-bootstrap-theme": "^1.0.1",
@ -62,62 +62,64 @@
"leaflet.markercluster": "^1.4.1", "leaflet.markercluster": "^1.4.1",
"material-design-icons": "^3.0.1", "material-design-icons": "^3.0.1",
"messageformat": "^2.3.0", "messageformat": "^2.3.0",
"moment": "^2.27.0", "moment": "^2.29.1",
"moment-timezone": "^0.5.31", "moment-timezone": "^0.5.31",
"mousetrap": "1.6.3",
"ngx-clipboard": "^13.0.1", "ngx-clipboard": "^13.0.1",
"ngx-color-picker": "^10.0.1", "ngx-color-picker": "^10.1.0",
"ngx-daterangepicker-material": "^4.0.1", "ngx-daterangepicker-material": "^4.0.1",
"ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master", "ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master",
"ngx-hm-carousel": "^2.0.0-rc.1", "ngx-hm-carousel": "^2.0.0-rc.1",
"ngx-sharebuttons": "^8.0.1", "ngx-sharebuttons": "^8.0.1",
"ngx-translate-messageformat-compiler": "^4.8.0", "ngx-translate-messageformat-compiler": "^4.8.0",
"objectpath": "^2.0.0", "objectpath": "^2.0.0",
"prettier": "^2.0.5", "prettier": "^2.1.2",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"raphael": "^2.3.0", "raphael": "^2.3.0",
"rc-select": "^11.1.3", "rc-select": "^11.3.3",
"react": "^16.13.1", "react": "^16.13.1",
"react-ace": "^9.1.3", "react-ace": "^9.1.4",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-dropzone": "^11.0.3", "react-dropzone": "^11.2.0",
"reactcss": "^1.2.3", "reactcss": "^1.2.3",
"rxjs": "^6.6.2", "rxjs": "^6.6.3",
"schema-inspector": "^1.7.0", "schema-inspector": "^1.7.0",
"screenfull": "^5.0.2", "screenfull": "^5.0.2",
"split.js": "^1.6.2", "split.js": "^1.6.2",
"systemjs": "0.21.5", "systemjs": "0.21.5",
"tinycolor2": "^1.4.1", "tinycolor2": "^1.4.2",
"tooltipster": "^4.2.8", "tooltipster": "^4.2.8",
"tslib": "^2.0.1", "tslib": "^2.0.2",
"tv4": "^1.3.0", "tv4": "^1.3.0",
"typeface-roboto": "^0.0.75", "typeface-roboto": "^1.1.13",
"zone.js": "~0.10.3" "zone.js": "~0.11.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-builders/custom-webpack": "^10.0.0", "@angular-builders/custom-webpack": "^10.0.1",
"@angular-devkit/build-angular": "^0.1000.5", "@angular-devkit/build-angular": "^0.1001.5",
"@angular/cli": "^10.0.5", "@angular/cli": "^10.1.5",
"@angular/compiler-cli": "^10.0.9", "@angular/compiler-cli": "^10.1.5",
"@angular/language-service": "^10.0.9", "@angular/language-service": "^10.1.5",
"@types/canvas-gauges": "^2.1.2", "@types/canvas-gauges": "^2.1.2",
"@types/flot": "^0.0.31", "@types/flot": "^0.0.31",
"@types/jasmine": "^3.5.12", "@types/jasmine": "^3.5.12",
"@types/jasminewd2": "^2.0.8", "@types/jasminewd2": "^2.0.8",
"@types/jquery": "^3.5.1", "@types/jquery": "^3.5.2",
"@types/js-beautify": "^1.11.0", "@types/js-beautify": "^1.11.0",
"@types/jstree": "^3.3.40", "@types/jstree": "^3.3.40",
"@types/leaflet": "^1.5.17", "@types/leaflet": "^1.5.17",
"@types/leaflet-polylinedecorator": "^1.6.0", "@types/leaflet-polylinedecorator": "^1.6.0",
"@types/leaflet.markercluster": "^1.4.2", "@types/leaflet.markercluster": "^1.4.3",
"@types/lodash": "^4.14.159", "@types/lodash": "^4.14.161",
"@types/moment-timezone": "^0.5.30", "@types/moment-timezone": "^0.5.30",
"@types/mousetrap": "1.6.3",
"@types/raphael": "^2.3.0", "@types/raphael": "^2.3.0",
"@types/react": "^16.9.46", "@types/react": "^16.9.51",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
"@types/tinycolor2": "^1.4.2", "@types/tinycolor2": "^1.4.2",
"@types/tooltipster": "^0.0.30", "@types/tooltipster": "^0.0.30",
"codelyzer": "^6.0.0", "codelyzer": "^6.0.1",
"compression-webpack-plugin": "^4.0.1", "compression-webpack-plugin": "^6.0.2",
"directory-tree": "^2.2.4", "directory-tree": "^2.2.4",
"jasmine-core": "~3.6.0", "jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.2", "jasmine-spec-reporter": "~5.0.2",
@ -128,9 +130,9 @@
"karma-jasmine-html-reporter": "^1.5.4", "karma-jasmine-html-reporter": "^1.5.4",
"ngrx-store-freeze": "^0.2.4", "ngrx-store-freeze": "^0.2.4",
"protractor": "~7.0.0", "protractor": "~7.0.0",
"ts-node": "^8.10.2", "ts-node": "^9.0.0",
"tslint": "~6.1.3", "tslint": "~6.1.3",
"typescript": "~3.9.7", "typescript": "~4.0.3",
"webpack": "^4.44.1" "webpack": "^4.44.2"
} }
} }

4
ui-ngx/src/app/modules/home/components/attribute/attribute-table.component.html

@ -246,11 +246,11 @@
widgetsList.length === 0 && widgetsList.length === 0 &&
widgetsBundle" widgetsBundle"
fxFlex fxLayoutAlign="center center" fxFlex fxLayoutAlign="center center"
style="text-transform: uppercase; display: flex;" style="display: flex;"
class="mat-headline">widgets-bundle.empty</span> class="mat-headline">widgets-bundle.empty</span>
<span translate *ngIf="mode === 'widget' && !widgetsBundle" <span translate *ngIf="mode === 'widget' && !widgetsBundle"
fxFlex fxLayoutAlign="center center" fxFlex fxLayoutAlign="center center"
style="text-transform: uppercase; display: flex;" style="display: flex;"
class="mat-headline">widget.select-widgets-bundle</span> class="mat-headline">widget.select-widgets-bundle</span>
</div> </div>
</div> </div>

1
ui-ngx/src/app/modules/home/components/details-panel.component.scss

@ -41,7 +41,6 @@
font-size: 1rem; font-size: 1rem;
font-weight: 400; font-weight: 400;
text-overflow: ellipsis; text-overflow: ellipsis;
text-transform: uppercase;
white-space: nowrap; white-space: nowrap;
@media #{$mat-gt-sm} { @media #{$mat-gt-sm} {

1
ui-ngx/src/app/modules/home/components/filter/filter-text.component.scss

@ -62,7 +62,6 @@
font-size: 0.9em; font-size: 0.9em;
} }
.tb-filter-complex-operation { .tb-filter-complex-operation {
text-transform: uppercase;
font-weight: bold; font-weight: bold;
} }
.tb-filter-dynamic-value { .tb-filter-dynamic-value {

2
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.scss

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@import '../scss/constants'; @import '../../../../../../scss/constants';
:host { :host {
.tb-device-profile-alarms { .tb-device-profile-alarms {

1
ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.scss

@ -51,7 +51,6 @@
label { label {
padding: 4px; padding: 4px;
color: #00acc1; color: #00acc1;
text-transform: uppercase;
background: rgba(220, 220, 220, .35); background: rgba(220, 220, 220, .35);
border-radius: 5px; border-radius: 5px;
&:not(:last-child) { &:not(:last-child) {

1
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.scss

@ -30,7 +30,6 @@
position: relative; position: relative;
display: flex; display: flex;
height: 40px; height: 40px;
text-transform: uppercase;
} }
} }
} }

2
ui-ngx/src/app/modules/home/components/widget/widget.component.html

@ -38,7 +38,7 @@
</div> </div>
<div class="tb-absolute-fill tb-widget-no-data" *ngIf="displayNoData"> <div class="tb-absolute-fill tb-widget-no-data" *ngIf="displayNoData">
<span fxLayoutAlign="center center" <span fxLayoutAlign="center center"
style="text-transform: uppercase; display: flex;" style="display: flex;"
class="tb-absolute-fill" class="tb-absolute-fill"
translate>widget.no-data</span> translate>widget.no-data</span>
</div> </div>

2
ui-ngx/src/app/modules/home/home.component.ts

@ -50,7 +50,7 @@ export class HomeComponent extends PageComponent implements AfterViewInit, OnIni
sidenavMode: 'over' | 'push' | 'side' = 'side'; sidenavMode: 'over' | 'push' | 'side' = 'side';
sidenavOpened = true; sidenavOpened = true;
logo = require('../../../assets/logo_title_white.svg').default; logo = 'assets/logo_title_white.svg';
@ViewChild('sidenav') @ViewChild('sidenav')
sidenav: MatSidenav; sidenav: MatSidenav;

1
ui-ngx/src/app/modules/home/menu/side-menu.component.scss

@ -32,7 +32,6 @@
} }
a.mat-button { a.mat-button {
text-transform: uppercase;
display: flex; display: flex;
overflow: hidden; overflow: hidden;
line-height: 40px; line-height: 40px;

4
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-widget-select.component.html

@ -74,11 +74,11 @@
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
<span translate *ngIf="widgetsBundle && !hasWidgetTypes()" <span translate *ngIf="widgetsBundle && !hasWidgetTypes()"
style="text-transform: uppercase; display: flex;" style="display: flex;"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="mat-headline tb-absolute-fill">widgets-bundle.empty</span> class="mat-headline tb-absolute-fill">widgets-bundle.empty</span>
<span translate *ngIf="!widgetsBundle" <span translate *ngIf="!widgetsBundle"
style="text-transform: uppercase; display: flex;" style="display: flex;"
fxLayoutAlign="center center" fxLayoutAlign="center center"
class="mat-headline tb-absolute-fill">widget.select-widgets-bundle</span> class="mat-headline tb-absolute-fill">widget.select-widgets-bundle</span>
</div> </div>

2
ui-ngx/src/app/modules/home/pages/dashboard/layout/dashboard-layout.component.html

@ -27,7 +27,7 @@
[ngStyle]="dashboardStyle"> [ngStyle]="dashboardStyle">
<section *ngIf="layoutCtx.widgets.isEmpty()" fxLayoutAlign="center center" <section *ngIf="layoutCtx.widgets.isEmpty()" fxLayoutAlign="center center"
[ngStyle]="{'color': layoutCtx.gridSettings.color}" [ngStyle]="{'color': layoutCtx.gridSettings.color}"
style="text-transform: uppercase; display: flex; z-index: 1; pointer-events: none;" style="display: flex; z-index: 1; pointer-events: none;"
class="mat-headline tb-absolute-fill"> class="mat-headline tb-absolute-fill">
<span *ngIf="!isEdit"> <span *ngIf="!isEdit">
{{'dashboard.no-widgets' | translate}} {{'dashboard.no-widgets' | translate}}

1
ui-ngx/src/app/modules/home/pages/home-links/home-links.component.scss

@ -41,7 +41,6 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
max-width: 240px; max-width: 240px;
text-transform: uppercase;
&:hover { &:hover {
border-bottom: none; border-bottom: none;
} }

1
ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.scss

@ -120,7 +120,6 @@ div.tb-editor-area-title-panel {
label { label {
padding: 4px; padding: 4px;
color: #00acc1; color: #00acc1;
text-transform: uppercase;
background: rgba(220, 220, 220, .35); background: rgba(220, 220, 220, .35);
border-radius: 5px; border-radius: 5px;
&:not(:last-child) { &:not(:last-child) {

4
ui-ngx/src/app/modules/home/pages/widget/widget-library.component.html

@ -16,7 +16,7 @@
--> -->
<section [fxShow]="!(isLoading$ | async) && widgetsData.widgets.length === 0" fxLayoutAlign="center center" <section [fxShow]="!(isLoading$ | async) && widgetsData.widgets.length === 0" fxLayoutAlign="center center"
style="text-transform: uppercase; display: flex; z-index: 1;" style="display: flex; z-index: 1;"
class="tb-absolute-fill"> class="tb-absolute-fill">
<button mat-button *ngIf="!isReadOnly" class="tb-add-new-widget" (click)="addWidgetType($event)"> <button mat-button *ngIf="!isReadOnly" class="tb-add-new-widget" (click)="addWidgetType($event)">
<mat-icon class="tb-mat-96">add</mat-icon> <mat-icon class="tb-mat-96">add</mat-icon>
@ -24,7 +24,7 @@
</button> </button>
<span translate *ngIf="isReadOnly" <span translate *ngIf="isReadOnly"
fxLayoutAlign="center center" fxLayoutAlign="center center"
style="text-transform: uppercase; display: flex;" style="display: flex;"
class="mat-headline tb-absolute-fill">widgets-bundle.empty</span> class="mat-headline tb-absolute-fill">widgets-bundle.empty</span>
</section> </section>
<tb-dashboard #dashboard <tb-dashboard #dashboard

1
ui-ngx/src/app/modules/login/pages/login/login.component.scss

@ -75,7 +75,6 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
text-transform: uppercase;
} }
} }
} }

1
ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.scss

@ -77,7 +77,6 @@
label { label {
padding: 4px; padding: 4px;
color: #00acc1; color: #00acc1;
text-transform: uppercase;
background: rgba(220, 220, 220, .35); background: rgba(220, 220, 220, .35);
border-radius: 5px; border-radius: 5px;
} }

5
ui-ngx/src/app/shared/components/json-form/react/json-form.scss

@ -178,7 +178,6 @@ $previewSize: 100px !default;
label { label {
padding: 4px; padding: 4px;
color: #00acc1; color: #00acc1;
text-transform: uppercase;
background: rgba(220, 220, 220, .35); background: rgba(220, 220, 220, .35);
border-radius: 5px; border-radius: 5px;
} }
@ -263,6 +262,10 @@ $previewSize: 100px !default;
transform: translate(0%, -50%) !important; transform: translate(0%, -50%) !important;
} }
.MuiButton-root {
text-transform: none;
}
} }
.rc-select { .rc-select {

1
ui-ngx/src/app/shared/components/kv-map.component.scss

@ -19,7 +19,6 @@
position: relative; position: relative;
display: flex; display: flex;
height: 40px; height: 40px;
text-transform: uppercase;
&.disabled { &.disabled {
color: rgba(0, 0, 0, .38); color: rgba(0, 0, 0, .38);

2
ui-ngx/src/app/shared/components/logo.component.ts

@ -23,7 +23,7 @@ import { Component } from '@angular/core';
}) })
export class LogoComponent { export class LogoComponent {
logo = require('../../../assets/logo_title_white.svg').default; logo = 'assets/logo_title_white.svg';
gotoThingsboard(): void { gotoThingsboard(): void {
window.open('https://thingsboard.io', '_blank'); window.open('https://thingsboard.io', '_blank');

4
ui-ngx/src/app/shared/components/nav-tree.component.ts

@ -150,13 +150,13 @@ export class NavTreeComponent implements OnInit {
this.treeElement.on('changed.jstree', (e: any, data) => { this.treeElement.on('changed.jstree', (e: any, data) => {
const node: NavTreeNode = data.instance.get_selected(true)[0]; const node: NavTreeNode = data.instance.get_selected(true)[0];
if (this.onNodeSelected) { if (this.onNodeSelected) {
this.onNodeSelected(node, e as Event); this.ngZone.run(() => this.onNodeSelected(node, e as Event));
} }
}); });
this.treeElement.on('model.jstree', (e: any, data) => { this.treeElement.on('model.jstree', (e: any, data) => {
if (this.onNodesInserted) { if (this.onNodesInserted) {
this.onNodesInserted(data.nodes, data.parent); this.ngZone.run(() => this.onNodesInserted(data.nodes, data.parent));
} }
}); });

10
ui-ngx/src/styles.scss

@ -331,7 +331,6 @@ pre.tb-highlight {
font-weight: 400; font-weight: 400;
line-height: 18px; line-height: 18px;
color: rgba(0, 0, 0, .38); color: rgba(0, 0, 0, .38);
text-transform: uppercase;
} }
.tb-fullscreen { .tb-fullscreen {
@ -482,10 +481,6 @@ mat-label {
pointer-events: all; pointer-events: all;
} }
button:not(.mat-menu-item):not(.mat-sort-header-button) {
text-transform: uppercase;
}
button.mat-menu-item { button.mat-menu-item {
font-size: 15px; font-size: 15px;
} }
@ -965,7 +960,6 @@ mat-label {
position: relative; position: relative;
display: flex; display: flex;
height: calc(100% - 60px); height: calc(100% - 60px);
text-transform: uppercase;
text-align: center; text-align: center;
} }
@ -974,10 +968,6 @@ mat-label {
margin-top: -50px; margin-top: -50px;
} }
.mat-tab-label {
text-transform: uppercase;
}
.tb-primary-background { .tb-primary-background {
background-color: $primary; background-color: $primary;
} }

2
ui-ngx/src/tsconfig.app.json

@ -1,5 +1,5 @@
{ {
"extends": "../tsconfig.base.json", "extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../out-tsc/app", "outDir": "../out-tsc/app",
"types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify", "types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify",

2
ui-ngx/src/tsconfig.spec.json

@ -1,5 +1,5 @@
{ {
"extends": "../tsconfig.base.json", "extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../out-tsc/spec", "outDir": "../out-tsc/spec",
"types": [ "types": [

45
ui-ngx/tsconfig.base.json

@ -1,45 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2020",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"target": "es5",
"jsx": "react",
"typeRoots": [
"node_modules/@types",
"src/typings/rawloader.typings.d.ts",
"src/typings/jquery.typings.d.ts",
"src/typings/jquery.flot.typings.d.ts",
"src/typings/jquery.jstree.typings.d.ts",
"src/typings/split.js.typings.d.ts",
"src/typings/add-marker.d.ts",
"src/typings/leaflet-editable.d.ts"
],
"paths": {
"@app/*": ["src/app/*"],
"@env/*": [
"src/environments/*"
],
"@core/*": ["src/app/core/*"],
"@modules/*": ["src/app/modules/*"],
"@shared/*": ["src/app/shared/*"],
"@home/*": ["src/app/modules/home/*"],
"jszip": [
"node_modules/jszip/dist/jszip.min.js"
]
},
"lib": [
"es2018",
"es2019",
"dom"
]
}
}

61
ui-ngx/tsconfig.json

@ -1,20 +1,45 @@
/*
This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
It is not intended to be used to perform a compilation.
To learn more about this file see: https://angular.io/config/solution-tsconfig.
*/
{ {
"files": [], "compileOnSave": false,
"references": [ "compilerOptions": {
{ "baseUrl": "./",
"path": "./src/tsconfig.app.json" "outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2020",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"target": "es5",
"jsx": "react",
"typeRoots": [
"node_modules/@types",
"src/typings/rawloader.typings.d.ts",
"src/typings/jquery.typings.d.ts",
"src/typings/jquery.flot.typings.d.ts",
"src/typings/jquery.jstree.typings.d.ts",
"src/typings/split.js.typings.d.ts",
"src/typings/add-marker.d.ts",
"src/typings/leaflet-editable.d.ts"
],
"paths": {
"@app/*": ["src/app/*"],
"@env/*": [
"src/environments/*"
],
"@core/*": ["src/app/core/*"],
"@modules/*": ["src/app/modules/*"],
"@shared/*": ["src/app/shared/*"],
"@home/*": ["src/app/modules/home/*"],
"jszip": [
"node_modules/jszip/dist/jszip.min.js"
]
}, },
{ "lib": [
"path": "./src/tsconfig.spec.json" "es2018",
}, "es2019",
{ "dom"
"path": "./e2e/tsconfig.e2e.json" ]
} }
] }
}

2040
ui-ngx/yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save