Commit 59c55fb2c59c4005c0a6152aba3dba3b9d4e9854

Authored by Volodymyr Babak
1 parent b52d2aae

For devices from edge new id generated every time

@@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc; @@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc;
17 17
18 import com.datastax.driver.core.utils.UUIDs; 18 import com.datastax.driver.core.utils.UUIDs;
19 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
  20 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 import com.google.common.util.concurrent.FutureCallback; 21 import com.google.common.util.concurrent.FutureCallback;
21 import com.google.common.util.concurrent.Futures; 22 import com.google.common.util.concurrent.Futures;
22 import com.google.common.util.concurrent.ListenableFuture; 23 import com.google.common.util.concurrent.ListenableFuture;
@@ -335,8 +336,8 @@ public final class EdgeGrpcSession implements Closeable { @@ -335,8 +336,8 @@ public final class EdgeGrpcSession implements Closeable {
335 case CREDENTIALS_REQUEST: 336 case CREDENTIALS_REQUEST:
336 downlinkMsg = processCredentialsRequestMessage(edgeEvent); 337 downlinkMsg = processCredentialsRequestMessage(edgeEvent);
337 break; 338 break;
338 - case ENTITY_EXISTS_REQUEST:  
339 - downlinkMsg = processEntityExistsRequestMessage(edgeEvent); 339 + case ENTITY_MERGE_REQUEST:
  340 + downlinkMsg = processEntityMergeRequestMessage(edgeEvent);
340 break; 341 break;
341 case RPC_CALL: 342 case RPC_CALL:
342 downlinkMsg = processRpcCallMsg(edgeEvent); 343 downlinkMsg = processRpcCallMsg(edgeEvent);
@@ -352,13 +353,18 @@ public final class EdgeGrpcSession implements Closeable { @@ -352,13 +353,18 @@ public final class EdgeGrpcSession implements Closeable {
352 return result; 353 return result;
353 } 354 }
354 355
355 - private DownlinkMsg processEntityExistsRequestMessage(EdgeEvent edgeEvent) { 356 + private DownlinkMsg processEntityMergeRequestMessage(EdgeEvent edgeEvent) {
356 DownlinkMsg downlinkMsg = null; 357 DownlinkMsg downlinkMsg = null;
357 if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { 358 if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) {
358 DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); 359 DeviceId deviceId = new DeviceId(edgeEvent.getEntityId());
359 Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); 360 Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId);
360 CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); 361 CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device);
361 - DeviceUpdateMsg d = ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device, customerId); 362 + String conflictName = null;
  363 + if(edgeEvent.getBody() != null) {
  364 + conflictName = edgeEvent.getBody().get("conflictName").asText();
  365 + }
  366 + DeviceUpdateMsg d = ctx.getDeviceMsgConstructor()
  367 + .constructDeviceUpdatedMsg(UpdateMsgType.ENTITY_MERGE_RPC_MESSAGE, device, customerId, conflictName);
362 downlinkMsg = DownlinkMsg.newBuilder() 368 downlinkMsg = DownlinkMsg.newBuilder()
363 .addAllDeviceUpdateMsg(Collections.singletonList(d)) 369 .addAllDeviceUpdateMsg(Collections.singletonList(d))
364 .build(); 370 .build();
@@ -497,7 +503,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -497,7 +503,7 @@ public final class EdgeGrpcSession implements Closeable {
497 if (device != null) { 503 if (device != null) {
498 CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); 504 CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device);
499 DeviceUpdateMsg deviceUpdateMsg = 505 DeviceUpdateMsg deviceUpdateMsg =
500 - ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId); 506 + ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId, null);
501 downlinkMsg = DownlinkMsg.newBuilder() 507 downlinkMsg = DownlinkMsg.newBuilder()
502 .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) 508 .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg))
503 .build(); 509 .build();
@@ -38,7 +38,7 @@ public class DeviceMsgConstructor { @@ -38,7 +38,7 @@ public class DeviceMsgConstructor {
38 38
39 protected static final ObjectMapper mapper = new ObjectMapper(); 39 protected static final ObjectMapper mapper = new ObjectMapper();
40 40
41 - public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId) { 41 + public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId, String conflictName) {
42 DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() 42 DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
43 .setMsgType(msgType) 43 .setMsgType(msgType)
44 .setIdMSB(device.getId().getId().getMostSignificantBits()) 44 .setIdMSB(device.getId().getId().getMostSignificantBits())
@@ -55,6 +55,9 @@ public class DeviceMsgConstructor { @@ -55,6 +55,9 @@ public class DeviceMsgConstructor {
55 if (device.getAdditionalInfo() != null) { 55 if (device.getAdditionalInfo() != null) {
56 builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo())); 56 builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo()));
57 } 57 }
  58 + if (conflictName != null) {
  59 + builder.setConflictName(conflictName);
  60 + }
58 return builder.build(); 61 return builder.build();
59 } 62 }
60 63
@@ -37,6 +37,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService; @@ -37,6 +37,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
37 import org.thingsboard.server.dao.device.DeviceCredentialsService; 37 import org.thingsboard.server.dao.device.DeviceCredentialsService;
38 import org.thingsboard.server.dao.device.DeviceService; 38 import org.thingsboard.server.dao.device.DeviceService;
39 import org.thingsboard.server.dao.edge.EdgeEventService; 39 import org.thingsboard.server.dao.edge.EdgeEventService;
  40 +import org.thingsboard.server.dao.edge.EdgeService;
40 import org.thingsboard.server.dao.entityview.EntityViewService; 41 import org.thingsboard.server.dao.entityview.EntityViewService;
41 import org.thingsboard.server.dao.relation.RelationService; 42 import org.thingsboard.server.dao.relation.RelationService;
42 import org.thingsboard.server.dao.user.UserService; 43 import org.thingsboard.server.dao.user.UserService;
@@ -65,6 +66,9 @@ public abstract class BaseProcessor { @@ -65,6 +66,9 @@ public abstract class BaseProcessor {
65 protected EntityViewService entityViewService; 66 protected EntityViewService entityViewService;
66 67
67 @Autowired 68 @Autowired
  69 + protected EdgeService edgeService;
  70 +
  71 + @Autowired
68 protected CustomerService customerService; 72 protected CustomerService customerService;
69 73
70 @Autowired 74 @Autowired
@@ -17,12 +17,15 @@ package org.thingsboard.server.service.edge.rpc.processor; @@ -17,12 +17,15 @@ package org.thingsboard.server.service.edge.rpc.processor;
17 17
18 import com.fasterxml.jackson.core.JsonProcessingException; 18 import com.fasterxml.jackson.core.JsonProcessingException;
19 import com.fasterxml.jackson.databind.node.ObjectNode; 19 import com.fasterxml.jackson.databind.node.ObjectNode;
  20 +import com.google.common.util.concurrent.FutureCallback;
20 import com.google.common.util.concurrent.Futures; 21 import com.google.common.util.concurrent.Futures;
21 import com.google.common.util.concurrent.ListenableFuture; 22 import com.google.common.util.concurrent.ListenableFuture;
22 import com.google.common.util.concurrent.SettableFuture; 23 import com.google.common.util.concurrent.SettableFuture;
23 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
24 import org.apache.commons.lang.RandomStringUtils; 25 import org.apache.commons.lang.RandomStringUtils;
25 import org.apache.commons.lang.StringUtils; 26 import org.apache.commons.lang.StringUtils;
  27 +import org.checkerframework.checker.nullness.qual.Nullable;
  28 +import org.springframework.security.core.parameters.P;
26 import org.springframework.stereotype.Component; 29 import org.springframework.stereotype.Component;
27 import org.thingsboard.rule.engine.api.RpcError; 30 import org.thingsboard.rule.engine.api.RpcError;
28 import org.thingsboard.server.common.data.DataConstants; 31 import org.thingsboard.server.common.data.DataConstants;
@@ -52,6 +55,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; @@ -52,6 +55,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
52 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; 55 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
53 import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg; 56 import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg;
54 57
  58 +import java.util.List;
55 import java.util.UUID; 59 import java.util.UUID;
56 import java.util.concurrent.locks.ReentrantLock; 60 import java.util.concurrent.locks.ReentrantLock;
57 61
@@ -64,36 +68,62 @@ public class DeviceProcessor extends BaseProcessor { @@ -64,36 +68,62 @@ public class DeviceProcessor extends BaseProcessor {
64 68
65 public ListenableFuture<Void> onDeviceUpdate(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { 69 public ListenableFuture<Void> onDeviceUpdate(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
66 log.trace("[{}] onDeviceUpdate [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName()); 70 log.trace("[{}] onDeviceUpdate [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
67 - DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));  
68 switch (deviceUpdateMsg.getMsgType()) { 71 switch (deviceUpdateMsg.getMsgType()) {
69 case ENTITY_CREATED_RPC_MESSAGE: 72 case ENTITY_CREATED_RPC_MESSAGE:
70 String deviceName = deviceUpdateMsg.getName(); 73 String deviceName = deviceUpdateMsg.getName();
71 Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); 74 Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);
72 if (device != null) { 75 if (device != null) {
73 - log.info("[{}] Device with name '{}' already exists on the cloud. Updating id of device entity on the edge", tenantId, deviceName);  
74 - if (!device.getId().equals(edgeDeviceId)) {  
75 - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_EXISTS_REQUEST, device.getId(), null);  
76 - } 76 + ListenableFuture<List<EdgeId>> future = edgeService.findRelatedEdgeIdsByEntityId(tenantId, device.getId());
  77 + SettableFuture<Void> futureToSet = SettableFuture.create();
  78 + Futures.addCallback(future, new FutureCallback<List<EdgeId>>() {
  79 + @Override
  80 + public void onSuccess(@Nullable List<EdgeId> edgeIds) {
  81 + boolean update = false;
  82 + if (edgeIds != null && !edgeIds.isEmpty()) {
  83 + if (edgeIds.contains(edge.getId())) {
  84 + update = true;
  85 + }
  86 + }
  87 + Device device;
  88 + if (update) {
  89 + log.info("[{}] Device with name '{}' already exists on the cloud, and related to this edge [{}]. " +
  90 + "deviceUpdateMsg [{}], Updating device", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
  91 + updateDevice(tenantId, edge, deviceUpdateMsg);
  92 + } else {
  93 + log.info("[{}] Device with name '{}' already exists on the cloud, but not related to this edge [{}]. deviceUpdateMsg [{}]." +
  94 + "Creating a new device with random prefix and relate to this edge", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
  95 + String newDeviceName = deviceUpdateMsg.getName() + "_" + RandomStringUtils.randomAlphabetic(15);
  96 + device = createDevice(tenantId, edge, deviceUpdateMsg, newDeviceName);
  97 + ObjectNode body = mapper.createObjectNode();
  98 + body.put("conflictName", deviceName);
  99 + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, device.getId(), body);
  100 + deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
  101 + }
  102 + futureToSet.set(null);
  103 + }
  104 +
  105 + @Override
  106 + public void onFailure(Throwable t) {
  107 + log.error("[{}] Failed to get related edge ids by device id [{}], edge [{}]", tenantId, deviceUpdateMsg, edge.getId(), t);
  108 + futureToSet.setException(t);
  109 + }
  110 + }, dbCallbackExecutorService);
  111 + return futureToSet;
77 } else { 112 } else {
78 - Device deviceById = deviceService.findDeviceById(edge.getTenantId(), edgeDeviceId);  
79 - if (deviceById != null) {  
80 - 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());  
81 - device = createDevice(tenantId, edge, deviceUpdateMsg);  
82 - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_EXISTS_REQUEST, device.getId(), null);  
83 - } else {  
84 - device = createDevice(tenantId, edge, deviceUpdateMsg);  
85 - } 113 + log.info("[{}] Creating new device and replacing device entity on the edge [{}]", tenantId, deviceUpdateMsg);
  114 + device = createDevice(tenantId, edge, deviceUpdateMsg, deviceUpdateMsg.getName());
  115 + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, device.getId(), null);
  116 + deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
86 } 117 }
87 - // TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment  
88 - deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());  
89 break; 118 break;
90 case ENTITY_UPDATED_RPC_MESSAGE: 119 case ENTITY_UPDATED_RPC_MESSAGE:
91 updateDevice(tenantId, edge, deviceUpdateMsg); 120 updateDevice(tenantId, edge, deviceUpdateMsg);
92 break; 121 break;
93 case ENTITY_DELETED_RPC_MESSAGE: 122 case ENTITY_DELETED_RPC_MESSAGE:
94 - Device deviceToDelete = deviceService.findDeviceById(tenantId, edgeDeviceId); 123 + DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
  124 + Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId);
95 if (deviceToDelete != null) { 125 if (deviceToDelete != null) {
96 - deviceService.unassignDeviceFromEdge(tenantId, edgeDeviceId, edge.getId()); 126 + deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId());
97 } 127 }
98 break; 128 break;
99 case UNRECOGNIZED: 129 case UNRECOGNIZED:
@@ -103,7 +133,6 @@ public class DeviceProcessor extends BaseProcessor { @@ -103,7 +133,6 @@ public class DeviceProcessor extends BaseProcessor {
103 return Futures.immediateFuture(null); 133 return Futures.immediateFuture(null);
104 } 134 }
105 135
106 -  
107 public ListenableFuture<Void> onDeviceCredentialsUpdate(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { 136 public ListenableFuture<Void> onDeviceCredentialsUpdate(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) {
108 log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); 137 log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg);
109 DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); 138 DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB()));
@@ -131,36 +160,34 @@ public class DeviceProcessor extends BaseProcessor { @@ -131,36 +160,34 @@ public class DeviceProcessor extends BaseProcessor {
131 private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { 160 private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
132 DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); 161 DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
133 Device device = deviceService.findDeviceById(tenantId, deviceId); 162 Device device = deviceService.findDeviceById(tenantId, deviceId);
134 - device.setName(deviceUpdateMsg.getName());  
135 - device.setType(deviceUpdateMsg.getType());  
136 - device.setLabel(deviceUpdateMsg.getLabel());  
137 - device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));  
138 - deviceService.saveDevice(device);  
139 -  
140 - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null); 163 + if (device != null) {
  164 + device.setName(deviceUpdateMsg.getName());
  165 + device.setType(deviceUpdateMsg.getType());
  166 + device.setLabel(deviceUpdateMsg.getLabel());
  167 + device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
  168 + deviceService.saveDevice(device);
  169 + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
  170 + } else {
  171 + log.warn("[{}] can't find device [{}], edge [{}]", tenantId, deviceUpdateMsg, edge.getId());
  172 + }
141 } 173 }
142 174
143 - private Device createDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { 175 + private Device createDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg, String deviceName) {
144 Device device; 176 Device device;
145 try { 177 try {
146 deviceCreationLock.lock(); 178 deviceCreationLock.lock();
147 log.debug("[{}] Creating device entity [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName()); 179 log.debug("[{}] Creating device entity [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
148 - DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));  
149 device = new Device(); 180 device = new Device();
150 device.setTenantId(edge.getTenantId()); 181 device.setTenantId(edge.getTenantId());
151 device.setCustomerId(edge.getCustomerId()); 182 device.setCustomerId(edge.getCustomerId());
152 - device.setId(deviceId);  
153 - device.setName(deviceUpdateMsg.getName()); 183 + device.setName(deviceName);
154 device.setType(deviceUpdateMsg.getType()); 184 device.setType(deviceUpdateMsg.getType());
155 device.setLabel(deviceUpdateMsg.getLabel()); 185 device.setLabel(deviceUpdateMsg.getLabel());
156 device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); 186 device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
157 device = deviceService.saveDevice(device); 187 device = deviceService.saveDevice(device);
158 - createDeviceCredentials(device);  
159 createRelationFromEdge(tenantId, edge.getId(), device.getId()); 188 createRelationFromEdge(tenantId, edge.getId(), device.getId());
160 deviceStateService.onDeviceAdded(device); 189 deviceStateService.onDeviceAdded(device);
161 pushDeviceCreatedEventToRuleEngine(tenantId, edge, device); 190 pushDeviceCreatedEventToRuleEngine(tenantId, edge, device);
162 -  
163 - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);  
164 } finally { 191 } finally {
165 deviceCreationLock.unlock(); 192 deviceCreationLock.unlock();
166 } 193 }
@@ -176,14 +203,6 @@ public class DeviceProcessor extends BaseProcessor { @@ -176,14 +203,6 @@ public class DeviceProcessor extends BaseProcessor {
176 relationService.saveRelation(tenantId, relation); 203 relationService.saveRelation(tenantId, relation);
177 } 204 }
178 205
179 - private void createDeviceCredentials(Device device) {  
180 - DeviceCredentials deviceCredentials = new DeviceCredentials();  
181 - deviceCredentials.setDeviceId(device.getId());  
182 - deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);  
183 - deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20));  
184 - deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);  
185 - }  
186 -  
187 private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) { 206 private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) {
188 try { 207 try {
189 DeviceId deviceId = device.getId(); 208 DeviceId deviceId = device.getId();
@@ -26,6 +26,7 @@ import com.google.protobuf.AbstractMessage; @@ -26,6 +26,7 @@ import com.google.protobuf.AbstractMessage;
26 import com.google.protobuf.InvalidProtocolBufferException; 26 import com.google.protobuf.InvalidProtocolBufferException;
27 import com.google.protobuf.MessageLite; 27 import com.google.protobuf.MessageLite;
28 import lombok.extern.slf4j.Slf4j; 28 import lombok.extern.slf4j.Slf4j;
  29 +import org.apache.commons.lang.RandomStringUtils;
29 import org.junit.After; 30 import org.junit.After;
30 import org.junit.Assert; 31 import org.junit.Assert;
31 import org.junit.Before; 32 import org.junit.Before;
@@ -48,6 +49,7 @@ import org.thingsboard.server.common.data.edge.Edge; @@ -48,6 +49,7 @@ import org.thingsboard.server.common.data.edge.Edge;
48 import org.thingsboard.server.common.data.edge.EdgeEvent; 49 import org.thingsboard.server.common.data.edge.EdgeEvent;
49 import org.thingsboard.server.common.data.edge.EdgeEventActionType; 50 import org.thingsboard.server.common.data.edge.EdgeEventActionType;
50 import org.thingsboard.server.common.data.edge.EdgeEventType; 51 import org.thingsboard.server.common.data.edge.EdgeEventType;
  52 +import org.thingsboard.server.common.data.id.DeviceId;
51 import org.thingsboard.server.common.data.id.EdgeId; 53 import org.thingsboard.server.common.data.id.EdgeId;
52 import org.thingsboard.server.common.data.id.EntityId; 54 import org.thingsboard.server.common.data.id.EntityId;
53 import org.thingsboard.server.common.data.id.EntityIdFactory; 55 import org.thingsboard.server.common.data.id.EntityIdFactory;
@@ -964,6 +966,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -964,6 +966,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
964 private void testSendMessagesToCloud() throws Exception { 966 private void testSendMessagesToCloud() throws Exception {
965 log.info("Sending messages to cloud"); 967 log.info("Sending messages to cloud");
966 sendDevice(); 968 sendDevice();
  969 + sendDeviceWithNameThatAlreadyExistsOnCloud();
967 sendRelationRequest(); 970 sendRelationRequest();
968 sendAlarm(); 971 sendAlarm();
969 sendTelemetry(); 972 sendTelemetry();
@@ -992,17 +995,66 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -992,17 +995,66 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
992 uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build()); 995 uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build());
993 996
994 edgeImitator.expectResponsesAmount(1); 997 edgeImitator.expectResponsesAmount(1);
995 - 998 + edgeImitator.expectMessageAmount(1);
996 testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder); 999 testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
997 1000
998 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1001 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
  1002 +
999 edgeImitator.waitForResponses(); 1003 edgeImitator.waitForResponses();
  1004 + edgeImitator.waitForMessages();
  1005 +
  1006 + AbstractMessage latestMessage = edgeImitator.getLatestMessage();
  1007 + Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
  1008 + DeviceUpdateMsg latestDeviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
  1009 + Assert.assertEquals("Edge Device 2", latestDeviceUpdateMsg.getName());
  1010 +
  1011 + UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB());
1000 1012
1001 - Device device = doGet("/api/device/" + uuid.toString(), Device.class); 1013 + Device device = doGet("/api/device/" + newDeviceId, Device.class);
1002 Assert.assertNotNull(device); 1014 Assert.assertNotNull(device);
1003 Assert.assertEquals("Edge Device 2", device.getName()); 1015 Assert.assertEquals("Edge Device 2", device.getName());
1004 } 1016 }
1005 1017
  1018 + private void sendDeviceWithNameThatAlreadyExistsOnCloud() throws Exception {
  1019 + String deviceOnCloudName = RandomStringUtils.randomAlphanumeric(15);
  1020 + Device deviceOnCloud = saveDevice(deviceOnCloudName);
  1021 +
  1022 + UUID uuid = UUIDs.timeBased();
  1023 +
  1024 + UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
  1025 + DeviceUpdateMsg.Builder deviceUpdateMsgBuilder = DeviceUpdateMsg.newBuilder();
  1026 + deviceUpdateMsgBuilder.setIdMSB(uuid.getMostSignificantBits());
  1027 + deviceUpdateMsgBuilder.setIdLSB(uuid.getLeastSignificantBits());
  1028 + deviceUpdateMsgBuilder.setName(deviceOnCloudName);
  1029 + deviceUpdateMsgBuilder.setType("test");
  1030 + deviceUpdateMsgBuilder.setMsgType(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE);
  1031 + testAutoGeneratedCodeByProtobuf(deviceUpdateMsgBuilder);
  1032 + uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build());
  1033 +
  1034 + edgeImitator.expectResponsesAmount(1);
  1035 + edgeImitator.expectMessageAmount(1);
  1036 + testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder);
  1037 +
  1038 + edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
  1039 +
  1040 + edgeImitator.waitForResponses();
  1041 + edgeImitator.waitForMessages();
  1042 +
  1043 + AbstractMessage latestMessage = edgeImitator.getLatestMessage();
  1044 + Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
  1045 + DeviceUpdateMsg latestDeviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
  1046 + Assert.assertNotEquals(deviceOnCloudName, latestDeviceUpdateMsg.getName());
  1047 + Assert.assertEquals(deviceOnCloudName, latestDeviceUpdateMsg.getConflictName());
  1048 +
  1049 + UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB());
  1050 +
  1051 + Assert.assertNotEquals(deviceOnCloud.getId().getId(), newDeviceId);
  1052 +
  1053 + Device device = doGet("/api/device/" + newDeviceId, Device.class);
  1054 + Assert.assertNotNull(device);
  1055 + Assert.assertNotEquals(deviceOnCloudName, device.getName());
  1056 + }
  1057 +
1006 private void sendRelationRequest() throws Exception { 1058 private void sendRelationRequest() throws Exception {
1007 Device device = findDeviceByName("Edge Device 1"); 1059 Device device = findDeviceByName("Edge Device 1");
1008 Asset asset = findAssetByName("Edge Asset 1"); 1060 Asset asset = findAssetByName("Edge Asset 1");
@@ -34,5 +34,5 @@ public enum EdgeEventActionType { @@ -34,5 +34,5 @@ public enum EdgeEventActionType {
34 ASSIGNED_TO_EDGE, 34 ASSIGNED_TO_EDGE,
35 UNASSIGNED_FROM_EDGE, 35 UNASSIGNED_FROM_EDGE,
36 CREDENTIALS_REQUEST, 36 CREDENTIALS_REQUEST,
37 - ENTITY_EXISTS_REQUEST 37 + ENTITY_MERGE_REQUEST
38 } 38 }
@@ -97,7 +97,7 @@ enum UpdateMsgType { @@ -97,7 +97,7 @@ enum UpdateMsgType {
97 ENTITY_DELETED_RPC_MESSAGE = 2; 97 ENTITY_DELETED_RPC_MESSAGE = 2;
98 ALARM_ACK_RPC_MESSAGE = 3; 98 ALARM_ACK_RPC_MESSAGE = 3;
99 ALARM_CLEAR_RPC_MESSAGE = 4; 99 ALARM_CLEAR_RPC_MESSAGE = 4;
100 - DEVICE_CONFLICT_RPC_MESSAGE = 5; 100 + ENTITY_MERGE_RPC_MESSAGE = 5;
101 } 101 }
102 102
103 message EntityDataProto { 103 message EntityDataProto {
@@ -182,6 +182,7 @@ message DeviceUpdateMsg { @@ -182,6 +182,7 @@ message DeviceUpdateMsg {
182 string type = 7; 182 string type = 7;
183 string label = 8; 183 string label = 8;
184 string additionalInfo = 9; 184 string additionalInfo = 9;
  185 + string conflictName = 10;
185 } 186 }
186 187
187 message DeviceCredentialsUpdateMsg { 188 message DeviceCredentialsUpdateMsg {
@@ -87,6 +87,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; @@ -87,6 +87,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
87 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 87 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
88 import org.thingsboard.server.common.data.rule.RuleChain; 88 import org.thingsboard.server.common.data.rule.RuleChain;
89 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 89 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
  90 +import org.thingsboard.server.common.data.rule.RuleChainType;
90 import org.thingsboard.server.common.data.security.DeviceCredentials; 91 import org.thingsboard.server.common.data.security.DeviceCredentials;
91 import org.thingsboard.server.common.data.security.DeviceCredentialsType; 92 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
92 import org.thingsboard.server.common.data.security.model.SecuritySettings; 93 import org.thingsboard.server.common.data.security.model.SecuritySettings;
@@ -97,6 +98,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; @@ -97,6 +98,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle;
97 import java.io.Closeable; 98 import java.io.Closeable;
98 import java.io.IOException; 99 import java.io.IOException;
99 import java.net.URI; 100 import java.net.URI;
  101 +import java.util.Arrays;
100 import java.util.Collections; 102 import java.util.Collections;
101 import java.util.HashMap; 103 import java.util.HashMap;
102 import java.util.List; 104 import java.util.List;
@@ -626,22 +628,31 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -626,22 +628,31 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
626 } 628 }
627 629
628 public List<ComponentDescriptor> getComponentDescriptorsByType(ComponentType componentType) { 630 public List<ComponentDescriptor> getComponentDescriptorsByType(ComponentType componentType) {
  631 + return getComponentDescriptorsByType(componentType, RuleChainType.CORE);
  632 + }
  633 +
  634 + public List<ComponentDescriptor> getComponentDescriptorsByType(ComponentType componentType, RuleChainType ruleChainType) {
629 return restTemplate.exchange( 635 return restTemplate.exchange(
630 - baseURL + "/api/components?componentType={componentType}", 636 + baseURL + "/api/components/" + componentType.name() + "/?ruleChainType={ruleChainType}",
631 HttpMethod.GET, HttpEntity.EMPTY, 637 HttpMethod.GET, HttpEntity.EMPTY,
632 new ParameterizedTypeReference<List<ComponentDescriptor>>() { 638 new ParameterizedTypeReference<List<ComponentDescriptor>>() {
633 }, 639 },
634 - componentType).getBody(); 640 + ruleChainType).getBody();
635 } 641 }
636 642
637 public List<ComponentDescriptor> getComponentDescriptorsByTypes(List<ComponentType> componentTypes) { 643 public List<ComponentDescriptor> getComponentDescriptorsByTypes(List<ComponentType> componentTypes) {
  644 + return getComponentDescriptorsByTypes(componentTypes, RuleChainType.CORE);
  645 + }
  646 +
  647 + public List<ComponentDescriptor> getComponentDescriptorsByTypes(List<ComponentType> componentTypes, RuleChainType ruleChainType) {
638 return restTemplate.exchange( 648 return restTemplate.exchange(
639 - baseURL + "/api/components?componentTypes={componentTypes}", 649 + baseURL + "/api/components?componentTypes={componentTypes}&ruleChainType={ruleChainType}",
640 HttpMethod.GET, 650 HttpMethod.GET,
641 HttpEntity.EMPTY, 651 HttpEntity.EMPTY,
642 new ParameterizedTypeReference<List<ComponentDescriptor>>() { 652 new ParameterizedTypeReference<List<ComponentDescriptor>>() {
643 }, 653 },
644 - listEnumToString(componentTypes)) 654 + listEnumToString(componentTypes),
  655 + ruleChainType)
645 .getBody(); 656 .getBody();
646 } 657 }
647 658