Merge pull request #13669 from thingsboard/fix/telemetry-controller
Fixed no type-cast for attributes when adding from UI
This commit is contained in:
commit
8c30b11a23
@ -33,11 +33,11 @@ import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@ -65,25 +65,17 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.UUIDBased;
|
||||
import org.thingsboard.server.common.data.kv.Aggregation;
|
||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.BaseDeleteTsKvQuery;
|
||||
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.BooleanDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.DataType;
|
||||
import org.thingsboard.server.common.data.kv.DeleteTsKvQuery;
|
||||
import org.thingsboard.server.common.data.kv.DoubleDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.IntervalType;
|
||||
import org.thingsboard.server.common.data.kv.JsonDataEntry;
|
||||
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.tenant.profile.DefaultTenantProfileConfiguration;
|
||||
import org.thingsboard.server.common.msg.rule.engine.DeviceAttributesEventNotificationMsg;
|
||||
import org.thingsboard.server.config.annotations.ApiOperation;
|
||||
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
||||
import org.thingsboard.server.exception.InvalidParametersException;
|
||||
import org.thingsboard.server.exception.UncheckedApiException;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.AccessValidator;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
@ -156,9 +148,6 @@ public class TelemetryController extends BaseController {
|
||||
@Autowired
|
||||
private TbTelemetryService tbTelemetryService;
|
||||
|
||||
@Value("${transport.json.max_string_value_length:0}")
|
||||
private int maxStringValueLength;
|
||||
|
||||
private ExecutorService executor;
|
||||
|
||||
@PostConstruct
|
||||
@ -345,12 +334,13 @@ public class TelemetryController extends BaseController {
|
||||
"Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED' that includes an error stacktrace."),
|
||||
})
|
||||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
|
||||
@RequestMapping(value = "/{deviceId}/{scope}", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public DeferredResult<ResponseEntity> saveDeviceAttributes(
|
||||
@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr,
|
||||
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, requiredMode = Schema.RequiredMode.REQUIRED)) @PathVariable("scope") AttributeScope scope,
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
|
||||
@PostMapping(value = "/{deviceId}/{scope}")
|
||||
public DeferredResult<ResponseEntity> saveDeviceAttributes(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true)
|
||||
@PathVariable("deviceId") String deviceIdStr,
|
||||
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, requiredMode = Schema.RequiredMode.REQUIRED))
|
||||
@PathVariable("scope") AttributeScope scope,
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)
|
||||
@RequestBody String request) throws ThingsboardException {
|
||||
EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr);
|
||||
return saveAttributes(getTenantId(), entityId, scope, request);
|
||||
}
|
||||
@ -367,13 +357,15 @@ public class TelemetryController extends BaseController {
|
||||
@ApiResponse(responseCode = "500", description = SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR),
|
||||
})
|
||||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
|
||||
@RequestMapping(value = "/{entityType}/{entityId}/{scope}", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public DeferredResult<ResponseEntity> saveEntityAttributesV1(
|
||||
@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType,
|
||||
@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
|
||||
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"})) @PathVariable("scope") AttributeScope scope,
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
|
||||
@PostMapping(value = "/{entityType}/{entityId}/{scope}")
|
||||
public DeferredResult<ResponseEntity> saveEntityAttributesV1(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE"))
|
||||
@PathVariable("entityType") String entityType,
|
||||
@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true)
|
||||
@PathVariable("entityId") String entityIdStr,
|
||||
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}))
|
||||
@PathVariable("scope") AttributeScope scope,
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)
|
||||
@RequestBody String request) throws ThingsboardException {
|
||||
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
|
||||
return saveAttributes(getTenantId(), entityId, scope, request);
|
||||
}
|
||||
@ -390,13 +382,15 @@ public class TelemetryController extends BaseController {
|
||||
@ApiResponse(responseCode = "500", description = SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR),
|
||||
})
|
||||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
|
||||
@RequestMapping(value = "/{entityType}/{entityId}/attributes/{scope}", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public DeferredResult<ResponseEntity> saveEntityAttributesV2(
|
||||
@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType,
|
||||
@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
|
||||
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, requiredMode = Schema.RequiredMode.REQUIRED)) @PathVariable("scope") AttributeScope scope,
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
|
||||
@PostMapping(value = "/{entityType}/{entityId}/attributes/{scope}")
|
||||
public DeferredResult<ResponseEntity> saveEntityAttributesV2(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE"))
|
||||
@PathVariable("entityType") String entityType,
|
||||
@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true)
|
||||
@PathVariable("entityId") String entityIdStr,
|
||||
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, requiredMode = Schema.RequiredMode.REQUIRED))
|
||||
@PathVariable("scope") AttributeScope scope,
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)
|
||||
@RequestBody String request) throws ThingsboardException {
|
||||
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
|
||||
return saveAttributes(getTenantId(), entityId, scope, request);
|
||||
}
|
||||
@ -616,18 +610,24 @@ public class TelemetryController extends BaseController {
|
||||
});
|
||||
}
|
||||
|
||||
private DeferredResult<ResponseEntity> saveAttributes(TenantId srcTenantId, EntityId entityIdSrc, AttributeScope scope, JsonNode json) throws ThingsboardException {
|
||||
private DeferredResult<ResponseEntity> saveAttributes(TenantId srcTenantId, EntityId entityIdSrc, AttributeScope scope, String jsonStr) throws ThingsboardException {
|
||||
if (AttributeScope.SERVER_SCOPE != scope && AttributeScope.SHARED_SCOPE != scope) {
|
||||
return getImmediateDeferredResult("Invalid scope: " + scope, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (json.isObject()) {
|
||||
List<AttributeKvEntry> attributes = extractRequestAttributes(json);
|
||||
JsonElement json;
|
||||
try {
|
||||
json = JsonParser.parseString(jsonStr);
|
||||
} catch (Exception e) {
|
||||
return getImmediateDeferredResult("Invalid JSON", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (json.isJsonObject()) {
|
||||
List<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(json);
|
||||
if (attributes.isEmpty()) {
|
||||
return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
for (AttributeKvEntry attributeKvEntry : attributes) {
|
||||
if (attributeKvEntry.getKey().isEmpty() || attributeKvEntry.getKey().trim().length() == 0) {
|
||||
return getImmediateDeferredResult("Key cannot be empty or contains only spaces", HttpStatus.BAD_REQUEST);
|
||||
if (attributeKvEntry.getKey().isBlank()) {
|
||||
return getImmediateDeferredResult("Key cannot be blank", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
SecurityUser user = getCurrentUser();
|
||||
@ -885,43 +885,6 @@ public class TelemetryController extends BaseController {
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<AttributeKvEntry> extractRequestAttributes(JsonNode jsonNode) {
|
||||
long ts = System.currentTimeMillis();
|
||||
List<AttributeKvEntry> attributes = new ArrayList<>();
|
||||
jsonNode.fields().forEachRemaining(entry -> {
|
||||
String key = entry.getKey();
|
||||
JsonNode value = entry.getValue();
|
||||
if (entry.getValue().isObject() || entry.getValue().isArray()) {
|
||||
attributes.add(new BaseAttributeKvEntry(new JsonDataEntry(key, toJsonStr(value)), ts));
|
||||
} else if (entry.getValue().isTextual()) {
|
||||
if (maxStringValueLength > 0 && entry.getValue().textValue().length() > maxStringValueLength) {
|
||||
String message = String.format("String value length [%d] for key [%s] is greater than maximum allowed [%d]", entry.getValue().textValue().length(), key, maxStringValueLength);
|
||||
throw new UncheckedApiException(new InvalidParametersException(message));
|
||||
}
|
||||
attributes.add(new BaseAttributeKvEntry(new StringDataEntry(key, value.textValue()), ts));
|
||||
} else if (entry.getValue().isBoolean()) {
|
||||
attributes.add(new BaseAttributeKvEntry(new BooleanDataEntry(key, value.booleanValue()), ts));
|
||||
} else if (entry.getValue().isDouble()) {
|
||||
attributes.add(new BaseAttributeKvEntry(new DoubleDataEntry(key, value.doubleValue()), ts));
|
||||
} else if (entry.getValue().isNumber()) {
|
||||
if (entry.getValue().isBigInteger()) {
|
||||
throw new UncheckedApiException(new InvalidParametersException("Big integer values are not supported!"));
|
||||
} else {
|
||||
attributes.add(new BaseAttributeKvEntry(new LongDataEntry(key, value.longValue()), ts));
|
||||
}
|
||||
}
|
||||
});
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private String toJsonStr(JsonNode value) {
|
||||
try {
|
||||
return JacksonUtil.toString(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new JsonParseException("Can't parse jsonValue: " + value, e);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonNode toJsonNode(String value) {
|
||||
try {
|
||||
return JacksonUtil.toJsonNode(value);
|
||||
|
||||
@ -266,7 +266,7 @@ public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
|
||||
SettableFuture<Void> futureToSet = SettableFuture.create();
|
||||
JsonObject json = JsonUtils.getJsonObject(msg.getKvList());
|
||||
AttributeScope scope = AttributeScope.valueOf(metaData.getValue(DataConstants.SCOPE));
|
||||
List<AttributeKvEntry> attributes = new ArrayList<>(JsonConverter.convertToAttributes(json, ts));
|
||||
List<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(json, ts);
|
||||
ListenableFuture<List<AttributeKvEntry>> future = filterAttributesByTs(tenantId, entityId, scope, attributes);
|
||||
Futures.addCallback(future, new FutureCallback<>() {
|
||||
@Override
|
||||
@ -314,7 +314,7 @@ public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
|
||||
SettableFuture<Void> futureToSet = SettableFuture.create();
|
||||
JsonObject json = JsonUtils.getJsonObject(msg.getKvList());
|
||||
AttributeScope scope = AttributeScope.valueOf(metaData.getValue(DataConstants.SCOPE));
|
||||
List<AttributeKvEntry> attributes = new ArrayList<>(JsonConverter.convertToAttributes(json, ts));
|
||||
List<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(json, ts);
|
||||
ListenableFuture<List<AttributeKvEntry>> future = filterAttributesByTs(tenantId, entityId, scope, attributes);
|
||||
Futures.addCallback(future, new FutureCallback<>() {
|
||||
@Override
|
||||
|
||||
@ -67,7 +67,6 @@ import org.thingsboard.server.service.security.permission.Resource;
|
||||
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
|
||||
import org.thingsboard.server.utils.CsvUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@ -235,7 +234,7 @@ public abstract class AbstractBulkImportService<E extends HasId<? extends Entity
|
||||
@SneakyThrows
|
||||
private void saveAttributes(SecurityUser user, E entity, Map.Entry<BulkImportColumnType, JsonObject> kvsEntry, BulkImportColumnType kvType) {
|
||||
String scope = kvType.getKey();
|
||||
List<AttributeKvEntry> attributes = new ArrayList<>(JsonConverter.convertToAttributes(kvsEntry.getValue()));
|
||||
List<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(kvsEntry.getValue());
|
||||
|
||||
accessValidator.validateEntityAndCallback(user, Operation.WRITE_ATTRIBUTES, entity.getId(), (result, tenantId, entityId) -> {
|
||||
tsSubscriptionService.saveAttributes(AttributesSaveRequest.builder()
|
||||
|
||||
@ -56,11 +56,9 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509Ce
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -538,13 +536,13 @@ public class JsonConverter {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Set<AttributeKvEntry> convertToAttributes(JsonElement element) {
|
||||
public static List<AttributeKvEntry> convertToAttributes(JsonElement element) {
|
||||
long ts = System.currentTimeMillis();
|
||||
return convertToAttributes(element, ts);
|
||||
}
|
||||
|
||||
public static Set<AttributeKvEntry> convertToAttributes(JsonElement element, long ts) {
|
||||
return new HashSet<>(parseValues(element.getAsJsonObject()).stream().map(kv -> new BaseAttributeKvEntry(kv, ts)).toList());
|
||||
public static List<AttributeKvEntry> convertToAttributes(JsonElement element, long ts) {
|
||||
return parseValues(element.getAsJsonObject()).stream().<AttributeKvEntry>map(kv -> new BaseAttributeKvEntry(kv, ts)).toList();
|
||||
}
|
||||
|
||||
private static List<KvEntry> parseValues(JsonObject valuesObject) {
|
||||
|
||||
@ -23,8 +23,6 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.parallel.Isolated;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Isolated("JsonConverter static settings being modified")
|
||||
public class JsonConverterTest {
|
||||
|
||||
@ -53,7 +51,7 @@ public class JsonConverterTest {
|
||||
|
||||
@Test
|
||||
public void testParseAttributesBigDecimalAsLong() {
|
||||
var result = new ArrayList<>(JsonConverter.convertToAttributes(JsonParser.parseString("{\"meterReadingDelta\": 1E1}")));
|
||||
var result = JsonConverter.convertToAttributes(JsonParser.parseString("{\"meterReadingDelta\": 1E1}"));
|
||||
Assertions.assertEquals(10L, result.get(0).getLongValue().get().longValue());
|
||||
}
|
||||
|
||||
@ -108,4 +106,5 @@ public class JsonConverterTest {
|
||||
JsonConverter.convertToTelemetry(JsonParser.parseString("{\"meterReadingDelta\": 9.9701010061400066E19}"), 0L);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -44,7 +44,6 @@ import org.thingsboard.server.common.msg.TbMsg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.thingsboard.server.common.data.msg.TbMsgType.ACTIVITY_EVENT;
|
||||
@ -115,14 +114,13 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
|
||||
.build());
|
||||
}
|
||||
} else {
|
||||
Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(JsonParser.parseString(msg.getData()));
|
||||
List<AttributeKvEntry> filteredAttributes =
|
||||
attributes.stream().filter(attr -> attributeContainsInEntityView(scope, attr.getKey(), entityView)).collect(Collectors.toList());
|
||||
List<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(JsonParser.parseString(msg.getData())).stream()
|
||||
.filter(attr -> attributeContainsInEntityView(scope, attr.getKey(), entityView)).toList();
|
||||
ctx.getTelemetryService().saveAttributes(AttributesSaveRequest.builder()
|
||||
.tenantId(ctx.getTenantId())
|
||||
.entityId(entityView.getId())
|
||||
.scope(scope)
|
||||
.entries(filteredAttributes)
|
||||
.entries(attributes)
|
||||
.callback(getFutureCallback(ctx, msg, entityView))
|
||||
.build());
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ class DeviceState {
|
||||
|
||||
private boolean processAttributes(TbContext ctx, TbMsg msg, String scope) throws ExecutionException, InterruptedException {
|
||||
boolean stateChanged = false;
|
||||
Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(JsonParser.parseString(msg.getData()));
|
||||
List<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(JsonParser.parseString(msg.getData()));
|
||||
if (!attributes.isEmpty()) {
|
||||
SnapshotUpdate update = merge(latestValues, attributes, scope);
|
||||
for (DeviceProfileAlarm alarm : deviceProfile.getAlarmSettings()) {
|
||||
@ -321,7 +321,7 @@ class DeviceState {
|
||||
return new SnapshotUpdate(AlarmConditionKeyType.TIME_SERIES, keys);
|
||||
}
|
||||
|
||||
private SnapshotUpdate merge(DataSnapshot latestValues, Set<AttributeKvEntry> attributes, String scope) {
|
||||
private SnapshotUpdate merge(DataSnapshot latestValues, List<AttributeKvEntry> attributes, String scope) {
|
||||
long newTs = 0;
|
||||
Set<AlarmConditionFilterKey> keys = new HashSet<>();
|
||||
for (AttributeKvEntry entry : attributes) {
|
||||
|
||||
@ -103,8 +103,7 @@ public class TbCalculatedFieldsNode implements TbNode {
|
||||
}
|
||||
|
||||
private void processPostAttributesRequest(TbContext ctx, TbMsg msg) {
|
||||
List<AttributeKvEntry> newAttributes = new ArrayList<>(JsonConverter.convertToAttributes(JsonParser.parseString(msg.getData())));
|
||||
|
||||
List<AttributeKvEntry> newAttributes = JsonConverter.convertToAttributes(JsonParser.parseString(msg.getData()));
|
||||
if (newAttributes.isEmpty()) {
|
||||
ctx.tellSuccess(msg);
|
||||
return;
|
||||
|
||||
@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||
import org.thingsboard.server.common.data.util.TbPair;
|
||||
import org.thingsboard.server.common.msg.TbMsg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -133,7 +132,7 @@ public class TbMsgAttributesNode implements TbNode {
|
||||
return;
|
||||
}
|
||||
String src = msg.getData();
|
||||
List<AttributeKvEntry> newAttributes = new ArrayList<>(JsonConverter.convertToAttributes(JsonParser.parseString(src)));
|
||||
List<AttributeKvEntry> newAttributes = JsonConverter.convertToAttributes(JsonParser.parseString(src));
|
||||
if (newAttributes.isEmpty()) {
|
||||
ctx.tellSuccess(msg);
|
||||
return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user