Commit 4b0aae896dde86e6a7f26ea1c06d72a04b24123f

Authored by Andrii Shvaika
1 parent e207545c

Rest API support of strict data types in getTelemetry requests

@@ -183,11 +183,11 @@ public class TelemetryController extends BaseController { @@ -183,11 +183,11 @@ public class TelemetryController extends BaseController {
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, 185 @RequestParam(name = "keys", required = false) String keysStr,
186 - @RequestParam(name = "useStrictType", required = false, defaultValue = "false") Boolean useStrictType) throws ThingsboardException { 186 + @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
187 SecurityUser user = getCurrentUser(); 187 SecurityUser user = getCurrentUser();
188 188
189 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, 189 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
190 - (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictType)); 190 + (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes));
191 } 191 }
192 192
193 193
@@ -202,7 +202,7 @@ public class TelemetryController extends BaseController { @@ -202,7 +202,7 @@ public class TelemetryController extends BaseController {
202 @RequestParam(name = "interval", defaultValue = "0") Long interval, 202 @RequestParam(name = "interval", defaultValue = "0") Long interval,
203 @RequestParam(name = "limit", defaultValue = "100") Integer limit, 203 @RequestParam(name = "limit", defaultValue = "100") Integer limit,
204 @RequestParam(name = "agg", defaultValue = "NONE") String aggStr, 204 @RequestParam(name = "agg", defaultValue = "NONE") String aggStr,
205 - @RequestParam(name = "useStrictType", required = false, defaultValue = "false") Boolean useStrictType) throws ThingsboardException { 205 + @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
206 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, 206 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
207 (result, tenantId, entityId) -> { 207 (result, tenantId, entityId) -> {
208 // 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
@@ -210,7 +210,7 @@ public class TelemetryController extends BaseController { @@ -210,7 +210,7 @@ public class TelemetryController extends BaseController {
210 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))
211 .collect(Collectors.toList()); 211 .collect(Collectors.toList());
212 212
213 - Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictType)); 213 + Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes));
214 }); 214 });
215 } 215 }
216 216
@@ -455,14 +455,14 @@ public class TelemetryController extends BaseController { @@ -455,14 +455,14 @@ public class TelemetryController extends BaseController {
455 }); 455 });
456 } 456 }
457 457
458 - private void getLatestTimeseriesValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String keys, Boolean useStrictType) { 458 + private void getLatestTimeseriesValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String keys, Boolean useStrictDataTypes) {
459 ListenableFuture<List<TsKvEntry>> future; 459 ListenableFuture<List<TsKvEntry>> future;
460 if (StringUtils.isEmpty(keys)) { 460 if (StringUtils.isEmpty(keys)) {
461 future = tsService.findAllLatest(user.getTenantId(), entityId); 461 future = tsService.findAllLatest(user.getTenantId(), entityId);
462 } else { 462 } else {
463 future = tsService.findLatest(user.getTenantId(), entityId, toKeysList(keys)); 463 future = tsService.findLatest(user.getTenantId(), entityId, toKeysList(keys));
464 } 464 }
465 - Futures.addCallback(future, getTsKvListCallback(result, useStrictType)); 465 + Futures.addCallback(future, getTsKvListCallback(result, useStrictDataTypes));
466 } 466 }
467 467
468 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) {
@@ -560,13 +560,13 @@ public class TelemetryController extends BaseController { @@ -560,13 +560,13 @@ public class TelemetryController extends BaseController {
560 }; 560 };
561 } 561 }
562 562
563 - private FutureCallback<List<TsKvEntry>> getTsKvListCallback(final DeferredResult<ResponseEntity> response, Boolean useStrictType) { 563 + private FutureCallback<List<TsKvEntry>> getTsKvListCallback(final DeferredResult<ResponseEntity> response, Boolean useStrictDataTypes) {
564 return new FutureCallback<List<TsKvEntry>>() { 564 return new FutureCallback<List<TsKvEntry>>() {
565 @Override 565 @Override
566 public void onSuccess(List<TsKvEntry> data) { 566 public void onSuccess(List<TsKvEntry> data) {
567 Map<String, List<TsData>> result = new LinkedHashMap<>(); 567 Map<String, List<TsData>> result = new LinkedHashMap<>();
568 for (TsKvEntry entry : data) { 568 for (TsKvEntry entry : data) {
569 - Object value = useStrictType ? getKvValue(entry) : 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 result.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).add(new TsData(entry.getTs(), value));
571 } 571 }
572 response.setResult(new ResponseEntity<>(result, HttpStatus.OK)); 572 response.setResult(new ResponseEntity<>(result, HttpStatus.OK));
@@ -98,6 +98,7 @@ import java.util.HashMap; @@ -98,6 +98,7 @@ import java.util.HashMap;
98 import java.util.List; 98 import java.util.List;
99 import java.util.Map; 99 import java.util.Map;
100 import java.util.Optional; 100 import java.util.Optional;
  101 +import java.util.UUID;
101 import java.util.concurrent.ExecutorService; 102 import java.util.concurrent.ExecutorService;
102 import java.util.concurrent.Executors; 103 import java.util.concurrent.Executors;
103 import java.util.concurrent.Future; 104 import java.util.concurrent.Future;
@@ -1612,31 +1613,40 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1612,31 +1613,40 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1612 } 1613 }
1613 1614
1614 public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys) { 1615 public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys) {
  1616 + return getLatestTimeseries(entityId, keys, true);
  1617 + }
  1618 +
  1619 + public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys, boolean useStrictDataTypes) {
1615 Map<String, List<JsonNode>> timeseries = restTemplate.exchange( 1620 Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
1616 - baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}", 1621 + baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&useStrictDataTypes={useStrictDataTypes}",
1617 HttpMethod.GET, 1622 HttpMethod.GET,
1618 HttpEntity.EMPTY, 1623 HttpEntity.EMPTY,
1619 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { 1624 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {
1620 }, 1625 },
1621 entityId.getEntityType().name(), 1626 entityId.getEntityType().name(),
1622 entityId.getId().toString(), 1627 entityId.getId().toString(),
1623 - listToString(keys)).getBody(); 1628 + listToString(keys),
  1629 + useStrictDataTypes).getBody();
1624 1630
1625 return RestJsonConverter.toTimeseries(timeseries); 1631 return RestJsonConverter.toTimeseries(timeseries);
1626 } 1632 }
1627 1633
1628 -  
1629 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) { 1634 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) {
  1635 + return getTimeseries(entityId, keys, interval, agg, pageLink, true);
  1636 + }
  1637 +
  1638 + public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink, boolean useStrictDataTypes) {
1630 Map<String, String> params = new HashMap<>(); 1639 Map<String, String> params = new HashMap<>();
1631 - addPageLinkToParam(params, pageLink);  
1632 params.put("entityType", entityId.getEntityType().name()); 1640 params.put("entityType", entityId.getEntityType().name());
1633 params.put("entityId", entityId.getId().toString()); 1641 params.put("entityId", entityId.getId().toString());
1634 params.put("keys", listToString(keys)); 1642 params.put("keys", listToString(keys));
1635 params.put("interval", interval == null ? "0" : interval.toString()); 1643 params.put("interval", interval == null ? "0" : interval.toString());
1636 params.put("agg", agg == null ? "NONE" : agg.name()); 1644 params.put("agg", agg == null ? "NONE" : agg.name());
  1645 + params.put("useStrictDataTypes", Boolean.toString(useStrictDataTypes));
  1646 + addPageLinkToParam(params, pageLink);
1637 1647
1638 Map<String, List<JsonNode>> timeseries = restTemplate.exchange( 1648 Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
1639 - baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&" + getUrlParams(pageLink), 1649 + baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&" + getUrlParams(pageLink),
1640 HttpMethod.GET, 1650 HttpMethod.GET,
1641 HttpEntity.EMPTY, 1651 HttpEntity.EMPTY,
1642 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { 1652 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {