Commit c4fd267f9e091d9a5a74746fe368833bb34d9a58

Authored by Andrii Shvaika
2 parents 77ccf037 4b0aae89

Merge branch 'master' of github.com:thingsboard/thingsboard into develop/3.0

@@ -182,11 +182,12 @@ public class TelemetryController extends BaseController { @@ -182,11 +182,12 @@ public class TelemetryController extends BaseController {
182 @ResponseBody 182 @ResponseBody
183 public DeferredResult<ResponseEntity> getLatestTimeseries( 183 public DeferredResult<ResponseEntity> getLatestTimeseries(
184 @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, 184 @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr,
185 - @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { 185 + @RequestParam(name = "keys", required = false) String keysStr,
  186 + @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
186 SecurityUser user = getCurrentUser(); 187 SecurityUser user = getCurrentUser();
187 188
188 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, 189 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
189 - (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr)); 190 + (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes));
190 } 191 }
191 192
192 193
@@ -200,8 +201,8 @@ public class TelemetryController extends BaseController { @@ -200,8 +201,8 @@ public class TelemetryController extends BaseController {
200 @RequestParam(name = "endTs") Long endTs, 201 @RequestParam(name = "endTs") Long endTs,
201 @RequestParam(name = "interval", defaultValue = "0") Long interval, 202 @RequestParam(name = "interval", defaultValue = "0") Long interval,
202 @RequestParam(name = "limit", defaultValue = "100") Integer limit, 203 @RequestParam(name = "limit", defaultValue = "100") Integer limit,
203 - @RequestParam(name = "agg", defaultValue = "NONE") String aggStr  
204 - ) throws ThingsboardException { 204 + @RequestParam(name = "agg", defaultValue = "NONE") String aggStr,
  205 + @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
205 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, 206 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
206 (result, tenantId, entityId) -> { 207 (result, tenantId, entityId) -> {
207 // If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted 208 // If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted
@@ -209,7 +210,7 @@ public class TelemetryController extends BaseController { @@ -209,7 +210,7 @@ public class TelemetryController extends BaseController {
209 List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg)) 210 List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg))
210 .collect(Collectors.toList()); 211 .collect(Collectors.toList());
211 212
212 - Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result)); 213 + Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes));
213 }); 214 });
214 } 215 }
215 216
@@ -454,14 +455,14 @@ public class TelemetryController extends BaseController { @@ -454,14 +455,14 @@ public class TelemetryController extends BaseController {
454 }); 455 });
455 } 456 }
456 457
457 - private void getLatestTimeseriesValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String keys) { 458 + private void getLatestTimeseriesValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String keys, Boolean useStrictDataTypes) {
458 ListenableFuture<List<TsKvEntry>> future; 459 ListenableFuture<List<TsKvEntry>> future;
459 if (StringUtils.isEmpty(keys)) { 460 if (StringUtils.isEmpty(keys)) {
460 future = tsService.findAllLatest(user.getTenantId(), entityId); 461 future = tsService.findAllLatest(user.getTenantId(), entityId);
461 } else { 462 } else {
462 future = tsService.findLatest(user.getTenantId(), entityId, toKeysList(keys)); 463 future = tsService.findLatest(user.getTenantId(), entityId, toKeysList(keys));
463 } 464 }
464 - Futures.addCallback(future, getTsKvListCallback(result)); 465 + Futures.addCallback(future, getTsKvListCallback(result, useStrictDataTypes));
465 } 466 }
466 467
467 private void getAttributeValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String scope, String keys) { 468 private void getAttributeValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String scope, String keys) {
@@ -544,7 +545,7 @@ public class TelemetryController extends BaseController { @@ -544,7 +545,7 @@ public class TelemetryController extends BaseController {
544 @Override 545 @Override
545 public void onSuccess(List<AttributeKvEntry> attributes) { 546 public void onSuccess(List<AttributeKvEntry> attributes) {
546 List<AttributeData> values = attributes.stream().map(attribute -> 547 List<AttributeData> values = attributes.stream().map(attribute ->
547 - new AttributeData(attribute.getLastUpdateTs(), attribute.getKey(), getKvValue(attribute)) 548 + new AttributeData(attribute.getLastUpdateTs(), attribute.getKey(), getKvValue(attribute))
548 ).collect(Collectors.toList()); 549 ).collect(Collectors.toList());
549 logAttributesRead(user, entityId, scope, keyList, null); 550 logAttributesRead(user, entityId, scope, keyList, null);
550 response.setResult(new ResponseEntity<>(values, HttpStatus.OK)); 551 response.setResult(new ResponseEntity<>(values, HttpStatus.OK));
@@ -559,14 +560,14 @@ public class TelemetryController extends BaseController { @@ -559,14 +560,14 @@ public class TelemetryController extends BaseController {
559 }; 560 };
560 } 561 }
561 562
562 - private FutureCallback<List<TsKvEntry>> getTsKvListCallback(final DeferredResult<ResponseEntity> response) { 563 + private FutureCallback<List<TsKvEntry>> getTsKvListCallback(final DeferredResult<ResponseEntity> response, Boolean useStrictDataTypes) {
563 return new FutureCallback<List<TsKvEntry>>() { 564 return new FutureCallback<List<TsKvEntry>>() {
564 @Override 565 @Override
565 public void onSuccess(List<TsKvEntry> data) { 566 public void onSuccess(List<TsKvEntry> data) {
566 Map<String, List<TsData>> result = new LinkedHashMap<>(); 567 Map<String, List<TsData>> result = new LinkedHashMap<>();
567 for (TsKvEntry entry : data) { 568 for (TsKvEntry entry : data) {
568 - result.computeIfAbsent(entry.getKey(), k -> new ArrayList<>())  
569 - .add(new TsData(entry.getTs(), entry.getValueAsString())); 569 + Object value = useStrictDataTypes ? getKvValue(entry) : entry.getValueAsString();
  570 + result.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).add(new TsData(entry.getTs(), value));
570 } 571 }
571 response.setResult(new ResponseEntity<>(result, HttpStatus.OK)); 572 response.setResult(new ResponseEntity<>(result, HttpStatus.OK));
572 } 573 }
@@ -18,9 +18,9 @@ package org.thingsboard.server.service.telemetry; @@ -18,9 +18,9 @@ package org.thingsboard.server.service.telemetry;
18 public class TsData implements Comparable<TsData>{ 18 public class TsData implements Comparable<TsData>{
19 19
20 private final long ts; 20 private final long ts;
21 - private final String value; 21 + private final Object value;
22 22
23 - public TsData(long ts, String value) { 23 + public TsData(long ts, Object value) {
24 super(); 24 super();
25 this.ts = ts; 25 this.ts = ts;
26 this.value = value; 26 this.value = value;
@@ -30,7 +30,7 @@ public class TsData implements Comparable<TsData>{ @@ -30,7 +30,7 @@ public class TsData implements Comparable<TsData>{
30 return ts; 30 return ts;
31 } 31 }
32 32
33 - public String getValue() { 33 + public Object getValue() {
34 return value; 34 return value;
35 } 35 }
36 36
@@ -97,6 +97,7 @@ import java.util.HashMap; @@ -97,6 +97,7 @@ import java.util.HashMap;
97 import java.util.List; 97 import java.util.List;
98 import java.util.Map; 98 import java.util.Map;
99 import java.util.Optional; 99 import java.util.Optional;
  100 +import java.util.UUID;
100 import java.util.concurrent.ExecutorService; 101 import java.util.concurrent.ExecutorService;
101 import java.util.concurrent.Executors; 102 import java.util.concurrent.Executors;
102 import java.util.concurrent.Future; 103 import java.util.concurrent.Future;
@@ -1611,31 +1612,40 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1611,31 +1612,40 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1611 } 1612 }
1612 1613
1613 public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys) { 1614 public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys) {
  1615 + return getLatestTimeseries(entityId, keys, true);
  1616 + }
  1617 +
  1618 + public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys, boolean useStrictDataTypes) {
1614 Map<String, List<JsonNode>> timeseries = restTemplate.exchange( 1619 Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
1615 - baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}", 1620 + baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&useStrictDataTypes={useStrictDataTypes}",
1616 HttpMethod.GET, 1621 HttpMethod.GET,
1617 HttpEntity.EMPTY, 1622 HttpEntity.EMPTY,
1618 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { 1623 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {
1619 }, 1624 },
1620 entityId.getEntityType().name(), 1625 entityId.getEntityType().name(),
1621 entityId.getId().toString(), 1626 entityId.getId().toString(),
1622 - listToString(keys)).getBody(); 1627 + listToString(keys),
  1628 + useStrictDataTypes).getBody();
1623 1629
1624 return RestJsonConverter.toTimeseries(timeseries); 1630 return RestJsonConverter.toTimeseries(timeseries);
1625 } 1631 }
1626 1632
1627 -  
1628 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) { 1633 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) {
  1634 + return getTimeseries(entityId, keys, interval, agg, pageLink, true);
  1635 + }
  1636 +
  1637 + public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink, boolean useStrictDataTypes) {
1629 Map<String, String> params = new HashMap<>(); 1638 Map<String, String> params = new HashMap<>();
1630 - addPageLinkToParam(params, pageLink);  
1631 params.put("entityType", entityId.getEntityType().name()); 1639 params.put("entityType", entityId.getEntityType().name());
1632 params.put("entityId", entityId.getId().toString()); 1640 params.put("entityId", entityId.getId().toString());
1633 params.put("keys", listToString(keys)); 1641 params.put("keys", listToString(keys));
1634 params.put("interval", interval == null ? "0" : interval.toString()); 1642 params.put("interval", interval == null ? "0" : interval.toString());
1635 params.put("agg", agg == null ? "NONE" : agg.name()); 1643 params.put("agg", agg == null ? "NONE" : agg.name());
  1644 + params.put("useStrictDataTypes", Boolean.toString(useStrictDataTypes));
  1645 + addPageLinkToParam(params, pageLink);
1636 1646
1637 Map<String, List<JsonNode>> timeseries = restTemplate.exchange( 1647 Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
1638 - baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&" + getUrlParams(pageLink), 1648 + baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&" + getUrlParams(pageLink),
1639 HttpMethod.GET, 1649 HttpMethod.GET,
1640 HttpEntity.EMPTY, 1650 HttpEntity.EMPTY,
1641 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { 1651 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {