Commit bf5f90d2712b2d01553a3829150abfb2079cd3cb

Authored by Volodymyr Babak
1 parent b2f4a082

Added support for user update. Push notification to rule engine in case device was created

@@ -23,12 +23,14 @@ import lombok.extern.slf4j.Slf4j; @@ -23,12 +23,14 @@ import lombok.extern.slf4j.Slf4j;
23 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
25 import org.thingsboard.server.common.data.EntityType; 25 import org.thingsboard.server.common.data.EntityType;
  26 +import org.thingsboard.server.common.data.User;
26 import org.thingsboard.server.common.data.alarm.Alarm; 27 import org.thingsboard.server.common.data.alarm.Alarm;
27 import org.thingsboard.server.common.data.audit.ActionType; 28 import org.thingsboard.server.common.data.audit.ActionType;
28 import org.thingsboard.server.common.data.edge.Edge; 29 import org.thingsboard.server.common.data.edge.Edge;
29 import org.thingsboard.server.common.data.edge.EdgeEvent; 30 import org.thingsboard.server.common.data.edge.EdgeEvent;
30 import org.thingsboard.server.common.data.edge.EdgeEventType; 31 import org.thingsboard.server.common.data.edge.EdgeEventType;
31 import org.thingsboard.server.common.data.id.AlarmId; 32 import org.thingsboard.server.common.data.id.AlarmId;
  33 +import org.thingsboard.server.common.data.id.CustomerId;
32 import org.thingsboard.server.common.data.id.DashboardId; 34 import org.thingsboard.server.common.data.id.DashboardId;
33 import org.thingsboard.server.common.data.id.EdgeId; 35 import org.thingsboard.server.common.data.id.EdgeId;
34 import org.thingsboard.server.common.data.id.EntityId; 36 import org.thingsboard.server.common.data.id.EntityId;
@@ -36,6 +38,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; @@ -36,6 +38,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory;
36 import org.thingsboard.server.common.data.id.IdBased; 38 import org.thingsboard.server.common.data.id.IdBased;
37 import org.thingsboard.server.common.data.id.RuleChainId; 39 import org.thingsboard.server.common.data.id.RuleChainId;
38 import org.thingsboard.server.common.data.id.TenantId; 40 import org.thingsboard.server.common.data.id.TenantId;
  41 +import org.thingsboard.server.common.data.id.UserId;
39 import org.thingsboard.server.common.data.page.TextPageData; 42 import org.thingsboard.server.common.data.page.TextPageData;
40 import org.thingsboard.server.common.data.page.TextPageLink; 43 import org.thingsboard.server.common.data.page.TextPageLink;
41 import org.thingsboard.server.common.data.page.TimePageData; 44 import org.thingsboard.server.common.data.page.TimePageData;
@@ -46,7 +49,9 @@ import org.thingsboard.server.common.msg.queue.TbCallback; @@ -46,7 +49,9 @@ import org.thingsboard.server.common.msg.queue.TbCallback;
46 import org.thingsboard.server.dao.alarm.AlarmService; 49 import org.thingsboard.server.dao.alarm.AlarmService;
47 import org.thingsboard.server.dao.edge.EdgeEventService; 50 import org.thingsboard.server.dao.edge.EdgeEventService;
48 import org.thingsboard.server.dao.edge.EdgeService; 51 import org.thingsboard.server.dao.edge.EdgeService;
  52 +import org.thingsboard.server.dao.model.ModelConstants;
49 import org.thingsboard.server.dao.relation.RelationService; 53 import org.thingsboard.server.dao.relation.RelationService;
  54 +import org.thingsboard.server.dao.user.UserService;
50 import org.thingsboard.server.gen.transport.TransportProtos; 55 import org.thingsboard.server.gen.transport.TransportProtos;
51 import org.thingsboard.server.queue.util.TbCoreComponent; 56 import org.thingsboard.server.queue.util.TbCoreComponent;
52 import org.thingsboard.server.service.executors.DbCallbackExecutorService; 57 import org.thingsboard.server.service.executors.DbCallbackExecutorService;
@@ -78,6 +83,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -78,6 +83,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
78 private AlarmService alarmService; 83 private AlarmService alarmService;
79 84
80 @Autowired 85 @Autowired
  86 + private UserService userService;
  87 +
  88 + @Autowired
81 private RelationService relationService; 89 private RelationService relationService;
82 90
83 @Autowired 91 @Autowired
@@ -142,6 +150,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -142,6 +150,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
142 switch (edgeEventType) { 150 switch (edgeEventType) {
143 // TODO: voba - handle edge updates 151 // TODO: voba - handle edge updates
144 // case EDGE: 152 // case EDGE:
  153 + case USER:
145 case ASSET: 154 case ASSET:
146 case DEVICE: 155 case DEVICE:
147 case ENTITY_VIEW: 156 case ENTITY_VIEW:
@@ -286,6 +295,15 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -286,6 +295,15 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
286 return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); 295 return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId())));
287 case RULE_CHAIN: 296 case RULE_CHAIN:
288 return convertToEdgeIds(edgeService.findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId()))); 297 return convertToEdgeIds(edgeService.findEdgesByTenantIdAndRuleChainId(tenantId, new RuleChainId(entityId.getId())));
  298 + case USER:
  299 + User userById = userService.findUserById(tenantId, new UserId(entityId.getId()));
  300 + TextPageData<Edge> edges;
  301 + if (userById.getCustomerId() == null || userById.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
  302 + edges = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE));
  303 + } else {
  304 + edges = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE));
  305 + }
  306 + return convertToEdgeIds(Futures.immediateFuture(edges.getData()));
289 default: 307 default:
290 return Futures.immediateFuture(Collections.emptyList()); 308 return Futures.immediateFuture(Collections.emptyList());
291 } 309 }
@@ -33,6 +33,9 @@ import org.thingsboard.server.dao.entityview.EntityViewService; @@ -33,6 +33,9 @@ import org.thingsboard.server.dao.entityview.EntityViewService;
33 import org.thingsboard.server.dao.relation.RelationService; 33 import org.thingsboard.server.dao.relation.RelationService;
34 import org.thingsboard.server.dao.rule.RuleChainService; 34 import org.thingsboard.server.dao.rule.RuleChainService;
35 import org.thingsboard.server.dao.user.UserService; 35 import org.thingsboard.server.dao.user.UserService;
  36 +import org.thingsboard.server.queue.discovery.PartitionService;
  37 +import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
  38 +import org.thingsboard.server.queue.util.TbCoreComponent;
36 import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings; 39 import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings;
37 import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor; 40 import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor;
38 import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor; 41 import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor;
@@ -49,6 +52,7 @@ import org.thingsboard.server.service.queue.TbClusterService; @@ -49,6 +52,7 @@ import org.thingsboard.server.service.queue.TbClusterService;
49 import org.thingsboard.server.service.state.DeviceStateService; 52 import org.thingsboard.server.service.state.DeviceStateService;
50 53
51 @Component 54 @Component
  55 +@TbCoreComponent
52 @Data 56 @Data
53 public class EdgeContextComponent { 57 public class EdgeContextComponent {
54 58
@@ -56,6 +60,13 @@ public class EdgeContextComponent { @@ -56,6 +60,13 @@ public class EdgeContextComponent {
56 @Autowired 60 @Autowired
57 private EdgeService edgeService; 61 private EdgeService edgeService;
58 62
  63 + @Autowired
  64 + private PartitionService partitionService;
  65 +
  66 + @Autowired
  67 + @Lazy
  68 + private TbQueueProducerProvider producerProvider;
  69 +
59 @Lazy 70 @Lazy
60 @Autowired 71 @Autowired
61 private EdgeNotificationService edgeNotificationService; 72 private EdgeNotificationService edgeNotificationService;
@@ -18,10 +18,10 @@ package org.thingsboard.server.service.edge.rpc; @@ -18,10 +18,10 @@ package org.thingsboard.server.service.edge.rpc;
18 import com.datastax.driver.core.utils.UUIDs; 18 import com.datastax.driver.core.utils.UUIDs;
19 import com.fasterxml.jackson.core.JsonProcessingException; 19 import com.fasterxml.jackson.core.JsonProcessingException;
20 import com.fasterxml.jackson.databind.ObjectMapper; 20 import com.fasterxml.jackson.databind.ObjectMapper;
  21 +import com.fasterxml.jackson.databind.node.ObjectNode;
21 import com.google.common.util.concurrent.FutureCallback; 22 import com.google.common.util.concurrent.FutureCallback;
22 import com.google.common.util.concurrent.Futures; 23 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture; 24 import com.google.common.util.concurrent.ListenableFuture;
24 -import com.google.common.util.concurrent.MoreExecutors;  
25 import com.google.gson.Gson; 25 import com.google.gson.Gson;
26 import com.google.gson.JsonElement; 26 import com.google.gson.JsonElement;
27 import com.google.gson.JsonObject; 27 import com.google.gson.JsonObject;
@@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.edge.Edge; @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.edge.Edge;
44 import org.thingsboard.server.common.data.edge.EdgeEvent; 44 import org.thingsboard.server.common.data.edge.EdgeEvent;
45 import org.thingsboard.server.common.data.id.AlarmId; 45 import org.thingsboard.server.common.data.id.AlarmId;
46 import org.thingsboard.server.common.data.id.AssetId; 46 import org.thingsboard.server.common.data.id.AssetId;
  47 +import org.thingsboard.server.common.data.id.CustomerId;
47 import org.thingsboard.server.common.data.id.DashboardId; 48 import org.thingsboard.server.common.data.id.DashboardId;
48 import org.thingsboard.server.common.data.id.DeviceId; 49 import org.thingsboard.server.common.data.id.DeviceId;
49 import org.thingsboard.server.common.data.id.EdgeId; 50 import org.thingsboard.server.common.data.id.EdgeId;
@@ -66,6 +67,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; @@ -66,6 +67,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType;
66 import org.thingsboard.server.common.data.security.UserCredentials; 67 import org.thingsboard.server.common.data.security.UserCredentials;
67 import org.thingsboard.server.common.msg.TbMsg; 68 import org.thingsboard.server.common.msg.TbMsg;
68 import org.thingsboard.server.common.msg.TbMsgMetaData; 69 import org.thingsboard.server.common.msg.TbMsgMetaData;
  70 +import org.thingsboard.server.common.msg.queue.ServiceType;
  71 +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
69 import org.thingsboard.server.common.msg.session.SessionMsgType; 72 import org.thingsboard.server.common.msg.session.SessionMsgType;
70 import org.thingsboard.server.common.transport.util.JsonUtils; 73 import org.thingsboard.server.common.transport.util.JsonUtils;
71 import org.thingsboard.server.gen.edge.AlarmUpdateMsg; 74 import org.thingsboard.server.gen.edge.AlarmUpdateMsg;
@@ -96,6 +99,10 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg; @@ -96,6 +99,10 @@ import org.thingsboard.server.gen.edge.UplinkResponseMsg;
96 import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; 99 import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg;
97 import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; 100 import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg;
98 import org.thingsboard.server.gen.transport.TransportProtos; 101 import org.thingsboard.server.gen.transport.TransportProtos;
  102 +import org.thingsboard.server.queue.TbQueueCallback;
  103 +import org.thingsboard.server.queue.TbQueueMsgMetadata;
  104 +import org.thingsboard.server.queue.TbQueueProducer;
  105 +import org.thingsboard.server.queue.common.TbProtoQueueMsg;
99 import org.thingsboard.server.service.edge.EdgeContextComponent; 106 import org.thingsboard.server.service.edge.EdgeContextComponent;
100 107
101 import java.io.Closeable; 108 import java.io.Closeable;
@@ -132,6 +139,8 @@ public final class EdgeGrpcSession implements Closeable { @@ -132,6 +139,8 @@ public final class EdgeGrpcSession implements Closeable {
132 private StreamObserver<ResponseMsg> outputStream; 139 private StreamObserver<ResponseMsg> outputStream;
133 private boolean connected; 140 private boolean connected;
134 141
  142 + private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> ruleEngineMsgProducer;
  143 +
135 EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver<ResponseMsg> outputStream, BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener, 144 EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver<ResponseMsg> outputStream, BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener,
136 Consumer<EdgeId> sessionCloseListener, ObjectMapper mapper) { 145 Consumer<EdgeId> sessionCloseListener, ObjectMapper mapper) {
137 this.sessionId = UUID.randomUUID(); 146 this.sessionId = UUID.randomUUID();
@@ -140,6 +149,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -140,6 +149,7 @@ public final class EdgeGrpcSession implements Closeable {
140 this.sessionOpenListener = sessionOpenListener; 149 this.sessionOpenListener = sessionOpenListener;
141 this.sessionCloseListener = sessionCloseListener; 150 this.sessionCloseListener = sessionCloseListener;
142 this.mapper = mapper; 151 this.mapper = mapper;
  152 + this.ruleEngineMsgProducer = ctx.getProducerProvider().getRuleEngineMsgProducer();
143 initInputStream(); 153 initInputStream();
144 } 154 }
145 155
@@ -767,17 +777,19 @@ public final class EdgeGrpcSession implements Closeable { @@ -767,17 +777,19 @@ public final class EdgeGrpcSession implements Closeable {
767 Device deviceById = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId); 777 Device deviceById = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId);
768 if (deviceById != null) { 778 if (deviceById != null) {
769 // this ID already used by other device - create new device and update ID on the edge 779 // this ID already used by other device - create new device and update ID on the edge
770 - Device savedDevice = createDevice(deviceUpdateMsg); 780 + device = createDevice(deviceUpdateMsg);
771 EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() 781 EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
772 - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, savedDevice)) 782 + .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device))
773 .build(); 783 .build();
774 outputStream.onNext(ResponseMsg.newBuilder() 784 outputStream.onNext(ResponseMsg.newBuilder()
775 .setEntityUpdateMsg(entityUpdateMsg) 785 .setEntityUpdateMsg(entityUpdateMsg)
776 .build()); 786 .build());
777 } else { 787 } else {
778 - createDevice(deviceUpdateMsg); 788 + device = createDevice(deviceUpdateMsg);
779 } 789 }
780 } 790 }
  791 + // TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment
  792 + ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
781 break; 793 break;
782 case ENTITY_UPDATED_RPC_MESSAGE: 794 case ENTITY_UPDATED_RPC_MESSAGE:
783 updateDevice(deviceUpdateMsg); 795 updateDevice(deviceUpdateMsg);
@@ -866,11 +878,9 @@ public final class EdgeGrpcSession implements Closeable { @@ -866,11 +878,9 @@ public final class EdgeGrpcSession implements Closeable {
866 device.setType(deviceUpdateMsg.getType()); 878 device.setType(deviceUpdateMsg.getType());
867 device.setLabel(deviceUpdateMsg.getLabel()); 879 device.setLabel(deviceUpdateMsg.getLabel());
868 device = ctx.getDeviceService().saveDevice(device); 880 device = ctx.getDeviceService().saveDevice(device);
869 - device = ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());  
870 createRelationFromEdge(device.getId()); 881 createRelationFromEdge(device.getId());
871 - ctx.getRelationService().saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(edge.getId(), device.getId(), "Created"));  
872 ctx.getDeviceStateService().onDeviceAdded(device); 882 ctx.getDeviceStateService().onDeviceAdded(device);
873 - 883 + pushDeviceCreatedEventToRuleEngine(device);
874 requestDeviceCredentialsFromEdge(device); 884 requestDeviceCredentialsFromEdge(device);
875 } finally { 885 } finally {
876 deviceCreationLock.unlock(); 886 deviceCreationLock.unlock();
@@ -878,6 +888,49 @@ public final class EdgeGrpcSession implements Closeable { @@ -878,6 +888,49 @@ public final class EdgeGrpcSession implements Closeable {
878 return device; 888 return device;
879 } 889 }
880 890
  891 + private void pushDeviceCreatedEventToRuleEngine(Device device) {
  892 + try {
  893 + ObjectNode entityNode = mapper.valueToTree(device);
  894 + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, device.getId(), getActionTbMsgMetaData(device.getCustomerId()), mapper.writeValueAsString(entityNode));
  895 + sendToRuleEngine(edge.getTenantId(), tbMsg, new TbQueueCallback() {
  896 + @Override
  897 + public void onSuccess(TbQueueMsgMetadata metadata) {
  898 + // TODO: voba - handle success
  899 + }
  900 +
  901 + @Override
  902 + public void onFailure(Throwable t) {
  903 + // TODO: voba - handle failure
  904 + }
  905 + });
  906 + } catch (JsonProcessingException | IllegalArgumentException e) {
  907 + log.warn("[{}] Failed to push device action to rule engine: {}", device.getId(), DataConstants.ENTITY_CREATED, e);
  908 + }
  909 + }
  910 +
  911 + protected void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) {
  912 + TopicPartitionInfo tpi = ctx.getPartitionService().resolve(ServiceType.TB_RULE_ENGINE, tenantId, tbMsg.getOriginator());
  913 + TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder().setTbMsg(TbMsg.toByteString(tbMsg))
  914 + .setTenantIdMSB(tenantId.getId().getMostSignificantBits())
  915 + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()).build();
  916 + ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), callback);
  917 + }
  918 +
  919 + private TbMsgMetaData getActionTbMsgMetaData(CustomerId customerId) {
  920 + TbMsgMetaData metaData = getTbMsgMetaData(edge);
  921 + if (customerId != null && !customerId.isNullUid()) {
  922 + metaData.putValue("customerId", customerId.toString());
  923 + }
  924 + return metaData;
  925 + }
  926 +
  927 + private TbMsgMetaData getTbMsgMetaData(Edge edge) {
  928 + TbMsgMetaData metaData = new TbMsgMetaData();
  929 + metaData.putValue("edgeId", edge.getId().toString());
  930 + metaData.putValue("edgeName", edge.getName());
  931 + return metaData;
  932 + }
  933 +
881 private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) { 934 private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) {
882 switch (entityType) { 935 switch (entityType) {
883 case DEVICE: 936 case DEVICE: