For devices from edge new id generated every time

This commit is contained in:
Volodymyr Babak 2020-12-15 18:32:35 +02:00
parent b52d2aae17
commit 59c55fb2c5
8 changed files with 159 additions and 63 deletions

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc;
import com.datastax.driver.core.utils.UUIDs; import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -335,8 +336,8 @@ public final class EdgeGrpcSession implements Closeable {
case CREDENTIALS_REQUEST: case CREDENTIALS_REQUEST:
downlinkMsg = processCredentialsRequestMessage(edgeEvent); downlinkMsg = processCredentialsRequestMessage(edgeEvent);
break; break;
case ENTITY_EXISTS_REQUEST: case ENTITY_MERGE_REQUEST:
downlinkMsg = processEntityExistsRequestMessage(edgeEvent); downlinkMsg = processEntityMergeRequestMessage(edgeEvent);
break; break;
case RPC_CALL: case RPC_CALL:
downlinkMsg = processRpcCallMsg(edgeEvent); downlinkMsg = processRpcCallMsg(edgeEvent);
@ -352,13 +353,18 @@ public final class EdgeGrpcSession implements Closeable {
return result; return result;
} }
private DownlinkMsg processEntityExistsRequestMessage(EdgeEvent edgeEvent) { private DownlinkMsg processEntityMergeRequestMessage(EdgeEvent edgeEvent) {
DownlinkMsg downlinkMsg = null; DownlinkMsg downlinkMsg = null;
if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) {
DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); DeviceId deviceId = new DeviceId(edgeEvent.getEntityId());
Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId);
CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device);
DeviceUpdateMsg d = ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); String conflictName = null;
if(edgeEvent.getBody() != null) {
conflictName = edgeEvent.getBody().get("conflictName").asText();
}
DeviceUpdateMsg d = ctx.getDeviceMsgConstructor()
.constructDeviceUpdatedMsg(UpdateMsgType.ENTITY_MERGE_RPC_MESSAGE, device, customerId, conflictName);
downlinkMsg = DownlinkMsg.newBuilder() downlinkMsg = DownlinkMsg.newBuilder()
.addAllDeviceUpdateMsg(Collections.singletonList(d)) .addAllDeviceUpdateMsg(Collections.singletonList(d))
.build(); .build();
@ -497,7 +503,7 @@ public final class EdgeGrpcSession implements Closeable {
if (device != null) { if (device != null) {
CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device);
DeviceUpdateMsg deviceUpdateMsg = DeviceUpdateMsg deviceUpdateMsg =
ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId); ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId, null);
downlinkMsg = DownlinkMsg.newBuilder() downlinkMsg = DownlinkMsg.newBuilder()
.addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg))
.build(); .build();

View File

@ -38,7 +38,7 @@ public class DeviceMsgConstructor {
protected static final ObjectMapper mapper = new ObjectMapper(); protected static final ObjectMapper mapper = new ObjectMapper();
public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId) { public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId, String conflictName) {
DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
.setMsgType(msgType) .setMsgType(msgType)
.setIdMSB(device.getId().getId().getMostSignificantBits()) .setIdMSB(device.getId().getId().getMostSignificantBits())
@ -55,6 +55,9 @@ public class DeviceMsgConstructor {
if (device.getAdditionalInfo() != null) { if (device.getAdditionalInfo() != null) {
builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo())); builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo()));
} }
if (conflictName != null) {
builder.setConflictName(conflictName);
}
return builder.build(); return builder.build();
} }

View File

@ -37,6 +37,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserService;
@ -64,6 +65,9 @@ public abstract class BaseProcessor {
@Autowired @Autowired
protected EntityViewService entityViewService; protected EntityViewService entityViewService;
@Autowired
protected EdgeService edgeService;
@Autowired @Autowired
protected CustomerService customerService; protected CustomerService customerService;

View File

@ -17,12 +17,15 @@ package org.thingsboard.server.service.edge.rpc.processor;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.rule.engine.api.RpcError; import org.thingsboard.rule.engine.api.RpcError;
import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DataConstants;
@ -52,6 +55,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg; import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -64,36 +68,62 @@ public class DeviceProcessor extends BaseProcessor {
public ListenableFuture<Void> onDeviceUpdate(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { public ListenableFuture<Void> onDeviceUpdate(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
log.trace("[{}] onDeviceUpdate [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName()); log.trace("[{}] onDeviceUpdate [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
switch (deviceUpdateMsg.getMsgType()) { switch (deviceUpdateMsg.getMsgType()) {
case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_CREATED_RPC_MESSAGE:
String deviceName = deviceUpdateMsg.getName(); String deviceName = deviceUpdateMsg.getName();
Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);
if (device != null) { if (device != null) {
log.info("[{}] Device with name '{}' already exists on the cloud. Updating id of device entity on the edge", tenantId, deviceName); ListenableFuture<List<EdgeId>> future = edgeService.findRelatedEdgeIdsByEntityId(tenantId, device.getId());
if (!device.getId().equals(edgeDeviceId)) { SettableFuture<Void> futureToSet = SettableFuture.create();
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_EXISTS_REQUEST, device.getId(), null); Futures.addCallback(future, new FutureCallback<List<EdgeId>>() {
} @Override
public void onSuccess(@Nullable List<EdgeId> edgeIds) {
boolean update = false;
if (edgeIds != null && !edgeIds.isEmpty()) {
if (edgeIds.contains(edge.getId())) {
update = true;
}
}
Device device;
if (update) {
log.info("[{}] Device with name '{}' already exists on the cloud, and related to this edge [{}]. " +
"deviceUpdateMsg [{}], Updating device", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
updateDevice(tenantId, edge, deviceUpdateMsg);
} else {
log.info("[{}] Device with name '{}' already exists on the cloud, but not related to this edge [{}]. deviceUpdateMsg [{}]." +
"Creating a new device with random prefix and relate to this edge", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
String newDeviceName = deviceUpdateMsg.getName() + "_" + RandomStringUtils.randomAlphabetic(15);
device = createDevice(tenantId, edge, deviceUpdateMsg, newDeviceName);
ObjectNode body = mapper.createObjectNode();
body.put("conflictName", deviceName);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, device.getId(), body);
deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
}
futureToSet.set(null);
}
@Override
public void onFailure(Throwable t) {
log.error("[{}] Failed to get related edge ids by device id [{}], edge [{}]", tenantId, deviceUpdateMsg, edge.getId(), t);
futureToSet.setException(t);
}
}, dbCallbackExecutorService);
return futureToSet;
} else { } else {
Device deviceById = deviceService.findDeviceById(edge.getTenantId(), edgeDeviceId); log.info("[{}] Creating new device and replacing device entity on the edge [{}]", tenantId, deviceUpdateMsg);
if (deviceById != null) { device = createDevice(tenantId, edge, deviceUpdateMsg, deviceUpdateMsg.getName());
log.info("[{}] Device ID [{}] already used by other device on the cloud. Creating new device and replacing device entity on the edge", tenantId, edgeDeviceId.getId()); saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, device.getId(), null);
device = createDevice(tenantId, edge, deviceUpdateMsg); deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_EXISTS_REQUEST, device.getId(), null);
} else {
device = createDevice(tenantId, edge, deviceUpdateMsg);
}
} }
// TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment
deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
break; break;
case ENTITY_UPDATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE:
updateDevice(tenantId, edge, deviceUpdateMsg); updateDevice(tenantId, edge, deviceUpdateMsg);
break; break;
case ENTITY_DELETED_RPC_MESSAGE: case ENTITY_DELETED_RPC_MESSAGE:
Device deviceToDelete = deviceService.findDeviceById(tenantId, edgeDeviceId); DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId);
if (deviceToDelete != null) { if (deviceToDelete != null) {
deviceService.unassignDeviceFromEdge(tenantId, edgeDeviceId, edge.getId()); deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId());
} }
break; break;
case UNRECOGNIZED: case UNRECOGNIZED:
@ -103,7 +133,6 @@ public class DeviceProcessor extends BaseProcessor {
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
public ListenableFuture<Void> onDeviceCredentialsUpdate(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { public ListenableFuture<Void> onDeviceCredentialsUpdate(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) {
log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg);
DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB()));
@ -131,36 +160,34 @@ public class DeviceProcessor extends BaseProcessor {
private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
Device device = deviceService.findDeviceById(tenantId, deviceId); Device device = deviceService.findDeviceById(tenantId, deviceId);
device.setName(deviceUpdateMsg.getName()); if (device != null) {
device.setType(deviceUpdateMsg.getType());
device.setLabel(deviceUpdateMsg.getLabel());
device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
deviceService.saveDevice(device);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
}
private Device createDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
Device device;
try {
deviceCreationLock.lock();
log.debug("[{}] Creating device entity [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
device = new Device();
device.setTenantId(edge.getTenantId());
device.setCustomerId(edge.getCustomerId());
device.setId(deviceId);
device.setName(deviceUpdateMsg.getName()); device.setName(deviceUpdateMsg.getName());
device.setType(deviceUpdateMsg.getType()); device.setType(deviceUpdateMsg.getType());
device.setLabel(deviceUpdateMsg.getLabel()); device.setLabel(deviceUpdateMsg.getLabel());
device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
deviceService.saveDevice(device);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
} else {
log.warn("[{}] can't find device [{}], edge [{}]", tenantId, deviceUpdateMsg, edge.getId());
}
}
private Device createDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg, String deviceName) {
Device device;
try {
deviceCreationLock.lock();
log.debug("[{}] Creating device entity [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
device = new Device();
device.setTenantId(edge.getTenantId());
device.setCustomerId(edge.getCustomerId());
device.setName(deviceName);
device.setType(deviceUpdateMsg.getType());
device.setLabel(deviceUpdateMsg.getLabel());
device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
device = deviceService.saveDevice(device); device = deviceService.saveDevice(device);
createDeviceCredentials(device);
createRelationFromEdge(tenantId, edge.getId(), device.getId()); createRelationFromEdge(tenantId, edge.getId(), device.getId());
deviceStateService.onDeviceAdded(device); deviceStateService.onDeviceAdded(device);
pushDeviceCreatedEventToRuleEngine(tenantId, edge, device); pushDeviceCreatedEventToRuleEngine(tenantId, edge, device);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
} finally { } finally {
deviceCreationLock.unlock(); deviceCreationLock.unlock();
} }
@ -176,14 +203,6 @@ public class DeviceProcessor extends BaseProcessor {
relationService.saveRelation(tenantId, relation); relationService.saveRelation(tenantId, relation);
} }
private void createDeviceCredentials(Device device) {
DeviceCredentials deviceCredentials = new DeviceCredentials();
deviceCredentials.setDeviceId(device.getId());
deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20));
deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
}
private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) { private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) {
try { try {
DeviceId deviceId = device.getId(); DeviceId deviceId = device.getId();

View File

@ -26,6 +26,7 @@ import com.google.protobuf.AbstractMessage;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite; import com.google.protobuf.MessageLite;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -48,6 +49,7 @@ import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.EntityIdFactory;
@ -964,6 +966,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
private void testSendMessagesToCloud() throws Exception { private void testSendMessagesToCloud() throws Exception {
log.info("Sending messages to cloud"); log.info("Sending messages to cloud");
sendDevice(); sendDevice();
sendDeviceWithNameThatAlreadyExistsOnCloud();
sendRelationRequest(); sendRelationRequest();
sendAlarm(); sendAlarm();
sendTelemetry(); sendTelemetry();
@ -992,17 +995,66 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build()); uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build());
edgeImitator.expectResponsesAmount(1); edgeImitator.expectResponsesAmount(1);
edgeImitator.expectMessageAmount(1);
testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder); testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
edgeImitator.waitForResponses();
Device device = doGet("/api/device/" + uuid.toString(), Device.class); edgeImitator.waitForResponses();
edgeImitator.waitForMessages();
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
DeviceUpdateMsg latestDeviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
Assert.assertEquals("Edge Device 2", latestDeviceUpdateMsg.getName());
UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB());
Device device = doGet("/api/device/" + newDeviceId, Device.class);
Assert.assertNotNull(device); Assert.assertNotNull(device);
Assert.assertEquals("Edge Device 2", device.getName()); Assert.assertEquals("Edge Device 2", device.getName());
} }
private void sendDeviceWithNameThatAlreadyExistsOnCloud() throws Exception {
String deviceOnCloudName = RandomStringUtils.randomAlphanumeric(15);
Device deviceOnCloud = saveDevice(deviceOnCloudName);
UUID uuid = UUIDs.timeBased();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
DeviceUpdateMsg.Builder deviceUpdateMsgBuilder = DeviceUpdateMsg.newBuilder();
deviceUpdateMsgBuilder.setIdMSB(uuid.getMostSignificantBits());
deviceUpdateMsgBuilder.setIdLSB(uuid.getLeastSignificantBits());
deviceUpdateMsgBuilder.setName(deviceOnCloudName);
deviceUpdateMsgBuilder.setType("test");
deviceUpdateMsgBuilder.setMsgType(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
testAutoGeneratedCodeByProtobuf(deviceUpdateMsgBuilder);
uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build());
edgeImitator.expectResponsesAmount(1);
edgeImitator.expectMessageAmount(1);
testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
edgeImitator.waitForResponses();
edgeImitator.waitForMessages();
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
DeviceUpdateMsg latestDeviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
Assert.assertNotEquals(deviceOnCloudName, latestDeviceUpdateMsg.getName());
Assert.assertEquals(deviceOnCloudName, latestDeviceUpdateMsg.getConflictName());
UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB());
Assert.assertNotEquals(deviceOnCloud.getId().getId(), newDeviceId);
Device device = doGet("/api/device/" + newDeviceId, Device.class);
Assert.assertNotNull(device);
Assert.assertNotEquals(deviceOnCloudName, device.getName());
}
private void sendRelationRequest() throws Exception { private void sendRelationRequest() throws Exception {
Device device = findDeviceByName("Edge Device 1"); Device device = findDeviceByName("Edge Device 1");
Asset asset = findAssetByName("Edge Asset 1"); Asset asset = findAssetByName("Edge Asset 1");

View File

@ -34,5 +34,5 @@ public enum EdgeEventActionType {
ASSIGNED_TO_EDGE, ASSIGNED_TO_EDGE,
UNASSIGNED_FROM_EDGE, UNASSIGNED_FROM_EDGE,
CREDENTIALS_REQUEST, CREDENTIALS_REQUEST,
ENTITY_EXISTS_REQUEST ENTITY_MERGE_REQUEST
} }

View File

@ -97,7 +97,7 @@ enum UpdateMsgType {
ENTITY_DELETED_RPC_MESSAGE = 2; ENTITY_DELETED_RPC_MESSAGE = 2;
ALARM_ACK_RPC_MESSAGE = 3; ALARM_ACK_RPC_MESSAGE = 3;
ALARM_CLEAR_RPC_MESSAGE = 4; ALARM_CLEAR_RPC_MESSAGE = 4;
DEVICE_CONFLICT_RPC_MESSAGE = 5; ENTITY_MERGE_RPC_MESSAGE = 5;
} }
message EntityDataProto { message EntityDataProto {
@ -182,6 +182,7 @@ message DeviceUpdateMsg {
string type = 7; string type = 7;
string label = 8; string label = 8;
string additionalInfo = 9; string additionalInfo = 9;
string conflictName = 10;
} }
message DeviceCredentialsUpdateMsg { message DeviceCredentialsUpdateMsg {

View File

@ -87,6 +87,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.DeviceCredentialsType;
import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.SecuritySettings;
@ -97,6 +98,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -626,22 +628,31 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
} }
public List<ComponentDescriptor> getComponentDescriptorsByType(ComponentType componentType) { public List<ComponentDescriptor> getComponentDescriptorsByType(ComponentType componentType) {
return getComponentDescriptorsByType(componentType, RuleChainType.CORE);
}
public List<ComponentDescriptor> getComponentDescriptorsByType(ComponentType componentType, RuleChainType ruleChainType) {
return restTemplate.exchange( return restTemplate.exchange(
baseURL + "/api/components?componentType={componentType}", baseURL + "/api/components/" + componentType.name() + "/?ruleChainType={ruleChainType}",
HttpMethod.GET, HttpEntity.EMPTY, HttpMethod.GET, HttpEntity.EMPTY,
new ParameterizedTypeReference<List<ComponentDescriptor>>() { new ParameterizedTypeReference<List<ComponentDescriptor>>() {
}, },
componentType).getBody(); ruleChainType).getBody();
} }
public List<ComponentDescriptor> getComponentDescriptorsByTypes(List<ComponentType> componentTypes) { public List<ComponentDescriptor> getComponentDescriptorsByTypes(List<ComponentType> componentTypes) {
return getComponentDescriptorsByTypes(componentTypes, RuleChainType.CORE);
}
public List<ComponentDescriptor> getComponentDescriptorsByTypes(List<ComponentType> componentTypes, RuleChainType ruleChainType) {
return restTemplate.exchange( return restTemplate.exchange(
baseURL + "/api/components?componentTypes={componentTypes}", baseURL + "/api/components?componentTypes={componentTypes}&ruleChainType={ruleChainType}",
HttpMethod.GET, HttpMethod.GET,
HttpEntity.EMPTY, HttpEntity.EMPTY,
new ParameterizedTypeReference<List<ComponentDescriptor>>() { new ParameterizedTypeReference<List<ComponentDescriptor>>() {
}, },
listEnumToString(componentTypes)) listEnumToString(componentTypes),
ruleChainType)
.getBody(); .getBody();
} }