diff --git a/application/pom.xml b/application/pom.xml
index 72e7e7d7c2..c6503ef248 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
application
diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index 5eef1bdda0..b889143122 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -165,9 +165,9 @@ quota:
database:
entities:
- type: "${DATABASE_ENTITIES_TYPE:sql}" # cassandra OR sql
+ type: "${DATABASE_ENTITIES_TYPE:cassandra}" # cassandra OR sql
ts:
- type: "${DATABASE_TS_TYPE:sql}" # cassandra OR sql (for hybrid mode, only this value should be cassandra)
+ type: "${DATABASE_TS_TYPE:cassandra}" # cassandra OR sql (for hybrid mode, only this value should be cassandra)
# Cassandra driver configuration parameters
diff --git a/common/data/pom.xml b/common/data/pom.xml
index aa68b1adf6..f25e78de0e 100644
--- a/common/data/pom.xml
+++ b/common/data/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/message/pom.xml b/common/message/pom.xml
index 4da27e28f6..67648e9c4d 100644
--- a/common/message/pom.xml
+++ b/common/message/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/pom.xml b/common/pom.xml
index 4ee5937e7a..aba6d7f3a9 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
org.thingsboard
diff --git a/common/transport/pom.xml b/common/transport/pom.xml
index efd63b5240..583fcd28f7 100644
--- a/common/transport/pom.xml
+++ b/common/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
common
org.thingsboard.common
diff --git a/dao/pom.xml b/dao/pom.xml
index 8cc83e9393..e7d6783911 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
dao
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
index fe1a8d1f8d..6ddc18d463 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java
@@ -84,8 +84,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao>> futures = new ArrayList<>();
- if (savedEntityView.getKeys() != null) {
+ if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) {
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs()));
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs()));
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh()));
diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java
index 4a09bb7a23..4658cbe490 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java
@@ -79,12 +79,16 @@ public class BaseTimeseriesService implements TimeseriesService {
if (entityId.getEntityType().equals(EntityType.ENTITY_VIEW)) {
EntityView entityView = entityViewService.findEntityViewById((EntityViewId) entityId);
List filteredKeys = new ArrayList<>(keys);
- if (!entityView.getKeys().getTimeseries().isEmpty()) {
+ if (entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null &&
+ !entityView.getKeys().getTimeseries().isEmpty()) {
filteredKeys.retainAll(entityView.getKeys().getTimeseries());
}
List queries =
filteredKeys.stream()
- .map(key -> new BaseReadTsKvQuery(key, entityView.getStartTimeMs(), entityView.getEndTimeMs(), 1, "ASC"))
+ .map(key -> {
+ long endTs = entityView.getEndTimeMs() != 0 ? entityView.getEndTimeMs() : Long.MAX_VALUE;
+ return new BaseReadTsKvQuery(key, entityView.getStartTimeMs(), endTs, 1, "DESC");
+ })
.collect(Collectors.toList());
if (queries.size() > 0) {
@@ -100,7 +104,17 @@ public class BaseTimeseriesService implements TimeseriesService {
@Override
public ListenableFuture> findAllLatest(EntityId entityId) {
validate(entityId);
- return timeseriesDao.findAllLatest(entityId);
+ if (entityId.getEntityType().equals(EntityType.ENTITY_VIEW)) {
+ EntityView entityView = entityViewService.findEntityViewById((EntityViewId) entityId);
+ if (entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null &&
+ !entityView.getKeys().getTimeseries().isEmpty()) {
+ return findLatest(entityId, entityView.getKeys().getTimeseries());
+ } else {
+ return Futures.immediateFuture(new ArrayList<>());
+ }
+ } else {
+ return timeseriesDao.findAllLatest(entityId);
+ }
}
@Override
diff --git a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java
index 9e56d64aba..0eaebfbbdc 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java
@@ -24,7 +24,7 @@ import java.util.Arrays;
@RunWith(ClasspathSuite.class)
@ClassnameFilters({
- "org.thingsboard.server.dao.service.*ServiceSqlTest"
+ "org.thingsboard.server.dao.service.*.TimeseriesServiceSqlTest"
})
public class SqlDaoServiceTestSuite {
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
index 1e1f15daff..f49c357caa 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
@@ -45,6 +45,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService;
+import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rule.RuleChainService;
@@ -88,6 +89,9 @@ public abstract class AbstractServiceTest {
@Autowired
protected AssetService assetService;
+ @Autowired
+ protected EntityViewService entityViewService;
+
@Autowired
protected DeviceCredentialsService deviceCredentialsService;
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java
index 4528d9afb1..88f4d84eb6 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java
@@ -17,9 +17,15 @@ package org.thingsboard.server.dao.service.timeseries;
import com.datastax.driver.core.utils.UUIDs;
import lombok.extern.slf4j.Slf4j;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
+import org.thingsboard.server.common.data.EntityView;
+import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.Aggregation;
import org.thingsboard.server.common.data.kv.BaseDeleteTsKvQuery;
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
@@ -30,6 +36,7 @@ import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
+import org.thingsboard.server.common.data.objects.TelemetryEntityView;
import org.thingsboard.server.dao.service.AbstractServiceTest;
import java.util.ArrayList;
@@ -61,6 +68,22 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
KvEntry doubleKvEntry = new DoubleDataEntry(DOUBLE_KEY, Double.MAX_VALUE);
KvEntry booleanKvEntry = new BooleanDataEntry(BOOLEAN_KEY, Boolean.TRUE);
+ private TenantId tenantId;
+
+ @Before
+ public void before() {
+ Tenant tenant = new Tenant();
+ tenant.setTitle("My tenant");
+ Tenant savedTenant = tenantService.saveTenant(tenant);
+ Assert.assertNotNull(savedTenant);
+ tenantId = savedTenant.getId();
+ }
+
+ @After
+ public void after() {
+ tenantService.deleteTenant(tenantId);
+ }
+
@Test
public void testFindAllLatest() throws Exception {
DeviceId deviceId = new DeviceId(UUIDs.timeBased());
@@ -69,7 +92,15 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
saveEntries(deviceId, TS - 1);
saveEntries(deviceId, TS);
- List tsList = tsService.findAllLatest(deviceId).get();
+ testLatestTsAndVerify(deviceId);
+
+ EntityView entityView = saveAndCreateEntityView(deviceId, Arrays.asList(STRING_KEY, DOUBLE_KEY, LONG_KEY, BOOLEAN_KEY));
+
+ testLatestTsAndVerify(entityView.getId());
+ }
+
+ private void testLatestTsAndVerify(EntityId entityId) throws ExecutionException, InterruptedException {
+ List tsList = tsService.findAllLatest(entityId).get();
assertNotNull(tsList);
assertEquals(4, tsList.size());
@@ -89,6 +120,18 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
assertEquals(expected, tsList);
}
+ private EntityView saveAndCreateEntityView(DeviceId deviceId, List timeseries) {
+ EntityView entityView = new EntityView();
+ entityView.setName("entity_view_name");
+ entityView.setType("default");
+ entityView.setTenantId(tenantId);
+ TelemetryEntityView keys = new TelemetryEntityView();
+ keys.setTimeseries(timeseries);
+ entityView.setKeys(keys);
+ entityView.setEntityId(deviceId);
+ return entityViewService.saveEntityView(entityView);
+ }
+
@Test
public void testFindLatest() throws Exception {
DeviceId deviceId = new DeviceId(UUIDs.timeBased());
@@ -100,6 +143,12 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest {
List entries = tsService.findLatest(deviceId, Collections.singleton(STRING_KEY)).get();
Assert.assertEquals(1, entries.size());
Assert.assertEquals(toTsEntry(TS, stringKvEntry), entries.get(0));
+
+ EntityView entityView = saveAndCreateEntityView(deviceId, Arrays.asList(STRING_KEY));
+
+ entries = tsService.findLatest(entityView.getId(), Collections.singleton(STRING_KEY)).get();
+ Assert.assertEquals(1, entries.size());
+ Assert.assertEquals(toTsEntry(TS, stringKvEntry), entries.get(0));
}
@Test
diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml
index f7e32b53e7..0b1ea1e35e 100644
--- a/netty-mqtt/pom.xml
+++ b/netty-mqtt/pom.xml
@@ -19,12 +19,12 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
org.thingsboard
netty-mqtt
- 2.1.2
+ 2.1.3-SNAPSHOT
jar
Netty MQTT Client
diff --git a/pom.xml b/pom.xml
index 981482b35a..05ab0d6f39 100755
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
pom
Thingsboard
diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml
index 5c5fe56075..3847120030 100644
--- a/rule-engine/pom.xml
+++ b/rule-engine/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
rule-engine
diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml
index 4b4f33624f..4e79b11056 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
- 2.1.2
+ 2.1.3-SNAPSHOT
rule-engine
org.thingsboard.rule-engine
diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml
index ebab903190..6e7cfdc6a7 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
- 2.1.2
+ 2.1.3-SNAPSHOT
rule-engine
org.thingsboard.rule-engine
diff --git a/tools/pom.xml b/tools/pom.xml
index 8a9481d0b9..af4c53b4a1 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
org.thingsboard
diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml
index 537a9bee06..bcb45236c1 100644
--- a/transport/coap/pom.xml
+++ b/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/http/pom.xml b/transport/http/pom.xml
index 24e4ff94af..d73692f260 100644
--- a/transport/http/pom.xml
+++ b/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml
index f5c1104b6a..e89bba42b1 100644
--- a/transport/mqtt/pom.xml
+++ b/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/pom.xml b/transport/pom.xml
index 7858383d82..22ec9be255 100644
--- a/transport/pom.xml
+++ b/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
org.thingsboard
diff --git a/ui/pom.xml b/ui/pom.xml
index a2eadb5445..c219a22e6b 100644
--- a/ui/pom.xml
+++ b/ui/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 2.1.2
+ 2.1.3-SNAPSHOT
thingsboard
org.thingsboard
diff --git a/ui/src/app/entity-view/entity-view-fieldset.tpl.html b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
index 66dc116cc8..74d1e3397c 100644
--- a/ui/src/app/entity-view/entity-view-fieldset.tpl.html
+++ b/ui/src/app/entity-view/entity-view-fieldset.tpl.html
@@ -78,31 +78,79 @@
ng-required="false"
readonly="!isEdit"
ng-model="entityView.keys.attributes.cs"
- placeholder="{{'entity-view.client-attributes' | translate}}"
+ placeholder="{{'entity-view.client-attributes-placeholder' | translate}}"
md-separator-keys="separatorKeys">
+
+ {{item}}
+
+
+ {{item}}
+
+
+ {{item}}
+
-
+
+
+ {{item}}
+
diff --git a/ui/src/app/entity-view/entity-view.directive.js b/ui/src/app/entity-view/entity-view.directive.js
index e1ae82fa6a..d183053f47 100644
--- a/ui/src/app/entity-view/entity-view.directive.js
+++ b/ui/src/app/entity-view/entity-view.directive.js
@@ -20,8 +20,8 @@ import entityViewFieldsetTemplate from './entity-view-fieldset.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function EntityViewDirective($compile, $templateCache, $filter, toast, $translate, $mdConstant,
- types, clipboardService, entityViewService, customerService) {
+export default function EntityViewDirective($q, $compile, $templateCache, $filter, toast, $translate, $mdConstant,
+ types, clipboardService, entityViewService, customerService, entityService) {
var linker = function (scope, element) {
var template = $templateCache.get(entityViewFieldsetTemplate);
element.html(template);
@@ -53,9 +53,13 @@ export default function EntityViewDirective($compile, $templateCache, $filter, t
}
if (scope.entityView.startTimeMs > 0) {
scope.startTimeMs = new Date(scope.entityView.startTimeMs);
+ } else {
+ scope.startTimeMs = null;
}
if (scope.entityView.endTimeMs > 0) {
scope.endTimeMs = new Date(scope.entityView.endTimeMs);
+ } else {
+ scope.endTimeMs = null;
}
if (!scope.entityView.keys) {
scope.entityView.keys = {};
@@ -68,6 +72,19 @@ export default function EntityViewDirective($compile, $templateCache, $filter, t
}
});
+ scope.dataKeysSearch = function (searchText, type) {
+ var deferred = $q.defer();
+ entityService.getEntityKeys(scope.entityView.entityId.entityType, scope.entityView.entityId.id, searchText, type, {ignoreLoading: true}).then(
+ function success(keys) {
+ deferred.resolve(keys);
+ },
+ function fail() {
+ deferred.resolve([]);
+ }
+ );
+ return deferred.promise;
+
+ };
scope.$watch('startTimeMs', function (newDate) {
if (newDate) {
diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json
index 6c6ea438af..ccfcf659ac 100644
--- a/ui/src/app/locale/locale.constant-en_US.json
+++ b/ui/src/app/locale/locale.constant-en_US.json
@@ -844,7 +844,11 @@
"client-attributes": "Client attributes",
"shared-attributes": "Shared attributes",
"server-attributes": "Server attributes",
- "latest-timeseries": "Latest timeseries",
+ "timeseries": "Timeseries",
+ "client-attributes-placeholder": "Client attributes",
+ "shared-attributes-placeholder": "Shared attributes",
+ "server-attributes-placeholder": "Server attributes",
+ "timeseries-placeholder": "Timeseries",
"related-entity": "Related entity"
},
"event": {
diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json
index 285c589bd6..1b0a16939b 100644
--- a/ui/src/app/locale/locale.constant-es_ES.json
+++ b/ui/src/app/locale/locale.constant-es_ES.json
@@ -839,7 +839,7 @@
"client-attributes": "Client attributes",
"shared-attributes": "Shared attributes",
"server-attributes": "Server attributes",
- "latest-timeseries": "Latest timeseries"
+ "timeseries": "Timeseries"
},
"event": {
"event-type": "Tipo de evento",