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

This commit is contained in:
Andrii Shvaika 2020-02-21 18:01:45 +02:00
commit c4fd267f9e
3 changed files with 30 additions and 19 deletions

View File

@ -182,11 +182,12 @@ public class TelemetryController extends BaseController {
@ResponseBody @ResponseBody
public DeferredResult<ResponseEntity> getLatestTimeseries( public DeferredResult<ResponseEntity> getLatestTimeseries(
@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr,
@RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { @RequestParam(name = "keys", required = false) String keysStr,
@RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
SecurityUser user = getCurrentUser(); SecurityUser user = getCurrentUser();
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
(result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr)); (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes));
} }
@ -200,8 +201,8 @@ public class TelemetryController extends BaseController {
@RequestParam(name = "endTs") Long endTs, @RequestParam(name = "endTs") Long endTs,
@RequestParam(name = "interval", defaultValue = "0") Long interval, @RequestParam(name = "interval", defaultValue = "0") Long interval,
@RequestParam(name = "limit", defaultValue = "100") Integer limit, @RequestParam(name = "limit", defaultValue = "100") Integer limit,
@RequestParam(name = "agg", defaultValue = "NONE") String aggStr @RequestParam(name = "agg", defaultValue = "NONE") String aggStr,
) throws ThingsboardException { @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
(result, tenantId, entityId) -> { (result, tenantId, entityId) -> {
// If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted // 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 {
List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg)) List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg))
.collect(Collectors.toList()); .collect(Collectors.toList());
Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result)); Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes));
}); });
} }
@ -454,14 +455,14 @@ public class TelemetryController extends BaseController {
}); });
} }
private void getLatestTimeseriesValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String keys) { private void getLatestTimeseriesValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String keys, Boolean useStrictDataTypes) {
ListenableFuture<List<TsKvEntry>> future; ListenableFuture<List<TsKvEntry>> future;
if (StringUtils.isEmpty(keys)) { if (StringUtils.isEmpty(keys)) {
future = tsService.findAllLatest(user.getTenantId(), entityId); future = tsService.findAllLatest(user.getTenantId(), entityId);
} else { } else {
future = tsService.findLatest(user.getTenantId(), entityId, toKeysList(keys)); future = tsService.findLatest(user.getTenantId(), entityId, toKeysList(keys));
} }
Futures.addCallback(future, getTsKvListCallback(result)); Futures.addCallback(future, getTsKvListCallback(result, useStrictDataTypes));
} }
private void getAttributeValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String scope, String keys) { private void getAttributeValuesCallback(@Nullable DeferredResult<ResponseEntity> result, SecurityUser user, EntityId entityId, String scope, String keys) {
@ -559,14 +560,14 @@ public class TelemetryController extends BaseController {
}; };
} }
private FutureCallback<List<TsKvEntry>> getTsKvListCallback(final DeferredResult<ResponseEntity> response) { private FutureCallback<List<TsKvEntry>> getTsKvListCallback(final DeferredResult<ResponseEntity> response, Boolean useStrictDataTypes) {
return new FutureCallback<List<TsKvEntry>>() { return new FutureCallback<List<TsKvEntry>>() {
@Override @Override
public void onSuccess(List<TsKvEntry> data) { public void onSuccess(List<TsKvEntry> data) {
Map<String, List<TsData>> result = new LinkedHashMap<>(); Map<String, List<TsData>> result = new LinkedHashMap<>();
for (TsKvEntry entry : data) { for (TsKvEntry entry : data) {
result.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()) Object value = useStrictDataTypes ? getKvValue(entry) : entry.getValueAsString();
.add(new TsData(entry.getTs(), entry.getValueAsString())); result.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).add(new TsData(entry.getTs(), value));
} }
response.setResult(new ResponseEntity<>(result, HttpStatus.OK)); response.setResult(new ResponseEntity<>(result, HttpStatus.OK));
} }

View File

@ -18,9 +18,9 @@ package org.thingsboard.server.service.telemetry;
public class TsData implements Comparable<TsData>{ public class TsData implements Comparable<TsData>{
private final long ts; private final long ts;
private final String value; private final Object value;
public TsData(long ts, String value) { public TsData(long ts, Object value) {
super(); super();
this.ts = ts; this.ts = ts;
this.value = value; this.value = value;
@ -30,7 +30,7 @@ public class TsData implements Comparable<TsData>{
return ts; return ts;
} }
public String getValue() { public Object getValue() {
return value; return value;
} }

View File

@ -97,6 +97,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -1611,31 +1612,40 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
} }
public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys) { public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys) {
return getLatestTimeseries(entityId, keys, true);
}
public List<TsKvEntry> getLatestTimeseries(EntityId entityId, List<String> keys, boolean useStrictDataTypes) {
Map<String, List<JsonNode>> timeseries = restTemplate.exchange( Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}", baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&useStrictDataTypes={useStrictDataTypes}",
HttpMethod.GET, HttpMethod.GET,
HttpEntity.EMPTY, HttpEntity.EMPTY,
new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {
}, },
entityId.getEntityType().name(), entityId.getEntityType().name(),
entityId.getId().toString(), entityId.getId().toString(),
listToString(keys)).getBody(); listToString(keys),
useStrictDataTypes).getBody();
return RestJsonConverter.toTimeseries(timeseries); return RestJsonConverter.toTimeseries(timeseries);
} }
public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) { public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) {
return getTimeseries(entityId, keys, interval, agg, pageLink, true);
}
public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink, boolean useStrictDataTypes) {
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
addPageLinkToParam(params, pageLink);
params.put("entityType", entityId.getEntityType().name()); params.put("entityType", entityId.getEntityType().name());
params.put("entityId", entityId.getId().toString()); params.put("entityId", entityId.getId().toString());
params.put("keys", listToString(keys)); params.put("keys", listToString(keys));
params.put("interval", interval == null ? "0" : interval.toString()); params.put("interval", interval == null ? "0" : interval.toString());
params.put("agg", agg == null ? "NONE" : agg.name()); params.put("agg", agg == null ? "NONE" : agg.name());
params.put("useStrictDataTypes", Boolean.toString(useStrictDataTypes));
addPageLinkToParam(params, pageLink);
Map<String, List<JsonNode>> timeseries = restTemplate.exchange( Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&" + getUrlParams(pageLink), baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&" + getUrlParams(pageLink),
HttpMethod.GET, HttpMethod.GET,
HttpEntity.EMPTY, HttpEntity.EMPTY,
new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {