Commit 59c55fb2c59c4005c0a6152aba3dba3b9d4e9854
1 parent
b52d2aae
For devices from edge new id generated every time
Showing
8 changed files
with
150 additions
and
54 deletions
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc; |
17 | 17 | |
18 | 18 | import com.datastax.driver.core.utils.UUIDs; |
19 | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | |
20 | 21 | import com.google.common.util.concurrent.FutureCallback; |
21 | 22 | import com.google.common.util.concurrent.Futures; |
22 | 23 | import com.google.common.util.concurrent.ListenableFuture; |
... | ... | @@ -335,8 +336,8 @@ public final class EdgeGrpcSession implements Closeable { |
335 | 336 | case CREDENTIALS_REQUEST: |
336 | 337 | downlinkMsg = processCredentialsRequestMessage(edgeEvent); |
337 | 338 | break; |
338 | - case ENTITY_EXISTS_REQUEST: | |
339 | - downlinkMsg = processEntityExistsRequestMessage(edgeEvent); | |
339 | + case ENTITY_MERGE_REQUEST: | |
340 | + downlinkMsg = processEntityMergeRequestMessage(edgeEvent); | |
340 | 341 | break; |
341 | 342 | case RPC_CALL: |
342 | 343 | downlinkMsg = processRpcCallMsg(edgeEvent); |
... | ... | @@ -352,13 +353,18 @@ public final class EdgeGrpcSession implements Closeable { |
352 | 353 | return result; |
353 | 354 | } |
354 | 355 | |
355 | - private DownlinkMsg processEntityExistsRequestMessage(EdgeEvent edgeEvent) { | |
356 | + private DownlinkMsg processEntityMergeRequestMessage(EdgeEvent edgeEvent) { | |
356 | 357 | DownlinkMsg downlinkMsg = null; |
357 | 358 | if (EdgeEventType.DEVICE.equals(edgeEvent.getType())) { |
358 | 359 | DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); |
359 | 360 | Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), deviceId); |
360 | 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 | 368 | downlinkMsg = DownlinkMsg.newBuilder() |
363 | 369 | .addAllDeviceUpdateMsg(Collections.singletonList(d)) |
364 | 370 | .build(); |
... | ... | @@ -497,7 +503,7 @@ public final class EdgeGrpcSession implements Closeable { |
497 | 503 | if (device != null) { |
498 | 504 | CustomerId customerId = getCustomerIdIfEdgeAssignedToCustomer(device); |
499 | 505 | DeviceUpdateMsg deviceUpdateMsg = |
500 | - ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId); | |
506 | + ctx.getDeviceMsgConstructor().constructDeviceUpdatedMsg(msgType, device, customerId, null); | |
501 | 507 | downlinkMsg = DownlinkMsg.newBuilder() |
502 | 508 | .addAllDeviceUpdateMsg(Collections.singletonList(deviceUpdateMsg)) |
503 | 509 | .build(); | ... | ... |
... | ... | @@ -38,7 +38,7 @@ public class DeviceMsgConstructor { |
38 | 38 | |
39 | 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 | 42 | DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() |
43 | 43 | .setMsgType(msgType) |
44 | 44 | .setIdMSB(device.getId().getId().getMostSignificantBits()) |
... | ... | @@ -55,6 +55,9 @@ public class DeviceMsgConstructor { |
55 | 55 | if (device.getAdditionalInfo() != null) { |
56 | 56 | builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo())); |
57 | 57 | } |
58 | + if (conflictName != null) { | |
59 | + builder.setConflictName(conflictName); | |
60 | + } | |
58 | 61 | return builder.build(); |
59 | 62 | } |
60 | 63 | ... | ... |
... | ... | @@ -37,6 +37,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService; |
37 | 37 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
38 | 38 | import org.thingsboard.server.dao.device.DeviceService; |
39 | 39 | import org.thingsboard.server.dao.edge.EdgeEventService; |
40 | +import org.thingsboard.server.dao.edge.EdgeService; | |
40 | 41 | import org.thingsboard.server.dao.entityview.EntityViewService; |
41 | 42 | import org.thingsboard.server.dao.relation.RelationService; |
42 | 43 | import org.thingsboard.server.dao.user.UserService; |
... | ... | @@ -65,6 +66,9 @@ public abstract class BaseProcessor { |
65 | 66 | protected EntityViewService entityViewService; |
66 | 67 | |
67 | 68 | @Autowired |
69 | + protected EdgeService edgeService; | |
70 | + | |
71 | + @Autowired | |
68 | 72 | protected CustomerService customerService; |
69 | 73 | |
70 | 74 | @Autowired | ... | ... |
... | ... | @@ -17,12 +17,15 @@ package org.thingsboard.server.service.edge.rpc.processor; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
19 | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
20 | +import com.google.common.util.concurrent.FutureCallback; | |
20 | 21 | import com.google.common.util.concurrent.Futures; |
21 | 22 | import com.google.common.util.concurrent.ListenableFuture; |
22 | 23 | import com.google.common.util.concurrent.SettableFuture; |
23 | 24 | import lombok.extern.slf4j.Slf4j; |
24 | 25 | import org.apache.commons.lang.RandomStringUtils; |
25 | 26 | import org.apache.commons.lang.StringUtils; |
27 | +import org.checkerframework.checker.nullness.qual.Nullable; | |
28 | +import org.springframework.security.core.parameters.P; | |
26 | 29 | import org.springframework.stereotype.Component; |
27 | 30 | import org.thingsboard.rule.engine.api.RpcError; |
28 | 31 | import org.thingsboard.server.common.data.DataConstants; |
... | ... | @@ -52,6 +55,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; |
52 | 55 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
53 | 56 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg; |
54 | 57 | |
58 | +import java.util.List; | |
55 | 59 | import java.util.UUID; |
56 | 60 | import java.util.concurrent.locks.ReentrantLock; |
57 | 61 | |
... | ... | @@ -64,36 +68,62 @@ public class DeviceProcessor extends BaseProcessor { |
64 | 68 | |
65 | 69 | public ListenableFuture<Void> onDeviceUpdate(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { |
66 | 70 | log.trace("[{}] onDeviceUpdate [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName()); |
67 | - DeviceId edgeDeviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); | |
68 | 71 | switch (deviceUpdateMsg.getMsgType()) { |
69 | 72 | case ENTITY_CREATED_RPC_MESSAGE: |
70 | 73 | String deviceName = deviceUpdateMsg.getName(); |
71 | 74 | Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); |
72 | 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 | 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 | 118 | break; |
90 | 119 | case ENTITY_UPDATED_RPC_MESSAGE: |
91 | 120 | updateDevice(tenantId, edge, deviceUpdateMsg); |
92 | 121 | break; |
93 | 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 | 125 | if (deviceToDelete != null) { |
96 | - deviceService.unassignDeviceFromEdge(tenantId, edgeDeviceId, edge.getId()); | |
126 | + deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId()); | |
97 | 127 | } |
98 | 128 | break; |
99 | 129 | case UNRECOGNIZED: |
... | ... | @@ -103,7 +133,6 @@ public class DeviceProcessor extends BaseProcessor { |
103 | 133 | return Futures.immediateFuture(null); |
104 | 134 | } |
105 | 135 | |
106 | - | |
107 | 136 | public ListenableFuture<Void> onDeviceCredentialsUpdate(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { |
108 | 137 | log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg); |
109 | 138 | DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB())); |
... | ... | @@ -131,36 +160,34 @@ public class DeviceProcessor extends BaseProcessor { |
131 | 160 | private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { |
132 | 161 | DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); |
133 | 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 | 176 | Device device; |
145 | 177 | try { |
146 | 178 | deviceCreationLock.lock(); |
147 | 179 | log.debug("[{}] Creating device entity [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName()); |
148 | - DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); | |
149 | 180 | device = new Device(); |
150 | 181 | device.setTenantId(edge.getTenantId()); |
151 | 182 | device.setCustomerId(edge.getCustomerId()); |
152 | - device.setId(deviceId); | |
153 | - device.setName(deviceUpdateMsg.getName()); | |
183 | + device.setName(deviceName); | |
154 | 184 | device.setType(deviceUpdateMsg.getType()); |
155 | 185 | device.setLabel(deviceUpdateMsg.getLabel()); |
156 | 186 | device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo())); |
157 | 187 | device = deviceService.saveDevice(device); |
158 | - createDeviceCredentials(device); | |
159 | 188 | createRelationFromEdge(tenantId, edge.getId(), device.getId()); |
160 | 189 | deviceStateService.onDeviceAdded(device); |
161 | 190 | pushDeviceCreatedEventToRuleEngine(tenantId, edge, device); |
162 | - | |
163 | - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null); | |
164 | 191 | } finally { |
165 | 192 | deviceCreationLock.unlock(); |
166 | 193 | } |
... | ... | @@ -176,14 +203,6 @@ public class DeviceProcessor extends BaseProcessor { |
176 | 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 | 206 | private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) { |
188 | 207 | try { |
189 | 208 | DeviceId deviceId = device.getId(); | ... | ... |
... | ... | @@ -26,6 +26,7 @@ import com.google.protobuf.AbstractMessage; |
26 | 26 | import com.google.protobuf.InvalidProtocolBufferException; |
27 | 27 | import com.google.protobuf.MessageLite; |
28 | 28 | import lombok.extern.slf4j.Slf4j; |
29 | +import org.apache.commons.lang.RandomStringUtils; | |
29 | 30 | import org.junit.After; |
30 | 31 | import org.junit.Assert; |
31 | 32 | import org.junit.Before; |
... | ... | @@ -48,6 +49,7 @@ import org.thingsboard.server.common.data.edge.Edge; |
48 | 49 | import org.thingsboard.server.common.data.edge.EdgeEvent; |
49 | 50 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
50 | 51 | import org.thingsboard.server.common.data.edge.EdgeEventType; |
52 | +import org.thingsboard.server.common.data.id.DeviceId; | |
51 | 53 | import org.thingsboard.server.common.data.id.EdgeId; |
52 | 54 | import org.thingsboard.server.common.data.id.EntityId; |
53 | 55 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
... | ... | @@ -964,6 +966,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
964 | 966 | private void testSendMessagesToCloud() throws Exception { |
965 | 967 | log.info("Sending messages to cloud"); |
966 | 968 | sendDevice(); |
969 | + sendDeviceWithNameThatAlreadyExistsOnCloud(); | |
967 | 970 | sendRelationRequest(); |
968 | 971 | sendAlarm(); |
969 | 972 | sendTelemetry(); |
... | ... | @@ -992,17 +995,66 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
992 | 995 | uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build()); |
993 | 996 | |
994 | 997 | edgeImitator.expectResponsesAmount(1); |
995 | - | |
998 | + edgeImitator.expectMessageAmount(1); | |
996 | 999 | testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder); |
997 | 1000 | |
998 | 1001 | edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); |
1002 | + | |
999 | 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 | 1014 | Assert.assertNotNull(device); |
1003 | 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 | 1058 | private void sendRelationRequest() throws Exception { |
1007 | 1059 | Device device = findDeviceByName("Edge Device 1"); |
1008 | 1060 | Asset asset = findAssetByName("Edge Asset 1"); | ... | ... |
... | ... | @@ -97,7 +97,7 @@ enum UpdateMsgType { |
97 | 97 | ENTITY_DELETED_RPC_MESSAGE = 2; |
98 | 98 | ALARM_ACK_RPC_MESSAGE = 3; |
99 | 99 | ALARM_CLEAR_RPC_MESSAGE = 4; |
100 | - DEVICE_CONFLICT_RPC_MESSAGE = 5; | |
100 | + ENTITY_MERGE_RPC_MESSAGE = 5; | |
101 | 101 | } |
102 | 102 | |
103 | 103 | message EntityDataProto { |
... | ... | @@ -182,6 +182,7 @@ message DeviceUpdateMsg { |
182 | 182 | string type = 7; |
183 | 183 | string label = 8; |
184 | 184 | string additionalInfo = 9; |
185 | + string conflictName = 10; | |
185 | 186 | } |
186 | 187 | |
187 | 188 | message DeviceCredentialsUpdateMsg { | ... | ... |
... | ... | @@ -87,6 +87,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; |
87 | 87 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
88 | 88 | import org.thingsboard.server.common.data.rule.RuleChain; |
89 | 89 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
90 | +import org.thingsboard.server.common.data.rule.RuleChainType; | |
90 | 91 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
91 | 92 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
92 | 93 | import org.thingsboard.server.common.data.security.model.SecuritySettings; |
... | ... | @@ -97,6 +98,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; |
97 | 98 | import java.io.Closeable; |
98 | 99 | import java.io.IOException; |
99 | 100 | import java.net.URI; |
101 | +import java.util.Arrays; | |
100 | 102 | import java.util.Collections; |
101 | 103 | import java.util.HashMap; |
102 | 104 | import java.util.List; |
... | ... | @@ -626,22 +628,31 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { |
626 | 628 | } |
627 | 629 | |
628 | 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 | 635 | return restTemplate.exchange( |
630 | - baseURL + "/api/components?componentType={componentType}", | |
636 | + baseURL + "/api/components/" + componentType.name() + "/?ruleChainType={ruleChainType}", | |
631 | 637 | HttpMethod.GET, HttpEntity.EMPTY, |
632 | 638 | new ParameterizedTypeReference<List<ComponentDescriptor>>() { |
633 | 639 | }, |
634 | - componentType).getBody(); | |
640 | + ruleChainType).getBody(); | |
635 | 641 | } |
636 | 642 | |
637 | 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 | 648 | return restTemplate.exchange( |
639 | - baseURL + "/api/components?componentTypes={componentTypes}", | |
649 | + baseURL + "/api/components?componentTypes={componentTypes}&ruleChainType={ruleChainType}", | |
640 | 650 | HttpMethod.GET, |
641 | 651 | HttpEntity.EMPTY, |
642 | 652 | new ParameterizedTypeReference<List<ComponentDescriptor>>() { |
643 | 653 | }, |
644 | - listEnumToString(componentTypes)) | |
654 | + listEnumToString(componentTypes), | |
655 | + ruleChainType) | |
645 | 656 | .getBody(); |
646 | 657 | } |
647 | 658 | ... | ... |