Commit cd2e89e834d2283ebc0145abe5393772812bf393

Authored by deaflynx
2 parents b5d99e50 6ffaca25

Merge branch 'feature/edge' of github.com:volodymyr-babak/thingsboard into feature/edge

Showing 79 changed files with 1179 additions and 917 deletions
@@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.RestController; @@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.RestController;
35 import org.thingsboard.rule.engine.api.MailService; 35 import org.thingsboard.rule.engine.api.MailService;
36 import org.thingsboard.server.common.data.User; 36 import org.thingsboard.server.common.data.User;
37 import org.thingsboard.server.common.data.audit.ActionType; 37 import org.thingsboard.server.common.data.audit.ActionType;
  38 +import org.thingsboard.server.common.data.edge.EdgeEventType;
38 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; 39 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
39 import org.thingsboard.server.common.data.exception.ThingsboardException; 40 import org.thingsboard.server.common.data.exception.ThingsboardException;
40 import org.thingsboard.server.common.data.id.TenantId; 41 import org.thingsboard.server.common.data.id.TenantId;
@@ -124,6 +125,9 @@ public class AuthController extends BaseController { @@ -124,6 +125,9 @@ public class AuthController extends BaseController {
124 } 125 }
125 userCredentials.setPassword(passwordEncoder.encode(newPassword)); 126 userCredentials.setPassword(passwordEncoder.encode(newPassword));
126 userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials); 127 userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials);
  128 +
  129 + sendNotificationMsgToEdgeService(getTenantId(), null, userCredentials.getUserId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED);
  130 +
127 } catch (Exception e) { 131 } catch (Exception e) {
128 throw handleException(e); 132 throw handleException(e);
129 } 133 }
@@ -26,12 +26,12 @@ import org.springframework.beans.factory.annotation.Value; @@ -26,12 +26,12 @@ import org.springframework.beans.factory.annotation.Value;
26 import org.springframework.security.core.Authentication; 26 import org.springframework.security.core.Authentication;
27 import org.springframework.security.core.context.SecurityContextHolder; 27 import org.springframework.security.core.context.SecurityContextHolder;
28 import org.springframework.web.bind.annotation.ExceptionHandler; 28 import org.springframework.web.bind.annotation.ExceptionHandler;
29 -import org.thingsboard.server.common.data.BaseData;  
30 import org.thingsboard.server.common.data.Customer; 29 import org.thingsboard.server.common.data.Customer;
31 import org.thingsboard.server.common.data.Dashboard; 30 import org.thingsboard.server.common.data.Dashboard;
32 import org.thingsboard.server.common.data.DashboardInfo; 31 import org.thingsboard.server.common.data.DashboardInfo;
33 import org.thingsboard.server.common.data.DataConstants; 32 import org.thingsboard.server.common.data.DataConstants;
34 import org.thingsboard.server.common.data.Device; 33 import org.thingsboard.server.common.data.Device;
  34 +import org.thingsboard.server.common.data.EdgeUtils;
35 import org.thingsboard.server.common.data.EntityType; 35 import org.thingsboard.server.common.data.EntityType;
36 import org.thingsboard.server.common.data.EntityView; 36 import org.thingsboard.server.common.data.EntityView;
37 import org.thingsboard.server.common.data.HasName; 37 import org.thingsboard.server.common.data.HasName;
@@ -39,14 +39,14 @@ import org.thingsboard.server.common.data.HasTenantId; @@ -39,14 +39,14 @@ import org.thingsboard.server.common.data.HasTenantId;
39 import org.thingsboard.server.common.data.Tenant; 39 import org.thingsboard.server.common.data.Tenant;
40 import org.thingsboard.server.common.data.User; 40 import org.thingsboard.server.common.data.User;
41 import org.thingsboard.server.common.data.alarm.Alarm; 41 import org.thingsboard.server.common.data.alarm.Alarm;
42 -import org.thingsboard.server.common.data.edge.EdgeEventType;  
43 -import org.thingsboard.server.common.data.id.AlarmId;  
44 import org.thingsboard.server.common.data.alarm.AlarmInfo; 42 import org.thingsboard.server.common.data.alarm.AlarmInfo;
45 import org.thingsboard.server.common.data.asset.Asset; 43 import org.thingsboard.server.common.data.asset.Asset;
46 import org.thingsboard.server.common.data.audit.ActionType; 44 import org.thingsboard.server.common.data.audit.ActionType;
47 import org.thingsboard.server.common.data.edge.Edge; 45 import org.thingsboard.server.common.data.edge.Edge;
  46 +import org.thingsboard.server.common.data.edge.EdgeEventType;
48 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; 47 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
49 import org.thingsboard.server.common.data.exception.ThingsboardException; 48 import org.thingsboard.server.common.data.exception.ThingsboardException;
  49 +import org.thingsboard.server.common.data.id.AlarmId;
50 import org.thingsboard.server.common.data.id.AssetId; 50 import org.thingsboard.server.common.data.id.AssetId;
51 import org.thingsboard.server.common.data.id.CustomerId; 51 import org.thingsboard.server.common.data.id.CustomerId;
52 import org.thingsboard.server.common.data.id.DashboardId; 52 import org.thingsboard.server.common.data.id.DashboardId;
@@ -85,7 +85,6 @@ import org.thingsboard.server.dao.dashboard.DashboardService; @@ -85,7 +85,6 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
85 import org.thingsboard.server.dao.device.ClaimDevicesService; 85 import org.thingsboard.server.dao.device.ClaimDevicesService;
86 import org.thingsboard.server.dao.device.DeviceCredentialsService; 86 import org.thingsboard.server.dao.device.DeviceCredentialsService;
87 import org.thingsboard.server.dao.device.DeviceService; 87 import org.thingsboard.server.dao.device.DeviceService;
88 -import org.thingsboard.server.dao.edge.EdgeEventService;  
89 import org.thingsboard.server.dao.edge.EdgeService; 88 import org.thingsboard.server.dao.edge.EdgeService;
90 import org.thingsboard.server.dao.entityview.EntityViewService; 89 import org.thingsboard.server.dao.entityview.EntityViewService;
91 import org.thingsboard.server.dao.exception.DataValidationException; 90 import org.thingsboard.server.dao.exception.DataValidationException;
@@ -113,7 +112,6 @@ import org.thingsboard.server.service.state.DeviceStateService; @@ -113,7 +112,6 @@ import org.thingsboard.server.service.state.DeviceStateService;
113 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; 112 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
114 113
115 import javax.mail.MessagingException; 114 import javax.mail.MessagingException;
116 -import javax.management.relation.Relation;  
117 import javax.servlet.http.HttpServletResponse; 115 import javax.servlet.http.HttpServletResponse;
118 import java.util.List; 116 import java.util.List;
119 import java.util.Optional; 117 import java.util.Optional;
@@ -209,9 +207,6 @@ public abstract class BaseController { @@ -209,9 +207,6 @@ public abstract class BaseController {
209 @Autowired 207 @Autowired
210 protected EdgeNotificationService edgeNotificationService; 208 protected EdgeNotificationService edgeNotificationService;
211 209
212 - @Autowired  
213 - protected EdgeEventService edgeEventService;  
214 -  
215 @Value("${server.log_controller_error_stack_trace}") 210 @Value("${server.log_controller_error_stack_trace}")
216 @Getter 211 @Getter
217 private boolean logControllerErrorStackTrace; 212 private boolean logControllerErrorStackTrace;
@@ -725,14 +720,17 @@ public abstract class BaseController { @@ -725,14 +720,17 @@ public abstract class BaseController {
725 720
726 protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) { 721 protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) {
727 try { 722 try {
728 - sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction); 723 + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
  724 + !relation.getTo().getEntityType().equals(EntityType.EDGE)) {
  725 + sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction);
  726 + }
729 } catch (Exception e) { 727 } catch (Exception e) {
730 log.warn("Failed to push relation to core: {}", relation, e); 728 log.warn("Failed to push relation to core: {}", relation, e);
731 } 729 }
732 } 730 }
733 731
734 protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) { 732 protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) {
735 - EdgeEventType edgeEventType = edgeEventService.getEdgeEventTypeByEntityType(entityId.getEntityType()); 733 + EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType());
736 if (edgeEventType != null) { 734 if (edgeEventType != null) {
737 sendNotificationMsgToEdgeService(tenantId, null, entityId, null, edgeEventType, edgeEventAction); 735 sendNotificationMsgToEdgeService(tenantId, null, entityId, null, edgeEventType, edgeEventAction);
738 } 736 }
@@ -35,17 +35,14 @@ import org.thingsboard.rule.engine.api.MailService; @@ -35,17 +35,14 @@ import org.thingsboard.rule.engine.api.MailService;
35 import org.thingsboard.server.common.data.EntityType; 35 import org.thingsboard.server.common.data.EntityType;
36 import org.thingsboard.server.common.data.User; 36 import org.thingsboard.server.common.data.User;
37 import org.thingsboard.server.common.data.audit.ActionType; 37 import org.thingsboard.server.common.data.audit.ActionType;
38 -import org.thingsboard.server.common.data.edge.Edge; 38 +import org.thingsboard.server.common.data.edge.EdgeEventType;
39 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; 39 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
40 import org.thingsboard.server.common.data.exception.ThingsboardException; 40 import org.thingsboard.server.common.data.exception.ThingsboardException;
41 import org.thingsboard.server.common.data.id.CustomerId; 41 import org.thingsboard.server.common.data.id.CustomerId;
42 -import org.thingsboard.server.common.data.id.EdgeId;  
43 import org.thingsboard.server.common.data.id.TenantId; 42 import org.thingsboard.server.common.data.id.TenantId;
44 import org.thingsboard.server.common.data.id.UserId; 43 import org.thingsboard.server.common.data.id.UserId;
45 import org.thingsboard.server.common.data.page.TextPageData; 44 import org.thingsboard.server.common.data.page.TextPageData;
46 import org.thingsboard.server.common.data.page.TextPageLink; 45 import org.thingsboard.server.common.data.page.TextPageLink;
47 -import org.thingsboard.server.common.data.page.TimePageData;  
48 -import org.thingsboard.server.common.data.page.TimePageLink;  
49 import org.thingsboard.server.common.data.security.Authority; 46 import org.thingsboard.server.common.data.security.Authority;
50 import org.thingsboard.server.common.data.security.UserCredentials; 47 import org.thingsboard.server.common.data.security.UserCredentials;
51 import org.thingsboard.server.queue.util.TbCoreComponent; 48 import org.thingsboard.server.queue.util.TbCoreComponent;
@@ -60,8 +57,6 @@ import org.thingsboard.server.utils.MiscUtils; @@ -60,8 +57,6 @@ import org.thingsboard.server.utils.MiscUtils;
60 57
61 import javax.servlet.http.HttpServletRequest; 58 import javax.servlet.http.HttpServletRequest;
62 59
63 -import static org.thingsboard.server.controller.EdgeController.EDGE_ID;  
64 -  
65 @RestController 60 @RestController
66 @TbCoreComponent 61 @TbCoreComponent
67 @RequestMapping("/api") 62 @RequestMapping("/api")
@@ -167,6 +162,8 @@ public class UserController extends BaseController { @@ -167,6 +162,8 @@ public class UserController extends BaseController {
167 savedUser.getCustomerId(), 162 savedUser.getCustomerId(),
168 user.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); 163 user.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
169 164
  165 + sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, user.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
  166 +
170 return savedUser; 167 return savedUser;
171 } catch (Exception e) { 168 } catch (Exception e) {
172 169
@@ -242,6 +239,8 @@ public class UserController extends BaseController { @@ -242,6 +239,8 @@ public class UserController extends BaseController {
242 user.getCustomerId(), 239 user.getCustomerId(),
243 ActionType.DELETED, null, strUserId); 240 ActionType.DELETED, null, strUserId);
244 241
  242 + sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, ActionType.DELETED);
  243 +
245 } catch (Exception e) { 244 } catch (Exception e) {
246 logEntityAction(emptyId(EntityType.USER), 245 logEntityAction(emptyId(EntityType.USER),
247 null, 246 null,
@@ -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,19 +38,20 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; @@ -36,19 +38,20 @@ 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;
42 import org.thingsboard.server.common.data.page.TimePageLink; 45 import org.thingsboard.server.common.data.page.TimePageLink;
43 import org.thingsboard.server.common.data.relation.EntityRelation; 46 import org.thingsboard.server.common.data.relation.EntityRelation;
44 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 47 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
45 -import org.thingsboard.server.common.data.rule.RuleChainMetaData;  
46 import org.thingsboard.server.common.msg.queue.TbCallback; 48 import org.thingsboard.server.common.msg.queue.TbCallback;
47 import org.thingsboard.server.dao.alarm.AlarmService; 49 import org.thingsboard.server.dao.alarm.AlarmService;
48 import org.thingsboard.server.dao.edge.EdgeEventService; 50 import org.thingsboard.server.dao.edge.EdgeEventService;
49 import org.thingsboard.server.dao.edge.EdgeService; 51 import org.thingsboard.server.dao.edge.EdgeService;
  52 +import org.thingsboard.server.dao.model.ModelConstants;
50 import org.thingsboard.server.dao.relation.RelationService; 53 import org.thingsboard.server.dao.relation.RelationService;
51 -import org.thingsboard.server.dao.rule.RuleChainService; 54 +import org.thingsboard.server.dao.user.UserService;
52 import org.thingsboard.server.gen.transport.TransportProtos; 55 import org.thingsboard.server.gen.transport.TransportProtos;
53 import org.thingsboard.server.queue.util.TbCoreComponent; 56 import org.thingsboard.server.queue.util.TbCoreComponent;
54 import org.thingsboard.server.service.executors.DbCallbackExecutorService; 57 import org.thingsboard.server.service.executors.DbCallbackExecutorService;
@@ -77,10 +80,10 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -77,10 +80,10 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
77 private EdgeService edgeService; 80 private EdgeService edgeService;
78 81
79 @Autowired 82 @Autowired
80 - private RuleChainService ruleChainService; 83 + private AlarmService alarmService;
81 84
82 @Autowired 85 @Autowired
83 - private AlarmService alarmService; 86 + private UserService userService;
84 87
85 @Autowired 88 @Autowired
86 private RelationService relationService; 89 private RelationService relationService;
@@ -147,12 +150,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -147,12 +150,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
147 switch (edgeEventType) { 150 switch (edgeEventType) {
148 // TODO: voba - handle edge updates 151 // TODO: voba - handle edge updates
149 // case EDGE: 152 // case EDGE:
  153 + case USER:
150 case ASSET: 154 case ASSET:
151 case DEVICE: 155 case DEVICE:
152 case ENTITY_VIEW: 156 case ENTITY_VIEW:
153 case DASHBOARD: 157 case DASHBOARD:
154 case RULE_CHAIN: 158 case RULE_CHAIN:
155 - processEntities(tenantId, edgeNotificationMsg); 159 + processEntity(tenantId, edgeNotificationMsg);
156 break; 160 break;
157 case ALARM: 161 case ALARM:
158 processAlarm(tenantId, edgeNotificationMsg); 162 processAlarm(tenantId, edgeNotificationMsg);
@@ -171,7 +175,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -171,7 +175,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
171 } 175 }
172 } 176 }
173 177
174 - private void processEntities(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { 178 + private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
175 ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()); 179 ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction());
176 EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType()); 180 EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType());
177 EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); 181 EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
@@ -179,16 +183,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -179,16 +183,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
179 // TODO: voba - ADDED is not required for CE version ? 183 // TODO: voba - ADDED is not required for CE version ?
180 // case ADDED: 184 // case ADDED:
181 case UPDATED: 185 case UPDATED:
  186 + case CREDENTIALS_UPDATED:
182 ListenableFuture<List<EdgeId>> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId); 187 ListenableFuture<List<EdgeId>> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId);
183 Futures.transform(edgeIdsFuture, edgeIds -> { 188 Futures.transform(edgeIdsFuture, edgeIds -> {
184 if (edgeIds != null && !edgeIds.isEmpty()) { 189 if (edgeIds != null && !edgeIds.isEmpty()) {
185 for (EdgeId edgeId : edgeIds) { 190 for (EdgeId edgeId : edgeIds) {
186 try { 191 try {
187 saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null); 192 saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null);
188 - if (edgeEventType.equals(EdgeEventType.RULE_CHAIN)) {  
189 - RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, new RuleChainId(entityId.getId()));  
190 - saveEdgeEvent(tenantId, edgeId, EdgeEventType.RULE_CHAIN_METADATA, edgeEventActionType, ruleChainMetaData.getRuleChainId(), null);  
191 - }  
192 } catch (Exception e) { 193 } catch (Exception e) {
193 log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]", 194 log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]",
194 tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e); 195 tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e);
@@ -245,32 +246,35 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -245,32 +246,35 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
245 } 246 }
246 247
247 private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { 248 private void processRelation(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
248 - EntityRelation entityRelation = mapper.convertValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class);  
249 - List<ListenableFuture<List<EdgeId>>> futures = new ArrayList<>();  
250 - futures.add(findRelatedEdgeIdsByEntityId(tenantId, entityRelation.getTo()));  
251 - futures.add(findRelatedEdgeIdsByEntityId(tenantId, entityRelation.getFrom()));  
252 - ListenableFuture<List<List<EdgeId>>> combinedFuture = Futures.allAsList(futures);  
253 - Futures.transform(combinedFuture, listOfListsEdgeIds -> {  
254 - Set<EdgeId> uniqueEdgeIds = new HashSet<>();  
255 - if (listOfListsEdgeIds != null && !listOfListsEdgeIds.isEmpty()) {  
256 - for (List<EdgeId> listOfListsEdgeId : listOfListsEdgeIds) {  
257 - if (listOfListsEdgeId != null) {  
258 - uniqueEdgeIds.addAll(listOfListsEdgeId); 249 + EntityRelation relation = mapper.convertValue(edgeNotificationMsg.getEntityBody(), EntityRelation.class);
  250 + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
  251 + !relation.getTo().getEntityType().equals(EntityType.EDGE)) {
  252 + List<ListenableFuture<List<EdgeId>>> futures = new ArrayList<>();
  253 + futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getTo()));
  254 + futures.add(findRelatedEdgeIdsByEntityId(tenantId, relation.getFrom()));
  255 + ListenableFuture<List<List<EdgeId>>> combinedFuture = Futures.allAsList(futures);
  256 + Futures.transform(combinedFuture, listOfListsEdgeIds -> {
  257 + Set<EdgeId> uniqueEdgeIds = new HashSet<>();
  258 + if (listOfListsEdgeIds != null && !listOfListsEdgeIds.isEmpty()) {
  259 + for (List<EdgeId> listOfListsEdgeId : listOfListsEdgeIds) {
  260 + if (listOfListsEdgeId != null) {
  261 + uniqueEdgeIds.addAll(listOfListsEdgeId);
  262 + }
259 } 263 }
260 } 264 }
261 - }  
262 - if (!uniqueEdgeIds.isEmpty()) {  
263 - for (EdgeId edgeId : uniqueEdgeIds) {  
264 - saveEdgeEvent(tenantId,  
265 - edgeId,  
266 - EdgeEventType.RELATION,  
267 - ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()),  
268 - null,  
269 - mapper.valueToTree(entityRelation)); 265 + if (!uniqueEdgeIds.isEmpty()) {
  266 + for (EdgeId edgeId : uniqueEdgeIds) {
  267 + saveEdgeEvent(tenantId,
  268 + edgeId,
  269 + EdgeEventType.RELATION,
  270 + ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction()),
  271 + null,
  272 + mapper.valueToTree(relation));
  273 + }
270 } 274 }
271 - }  
272 - return null;  
273 - }, dbCallbackExecutorService); 275 + return null;
  276 + }, dbCallbackExecutorService);
  277 + }
274 } 278 }
275 279
276 private ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { 280 private ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) {
@@ -278,7 +282,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -278,7 +282,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
278 case DEVICE: 282 case DEVICE:
279 case ASSET: 283 case ASSET:
280 case ENTITY_VIEW: 284 case ENTITY_VIEW:
281 - ListenableFuture<List<EntityRelation>> originatorEdgeRelationsFuture = relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); 285 + ListenableFuture<List<EntityRelation>> originatorEdgeRelationsFuture =
  286 + relationService.findByToAndTypeAsync(tenantId, entityId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
282 return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> { 287 return Futures.transform(originatorEdgeRelationsFuture, originatorEdgeRelations -> {
283 if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { 288 if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) {
284 return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId())); 289 return Collections.singletonList(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId()));
@@ -290,6 +295,15 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -290,6 +295,15 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
290 return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId()))); 295 return convertToEdgeIds(edgeService.findEdgesByTenantIdAndDashboardId(tenantId, new DashboardId(entityId.getId())));
291 case RULE_CHAIN: 296 case RULE_CHAIN:
292 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()));
293 default: 307 default:
294 return Futures.immediateFuture(Collections.emptyList()); 308 return Futures.immediateFuture(Collections.emptyList());
295 } 309 }
@@ -314,7 +328,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -314,7 +328,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
314 case ENTITY_VIEW: 328 case ENTITY_VIEW:
315 return EdgeEventType.ENTITY_VIEW; 329 return EdgeEventType.ENTITY_VIEW;
316 default: 330 default:
317 - log.info("Unsupported entity type: [{}]", entityType); 331 + log.debug("Unsupported entity type: [{}]", entityType);
318 return null; 332 return null;
319 } 333 }
320 } 334 }
@@ -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;
@@ -26,8 +26,6 @@ import org.springframework.beans.factory.annotation.Value; @@ -26,8 +26,6 @@ import org.springframework.beans.factory.annotation.Value;
26 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 26 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
27 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
28 import org.thingsboard.server.common.data.id.EdgeId; 28 import org.thingsboard.server.common.data.id.EdgeId;
29 -import org.thingsboard.server.common.data.id.RuleChainId;  
30 -import org.thingsboard.server.common.data.id.TenantId;  
31 import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc; 29 import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc;
32 import org.thingsboard.server.gen.edge.RequestMsg; 30 import org.thingsboard.server.gen.edge.RequestMsg;
33 import org.thingsboard.server.gen.edge.ResponseMsg; 31 import org.thingsboard.server.gen.edge.ResponseMsg;
@@ -48,7 +46,7 @@ import java.util.concurrent.Executors; @@ -48,7 +46,7 @@ import java.util.concurrent.Executors;
48 public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { 46 public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase {
49 47
50 private final Map<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>(); 48 private final Map<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>();
51 - private static final ObjectMapper objectMapper = new ObjectMapper(); 49 + private static final ObjectMapper mapper = new ObjectMapper();
52 50
53 @Value("${edges.rpc.port}") 51 @Value("${edges.rpc.port}")
54 private int rpcPort; 52 private int rpcPort;
@@ -102,7 +100,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase { @@ -102,7 +100,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase {
102 100
103 @Override 101 @Override
104 public StreamObserver<RequestMsg> handleMsgs(StreamObserver<ResponseMsg> outputStream) { 102 public StreamObserver<RequestMsg> handleMsgs(StreamObserver<ResponseMsg> outputStream) {
105 - return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, objectMapper).getInputStream(); 103 + return new EdgeGrpcSession(ctx, outputStream, this::onEdgeConnect, this::onEdgeDisconnect, mapper).getInputStream();
106 } 104 }
107 105
108 private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { 106 private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) {
@@ -22,13 +22,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode; @@ -22,13 +22,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
22 import com.google.common.util.concurrent.FutureCallback; 22 import com.google.common.util.concurrent.FutureCallback;
23 import com.google.common.util.concurrent.Futures; 23 import com.google.common.util.concurrent.Futures;
24 import com.google.common.util.concurrent.ListenableFuture; 24 import com.google.common.util.concurrent.ListenableFuture;
25 -import com.google.common.util.concurrent.MoreExecutors;  
26 import com.google.gson.Gson; 25 import com.google.gson.Gson;
27 import com.google.gson.JsonElement; 26 import com.google.gson.JsonElement;
28 import com.google.gson.JsonObject; 27 import com.google.gson.JsonObject;
29 import io.grpc.stub.StreamObserver; 28 import io.grpc.stub.StreamObserver;
30 import lombok.Data; 29 import lombok.Data;
31 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
  31 +import org.apache.commons.lang.RandomStringUtils;
32 import org.checkerframework.checker.nullness.qual.Nullable; 32 import org.checkerframework.checker.nullness.qual.Nullable;
33 import org.thingsboard.server.common.data.Dashboard; 33 import org.thingsboard.server.common.data.Dashboard;
34 import org.thingsboard.server.common.data.DataConstants; 34 import org.thingsboard.server.common.data.DataConstants;
@@ -45,6 +45,7 @@ import org.thingsboard.server.common.data.edge.Edge; @@ -45,6 +45,7 @@ import org.thingsboard.server.common.data.edge.Edge;
45 import org.thingsboard.server.common.data.edge.EdgeEvent; 45 import org.thingsboard.server.common.data.edge.EdgeEvent;
46 import org.thingsboard.server.common.data.id.AlarmId; 46 import org.thingsboard.server.common.data.id.AlarmId;
47 import org.thingsboard.server.common.data.id.AssetId; 47 import org.thingsboard.server.common.data.id.AssetId;
  48 +import org.thingsboard.server.common.data.id.CustomerId;
48 import org.thingsboard.server.common.data.id.DashboardId; 49 import org.thingsboard.server.common.data.id.DashboardId;
49 import org.thingsboard.server.common.data.id.DeviceId; 50 import org.thingsboard.server.common.data.id.DeviceId;
50 import org.thingsboard.server.common.data.id.EdgeId; 51 import org.thingsboard.server.common.data.id.EdgeId;
@@ -55,7 +56,6 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -55,7 +56,6 @@ import org.thingsboard.server.common.data.id.TenantId;
55 import org.thingsboard.server.common.data.id.UserId; 56 import org.thingsboard.server.common.data.id.UserId;
56 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 57 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
57 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; 58 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
58 -import org.thingsboard.server.common.data.kv.DataType;  
59 import org.thingsboard.server.common.data.kv.LongDataEntry; 59 import org.thingsboard.server.common.data.kv.LongDataEntry;
60 import org.thingsboard.server.common.data.page.TimePageData; 60 import org.thingsboard.server.common.data.page.TimePageData;
61 import org.thingsboard.server.common.data.page.TimePageLink; 61 import org.thingsboard.server.common.data.page.TimePageLink;
@@ -65,28 +65,45 @@ import org.thingsboard.server.common.data.rule.RuleChain; @@ -65,28 +65,45 @@ import org.thingsboard.server.common.data.rule.RuleChain;
65 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 65 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
66 import org.thingsboard.server.common.data.security.DeviceCredentials; 66 import org.thingsboard.server.common.data.security.DeviceCredentials;
67 import org.thingsboard.server.common.data.security.DeviceCredentialsType; 67 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
  68 +import org.thingsboard.server.common.data.security.UserCredentials;
68 import org.thingsboard.server.common.msg.TbMsg; 69 import org.thingsboard.server.common.msg.TbMsg;
69 import org.thingsboard.server.common.msg.TbMsgMetaData; 70 import org.thingsboard.server.common.msg.TbMsgMetaData;
  71 +import org.thingsboard.server.common.msg.queue.ServiceType;
  72 +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
70 import org.thingsboard.server.common.msg.session.SessionMsgType; 73 import org.thingsboard.server.common.msg.session.SessionMsgType;
71 import org.thingsboard.server.common.transport.util.JsonUtils; 74 import org.thingsboard.server.common.transport.util.JsonUtils;
72 import org.thingsboard.server.gen.edge.AlarmUpdateMsg; 75 import org.thingsboard.server.gen.edge.AlarmUpdateMsg;
  76 +import org.thingsboard.server.gen.edge.AssetUpdateMsg;
  77 +import org.thingsboard.server.gen.edge.AttributesRequestMsg;
73 import org.thingsboard.server.gen.edge.ConnectRequestMsg; 78 import org.thingsboard.server.gen.edge.ConnectRequestMsg;
74 import org.thingsboard.server.gen.edge.ConnectResponseCode; 79 import org.thingsboard.server.gen.edge.ConnectResponseCode;
75 import org.thingsboard.server.gen.edge.ConnectResponseMsg; 80 import org.thingsboard.server.gen.edge.ConnectResponseMsg;
  81 +import org.thingsboard.server.gen.edge.DashboardUpdateMsg;
  82 +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
  83 +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg;
76 import org.thingsboard.server.gen.edge.DeviceUpdateMsg; 84 import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
77 import org.thingsboard.server.gen.edge.DownlinkMsg; 85 import org.thingsboard.server.gen.edge.DownlinkMsg;
78 import org.thingsboard.server.gen.edge.EdgeConfiguration; 86 import org.thingsboard.server.gen.edge.EdgeConfiguration;
79 import org.thingsboard.server.gen.edge.EntityDataProto; 87 import org.thingsboard.server.gen.edge.EntityDataProto;
80 import org.thingsboard.server.gen.edge.EntityUpdateMsg; 88 import org.thingsboard.server.gen.edge.EntityUpdateMsg;
  89 +import org.thingsboard.server.gen.edge.EntityViewUpdateMsg;
  90 +import org.thingsboard.server.gen.edge.RelationRequestMsg;
81 import org.thingsboard.server.gen.edge.RequestMsg; 91 import org.thingsboard.server.gen.edge.RequestMsg;
82 import org.thingsboard.server.gen.edge.RequestMsgType; 92 import org.thingsboard.server.gen.edge.RequestMsgType;
83 import org.thingsboard.server.gen.edge.ResponseMsg; 93 import org.thingsboard.server.gen.edge.ResponseMsg;
84 import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; 94 import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg;
85 import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg; 95 import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg;
  96 +import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;
86 import org.thingsboard.server.gen.edge.UpdateMsgType; 97 import org.thingsboard.server.gen.edge.UpdateMsgType;
87 import org.thingsboard.server.gen.edge.UplinkMsg; 98 import org.thingsboard.server.gen.edge.UplinkMsg;
88 import org.thingsboard.server.gen.edge.UplinkResponseMsg; 99 import org.thingsboard.server.gen.edge.UplinkResponseMsg;
  100 +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg;
  101 +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg;
89 import org.thingsboard.server.gen.transport.TransportProtos; 102 import org.thingsboard.server.gen.transport.TransportProtos;
  103 +import org.thingsboard.server.queue.TbQueueCallback;
  104 +import org.thingsboard.server.queue.TbQueueMsgMetadata;
  105 +import org.thingsboard.server.queue.TbQueueProducer;
  106 +import org.thingsboard.server.queue.common.TbProtoQueueMsg;
90 import org.thingsboard.server.service.edge.EdgeContextComponent; 107 import org.thingsboard.server.service.edge.EdgeContextComponent;
91 108
92 import java.io.Closeable; 109 import java.io.Closeable;
@@ -115,7 +132,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -115,7 +132,7 @@ public final class EdgeGrpcSession implements Closeable {
115 private final UUID sessionId; 132 private final UUID sessionId;
116 private final BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener; 133 private final BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener;
117 private final Consumer<EdgeId> sessionCloseListener; 134 private final Consumer<EdgeId> sessionCloseListener;
118 - private final ObjectMapper objectMapper; 135 + private final ObjectMapper mapper;
119 136
120 private EdgeContextComponent ctx; 137 private EdgeContextComponent ctx;
121 private Edge edge; 138 private Edge edge;
@@ -123,14 +140,17 @@ public final class EdgeGrpcSession implements Closeable { @@ -123,14 +140,17 @@ public final class EdgeGrpcSession implements Closeable {
123 private StreamObserver<ResponseMsg> outputStream; 140 private StreamObserver<ResponseMsg> outputStream;
124 private boolean connected; 141 private boolean connected;
125 142
  143 + private TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> ruleEngineMsgProducer;
  144 +
126 EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver<ResponseMsg> outputStream, BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener, 145 EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver<ResponseMsg> outputStream, BiConsumer<EdgeId, EdgeGrpcSession> sessionOpenListener,
127 - Consumer<EdgeId> sessionCloseListener, ObjectMapper objectMapper) { 146 + Consumer<EdgeId> sessionCloseListener, ObjectMapper mapper) {
128 this.sessionId = UUID.randomUUID(); 147 this.sessionId = UUID.randomUUID();
129 this.ctx = ctx; 148 this.ctx = ctx;
130 this.outputStream = outputStream; 149 this.outputStream = outputStream;
131 this.sessionOpenListener = sessionOpenListener; 150 this.sessionOpenListener = sessionOpenListener;
132 this.sessionCloseListener = sessionCloseListener; 151 this.sessionCloseListener = sessionCloseListener;
133 - this.objectMapper = objectMapper; 152 + this.mapper = mapper;
  153 + this.ruleEngineMsgProducer = ctx.getProducerProvider().getRuleEngineMsgProducer();
134 initInputStream(); 154 initInputStream();
135 } 155 }
136 156
@@ -147,7 +167,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -147,7 +167,7 @@ public final class EdgeGrpcSession implements Closeable {
147 outputStream.onError(new RuntimeException(responseMsg.getErrorMsg())); 167 outputStream.onError(new RuntimeException(responseMsg.getErrorMsg()));
148 } 168 }
149 if (ConnectResponseCode.ACCEPTED == responseMsg.getResponseCode()) { 169 if (ConnectResponseCode.ACCEPTED == responseMsg.getResponseCode()) {
150 - ctx.getSyncEdgeService().sync(ctx, edge, outputStream); 170 + ctx.getSyncEdgeService().sync(edge);
151 } 171 }
152 } 172 }
153 if (connected) { 173 if (connected) {
@@ -184,14 +204,23 @@ public final class EdgeGrpcSession implements Closeable { @@ -184,14 +204,23 @@ public final class EdgeGrpcSession implements Closeable {
184 for (EdgeEvent edgeEvent : pageData.getData()) { 204 for (EdgeEvent edgeEvent : pageData.getData()) {
185 log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent); 205 log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent);
186 try { 206 try {
187 - UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction()));  
188 - if (msgType == null) {  
189 - processTelemetryMessage(edgeEvent);  
190 - } else {  
191 - processEntityCRUDMessage(edgeEvent, msgType);  
192 - if (ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) {  
193 - pushEntityAttributesToEdge(edgeEvent);  
194 - } 207 + ActionType edgeEventAction = ActionType.valueOf(edgeEvent.getEdgeEventAction());
  208 + switch (edgeEventAction) {
  209 + case UPDATED:
  210 + case ADDED:
  211 + case ASSIGNED_TO_EDGE:
  212 + case DELETED:
  213 + case UNASSIGNED_FROM_EDGE:
  214 + case ALARM_ACK:
  215 + case ALARM_CLEAR:
  216 + case CREDENTIALS_UPDATED:
  217 + processEntityMessage(edgeEvent, edgeEventAction);
  218 + break;
  219 + case ATTRIBUTES_UPDATED:
  220 + case ATTRIBUTES_DELETED:
  221 + case TIMESERIES_UPDATED:
  222 + processTelemetryMessage(edgeEvent);
  223 + break;
195 } 224 }
196 } catch (Exception e) { 225 } catch (Exception e) {
197 log.error("Exception during processing records from queue", e); 226 log.error("Exception during processing records from queue", e);
@@ -230,7 +259,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -230,7 +259,7 @@ public final class EdgeGrpcSession implements Closeable {
230 } else { 259 } else {
231 return 0L; 260 return 0L;
232 } 261 }
233 - }, MoreExecutors.directExecutor()); 262 + }, ctx.getDbCallbackExecutor());
234 } 263 }
235 264
236 private void updateQueueStartTs(Long newStartTs) { 265 private void updateQueueStartTs(Long newStartTs) {
@@ -239,12 +268,10 @@ public final class EdgeGrpcSession implements Closeable { @@ -239,12 +268,10 @@ public final class EdgeGrpcSession implements Closeable {
239 ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes); 268 ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes);
240 } 269 }
241 270
242 - private void pushEntityAttributesToEdge(EdgeEvent edgeEvent) throws IOException { 271 + private void processTelemetryMessage(EdgeEvent edgeEvent) throws IOException {
  272 + log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent);
243 EntityId entityId = null; 273 EntityId entityId = null;
244 switch (edgeEvent.getEdgeEventType()) { 274 switch (edgeEvent.getEdgeEventType()) {
245 - case EDGE:  
246 - entityId = edge.getId();  
247 - break;  
248 case DEVICE: 275 case DEVICE:
249 entityId = new DeviceId(edgeEvent.getEntityId()); 276 entityId = new DeviceId(edgeEvent.getEntityId());
250 break; 277 break;
@@ -259,59 +286,11 @@ public final class EdgeGrpcSession implements Closeable { @@ -259,59 +286,11 @@ public final class EdgeGrpcSession implements Closeable {
259 break; 286 break;
260 } 287 }
261 if (entityId != null) { 288 if (entityId != null) {
262 - final EntityId finalEntityId = entityId;  
263 - ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE);  
264 - Futures.transform(ssAttrFuture, ssAttributes -> {  
265 - if (ssAttributes != null && !ssAttributes.isEmpty()) {  
266 - try {  
267 - ObjectNode entityNode = objectMapper.createObjectNode();  
268 - for (AttributeKvEntry attr : ssAttributes) {  
269 - if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) {  
270 - entityNode.put(attr.getKey(), attr.getBooleanValue().get());  
271 - } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) {  
272 - entityNode.put(attr.getKey(), attr.getDoubleValue().get());  
273 - } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) {  
274 - entityNode.put(attr.getKey(), attr.getLongValue().get());  
275 - } else {  
276 - entityNode.put(attr.getKey(), attr.getValueAsString());  
277 - }  
278 - }  
279 - log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", finalEntityId, entityNode);  
280 - DownlinkMsg value = constructEntityDataProtoMsg(finalEntityId, ActionType.ATTRIBUTES_UPDATED, JsonUtils.parse(objectMapper.writeValueAsString(entityNode)));  
281 - outputStream.onNext(ResponseMsg.newBuilder()  
282 - .setDownlinkMsg(value).build());  
283 - } catch (Exception e) {  
284 - log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e);  
285 - }  
286 - }  
287 - return null;  
288 - }, MoreExecutors.directExecutor());  
289 - ListenableFuture<List<AttributeKvEntry>> shAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE);  
290 - ListenableFuture<List<AttributeKvEntry>> clAttrFuture = ctx.getAttributesService().findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE);  
291 - }  
292 - }  
293 -  
294 - private void processTelemetryMessage(EdgeEvent edgeEvent) throws IOException {  
295 - log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent);  
296 - EntityId entityId = null;  
297 - switch (edgeEvent.getEdgeEventType()) {  
298 - case DEVICE:  
299 - entityId = new DeviceId(edgeEvent.getEntityId());  
300 - break;  
301 - case ASSET:  
302 - entityId = new AssetId(edgeEvent.getEntityId());  
303 - break;  
304 - case ENTITY_VIEW:  
305 - entityId = new EntityViewId(edgeEvent.getEntityId());  
306 - break;  
307 -  
308 - }  
309 - if (entityId != null) {  
310 log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody()); 289 log.debug("Sending telemetry data msg, entityId [{}], body [{}]", edgeEvent.getEntityId(), edgeEvent.getEntityBody());
311 DownlinkMsg downlinkMsg; 290 DownlinkMsg downlinkMsg;
312 try { 291 try {
313 ActionType actionType = ActionType.valueOf(edgeEvent.getEdgeEventAction()); 292 ActionType actionType = ActionType.valueOf(edgeEvent.getEdgeEventAction());
314 - downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(objectMapper.writeValueAsString(edgeEvent.getEntityBody()))); 293 + downlinkMsg = constructEntityDataProtoMsg(entityId, actionType, JsonUtils.parse(mapper.writeValueAsString(edgeEvent.getEntityBody())));
315 outputStream.onNext(ResponseMsg.newBuilder() 294 outputStream.onNext(ResponseMsg.newBuilder()
316 .setDownlinkMsg(downlinkMsg) 295 .setDownlinkMsg(downlinkMsg)
317 .build()); 296 .build());
@@ -322,302 +301,268 @@ public final class EdgeGrpcSession implements Closeable { @@ -322,302 +301,268 @@ public final class EdgeGrpcSession implements Closeable {
322 } 301 }
323 } 302 }
324 303
325 - private void processEntityCRUDMessage(EdgeEvent edgeEvent, UpdateMsgType msgType) {  
326 - log.trace("Executing processEntityCRUDMessage, edgeEvent [{}], msgType [{}]", edgeEvent, msgType); 304 + private void processEntityMessage(EdgeEvent edgeEvent, ActionType edgeEventAction) {
  305 + UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction()));
  306 + log.trace("Executing processEntityMessage, edgeEvent [{}], edgeEventAction [{}], msgType [{}]", edgeEvent, edgeEventAction, msgType);
327 switch (edgeEvent.getEdgeEventType()) { 307 switch (edgeEvent.getEdgeEventType()) {
328 case EDGE: 308 case EDGE:
329 // TODO: voba - add edge update logic 309 // TODO: voba - add edge update logic
330 break; 310 break;
331 case DEVICE: 311 case DEVICE:
332 - processDeviceCRUD(edgeEvent, msgType); 312 + processDevice(edgeEvent, msgType, edgeEventAction);
333 break; 313 break;
334 case ASSET: 314 case ASSET:
335 - processAssetCRUD(edgeEvent, msgType); 315 + processAsset(edgeEvent, msgType, edgeEventAction);
336 break; 316 break;
337 case ENTITY_VIEW: 317 case ENTITY_VIEW:
338 - processEntityViewCRUD(edgeEvent, msgType); 318 + processEntityView(edgeEvent, msgType, edgeEventAction);
339 break; 319 break;
340 case DASHBOARD: 320 case DASHBOARD:
341 - processDashboardCRUD(edgeEvent, msgType); 321 + processDashboard(edgeEvent, msgType, edgeEventAction);
342 break; 322 break;
343 case RULE_CHAIN: 323 case RULE_CHAIN:
344 - processRuleChainCRUD(edgeEvent, msgType); 324 + processRuleChain(edgeEvent, msgType, edgeEventAction);
345 break; 325 break;
346 case RULE_CHAIN_METADATA: 326 case RULE_CHAIN_METADATA:
347 - processRuleChainMetadataCRUD(edgeEvent, msgType); 327 + processRuleChainMetadata(edgeEvent, msgType);
348 break; 328 break;
349 case ALARM: 329 case ALARM:
350 - processAlarmCRUD(edgeEvent, msgType); 330 + processAlarm(edgeEvent, msgType);
351 break; 331 break;
352 case USER: 332 case USER:
353 - processUserCRUD(edgeEvent, msgType); 333 + processUser(edgeEvent, msgType, edgeEventAction);
354 break; 334 break;
355 case RELATION: 335 case RELATION:
356 - processRelationCRUD(edgeEvent, msgType); 336 + processRelation(edgeEvent, msgType);
357 break; 337 break;
358 } 338 }
359 } 339 }
360 340
361 - private void processDeviceCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 341 + private void processDevice(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) {
362 DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); 342 DeviceId deviceId = new DeviceId(edgeEvent.getEntityId());
363 - switch (msgType) {  
364 - case ENTITY_CREATED_RPC_MESSAGE:  
365 - case ENTITY_UPDATED_RPC_MESSAGE:  
366 - case DEVICE_CONFLICT_RPC_MESSAGE:  
367 - ListenableFuture<Device> deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edgeEvent.getTenantId(), deviceId);  
368 - Futures.addCallback(deviceFuture,  
369 - new FutureCallback<Device>() {  
370 - @Override  
371 - public void onSuccess(@Nullable Device device) {  
372 - if (device != null) {  
373 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
374 - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device))  
375 - .build();  
376 - outputStream.onNext(ResponseMsg.newBuilder()  
377 - .setEntityUpdateMsg(entityUpdateMsg)  
378 - .build());  
379 - }  
380 - }  
381 -  
382 - @Override  
383 - public void onFailure(Throwable t) {  
384 - log.warn("Can't processDeviceCRUD, edgeEvent [{}]", edgeEvent, t);  
385 - }  
386 - }, ctx.getDbCallbackExecutor()); 343 + EntityUpdateMsg entityUpdateMsg = null;
  344 + switch (edgeActionType) {
  345 + case ADDED:
  346 + case UPDATED:
  347 + case ASSIGNED_TO_EDGE:
  348 + Device device = ctx.getDeviceService().findDeviceById(edgeEvent.getTenantId(), deviceId);
  349 + if (device != null) {
  350 + DeviceUpdateMsg deviceUpdateMsg =
  351 + ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(msgType, device);
  352 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  353 + .setDeviceUpdateMsg(deviceUpdateMsg)
  354 + .build();
  355 + }
387 break; 356 break;
388 - case ENTITY_DELETED_RPC_MESSAGE:  
389 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
390 - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId)) 357 + case DELETED:
  358 + case UNASSIGNED_FROM_EDGE:
  359 + DeviceUpdateMsg deviceUpdateMsg =
  360 + ctx.getDeviceUpdateMsgConstructor().constructDeviceDeleteMsg(deviceId);
  361 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  362 + .setDeviceUpdateMsg(deviceUpdateMsg)
391 .build(); 363 .build();
392 - outputStream.onNext(ResponseMsg.newBuilder()  
393 - .setEntityUpdateMsg(entityUpdateMsg)  
394 - .build()); 364 + break;
  365 + case CREDENTIALS_UPDATED:
  366 + DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), deviceId);
  367 + if (deviceCredentials != null) {
  368 + DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg =
  369 + ctx.getDeviceUpdateMsgConstructor().constructDeviceCredentialsUpdatedMsg(deviceCredentials);
  370 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  371 + .setDeviceCredentialsUpdateMsg(deviceCredentialsUpdateMsg)
  372 + .build();
  373 + }
  374 + break;
  375 + }
  376 + if (entityUpdateMsg != null) {
  377 + outputStream.onNext(ResponseMsg.newBuilder()
  378 + .setEntityUpdateMsg(entityUpdateMsg)
  379 + .build());
395 } 380 }
396 -  
397 -  
398 } 381 }
399 382
400 - private void processAssetCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 383 + private void processAsset(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) {
401 AssetId assetId = new AssetId(edgeEvent.getEntityId()); 384 AssetId assetId = new AssetId(edgeEvent.getEntityId());
402 - switch (msgType) {  
403 - case ENTITY_CREATED_RPC_MESSAGE:  
404 - case ENTITY_UPDATED_RPC_MESSAGE:  
405 - case DEVICE_CONFLICT_RPC_MESSAGE:  
406 - ListenableFuture<Asset> assetFuture = ctx.getAssetService().findAssetByIdAsync(edgeEvent.getTenantId(), assetId);  
407 - Futures.addCallback(assetFuture,  
408 - new FutureCallback<Asset>() {  
409 - @Override  
410 - public void onSuccess(@Nullable Asset asset) {  
411 - if (asset != null) {  
412 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
413 - .setAssetUpdateMsg(ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset))  
414 - .build();  
415 - outputStream.onNext(ResponseMsg.newBuilder()  
416 - .setEntityUpdateMsg(entityUpdateMsg)  
417 - .build());  
418 - }  
419 - }  
420 -  
421 - @Override  
422 - public void onFailure(Throwable t) {  
423 - log.warn("Can't processAssetCRUD, edgeEvent [{}]", edgeEvent, t);  
424 - }  
425 - }, ctx.getDbCallbackExecutor()); 385 + EntityUpdateMsg entityUpdateMsg = null;
  386 + switch (edgeEventAction) {
  387 + case ADDED:
  388 + case UPDATED:
  389 + case ASSIGNED_TO_EDGE:
  390 + Asset asset = ctx.getAssetService().findAssetById(edgeEvent.getTenantId(), assetId);
  391 + if (asset != null) {
  392 + AssetUpdateMsg assetUpdateMsg =
  393 + ctx.getAssetUpdateMsgConstructor().constructAssetUpdatedMsg(msgType, asset);
  394 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  395 + .setAssetUpdateMsg(assetUpdateMsg)
  396 + .build();
  397 + }
426 break; 398 break;
427 - case ENTITY_DELETED_RPC_MESSAGE:  
428 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
429 - .setAssetUpdateMsg(ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId)) 399 + case DELETED:
  400 + case UNASSIGNED_FROM_EDGE:
  401 + AssetUpdateMsg assetUpdateMsg =
  402 + ctx.getAssetUpdateMsgConstructor().constructAssetDeleteMsg(assetId);
  403 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  404 + .setAssetUpdateMsg(assetUpdateMsg)
430 .build(); 405 .build();
431 - outputStream.onNext(ResponseMsg.newBuilder()  
432 - .setEntityUpdateMsg(entityUpdateMsg)  
433 - .build());  
434 break; 406 break;
435 } 407 }
  408 + if (entityUpdateMsg != null) {
  409 + outputStream.onNext(ResponseMsg.newBuilder()
  410 + .setEntityUpdateMsg(entityUpdateMsg)
  411 + .build());
  412 + }
436 } 413 }
437 414
438 - private void processEntityViewCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 415 + private void processEntityView(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) {
439 EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId()); 416 EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId());
440 - switch (msgType) {  
441 - case ENTITY_CREATED_RPC_MESSAGE:  
442 - case ENTITY_UPDATED_RPC_MESSAGE:  
443 - case DEVICE_CONFLICT_RPC_MESSAGE:  
444 - ListenableFuture<EntityView> entityViewFuture = ctx.getEntityViewService().findEntityViewByIdAsync(edgeEvent.getTenantId(), entityViewId);  
445 - Futures.addCallback(entityViewFuture,  
446 - new FutureCallback<EntityView>() {  
447 - @Override  
448 - public void onSuccess(@Nullable EntityView entityView) {  
449 - if (entityView != null) {  
450 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
451 - .setEntityViewUpdateMsg(ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView))  
452 - .build();  
453 - outputStream.onNext(ResponseMsg.newBuilder()  
454 - .setEntityUpdateMsg(entityUpdateMsg)  
455 - .build());  
456 - }  
457 - }  
458 -  
459 - @Override  
460 - public void onFailure(Throwable t) {  
461 - log.warn("Can't processEntityViewCRUD, edgeEvent [{}]", edgeEvent, t);  
462 - }  
463 - }, ctx.getDbCallbackExecutor()); 417 + EntityUpdateMsg entityUpdateMsg = null;
  418 + switch (edgeEventAction) {
  419 + case ADDED:
  420 + case UPDATED:
  421 + case ASSIGNED_TO_EDGE:
  422 + EntityView entityView = ctx.getEntityViewService().findEntityViewById(edgeEvent.getTenantId(), entityViewId);
  423 + if (entityView != null) {
  424 + EntityViewUpdateMsg entityViewUpdateMsg =
  425 + ctx.getEntityViewUpdateMsgConstructor().constructEntityViewUpdatedMsg(msgType, entityView);
  426 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  427 + .setEntityViewUpdateMsg(entityViewUpdateMsg)
  428 + .build();
  429 + }
464 break; 430 break;
465 - case ENTITY_DELETED_RPC_MESSAGE:  
466 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
467 - .setEntityViewUpdateMsg(ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId)) 431 + case DELETED:
  432 + case UNASSIGNED_FROM_EDGE:
  433 + EntityViewUpdateMsg entityViewUpdateMsg =
  434 + ctx.getEntityViewUpdateMsgConstructor().constructEntityViewDeleteMsg(entityViewId);
  435 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  436 + .setEntityViewUpdateMsg(entityViewUpdateMsg)
468 .build(); 437 .build();
469 - outputStream.onNext(ResponseMsg.newBuilder()  
470 - .setEntityUpdateMsg(entityUpdateMsg)  
471 - .build());  
472 break; 438 break;
473 } 439 }
  440 + if (entityUpdateMsg != null) {
  441 + outputStream.onNext(ResponseMsg.newBuilder()
  442 + .setEntityUpdateMsg(entityUpdateMsg)
  443 + .build());
  444 + }
474 } 445 }
475 446
476 - private void processDashboardCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 447 + private void processDashboard(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) {
477 DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId()); 448 DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId());
478 - switch (msgType) {  
479 - case ENTITY_CREATED_RPC_MESSAGE:  
480 - case ENTITY_UPDATED_RPC_MESSAGE:  
481 - case DEVICE_CONFLICT_RPC_MESSAGE:  
482 - ListenableFuture<Dashboard> dashboardFuture = ctx.getDashboardService().findDashboardByIdAsync(edgeEvent.getTenantId(), dashboardId);  
483 - Futures.addCallback(dashboardFuture,  
484 - new FutureCallback<Dashboard>() {  
485 - @Override  
486 - public void onSuccess(@Nullable Dashboard dashboard) {  
487 - if (dashboard != null) {  
488 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
489 - .setDashboardUpdateMsg(ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard))  
490 - .build();  
491 - outputStream.onNext(ResponseMsg.newBuilder()  
492 - .setEntityUpdateMsg(entityUpdateMsg)  
493 - .build());  
494 - }  
495 - }  
496 -  
497 - @Override  
498 - public void onFailure(Throwable t) {  
499 - log.warn("Can't processDashboardCRUD, edgeEvent [{}]", edgeEvent, t);  
500 - }  
501 - }, ctx.getDbCallbackExecutor()); 449 + EntityUpdateMsg entityUpdateMsg = null;
  450 + switch (edgeEventAction) {
  451 + case ADDED:
  452 + case UPDATED:
  453 + case ASSIGNED_TO_EDGE:
  454 + Dashboard dashboard = ctx.getDashboardService().findDashboardById(edgeEvent.getTenantId(), dashboardId);
  455 + if (dashboard != null) {
  456 + DashboardUpdateMsg dashboardUpdateMsg =
  457 + ctx.getDashboardUpdateMsgConstructor().constructDashboardUpdatedMsg(msgType, dashboard);
  458 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  459 + .setDashboardUpdateMsg(dashboardUpdateMsg)
  460 + .build();
  461 + }
502 break; 462 break;
503 - case ENTITY_DELETED_RPC_MESSAGE:  
504 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
505 - .setDashboardUpdateMsg(ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId)) 463 + case DELETED:
  464 + case UNASSIGNED_FROM_EDGE:
  465 + DashboardUpdateMsg dashboardUpdateMsg =
  466 + ctx.getDashboardUpdateMsgConstructor().constructDashboardDeleteMsg(dashboardId);
  467 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  468 + .setDashboardUpdateMsg(dashboardUpdateMsg)
506 .build(); 469 .build();
507 - outputStream.onNext(ResponseMsg.newBuilder()  
508 - .setEntityUpdateMsg(entityUpdateMsg)  
509 - .build());  
510 break; 470 break;
511 } 471 }
  472 + if (entityUpdateMsg != null) {
  473 + outputStream.onNext(ResponseMsg.newBuilder()
  474 + .setEntityUpdateMsg(entityUpdateMsg)
  475 + .build());
  476 + }
512 } 477 }
513 478
514 - private void processRuleChainCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 479 + private void processRuleChain(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeEventAction) {
515 RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); 480 RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId());
516 - switch (msgType) {  
517 - case ENTITY_CREATED_RPC_MESSAGE:  
518 - case ENTITY_UPDATED_RPC_MESSAGE:  
519 - case DEVICE_CONFLICT_RPC_MESSAGE:  
520 - ListenableFuture<RuleChain> ruleChainFuture = ctx.getRuleChainService().findRuleChainByIdAsync(edgeEvent.getTenantId(), ruleChainId);  
521 - Futures.addCallback(ruleChainFuture,  
522 - new FutureCallback<RuleChain>() {  
523 - @Override  
524 - public void onSuccess(@Nullable RuleChain ruleChain) {  
525 - if (ruleChain != null) {  
526 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
527 - .setRuleChainUpdateMsg(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain))  
528 - .build();  
529 - outputStream.onNext(ResponseMsg.newBuilder()  
530 - .setEntityUpdateMsg(entityUpdateMsg)  
531 - .build());  
532 - }  
533 - }  
534 -  
535 - @Override  
536 - public void onFailure(Throwable t) {  
537 - log.warn("Can't processRuleChainCRUD, edgeEvent [{}]", edgeEvent, t);  
538 - }  
539 - }, ctx.getDbCallbackExecutor()); 481 + EntityUpdateMsg entityUpdateMsg = null;
  482 + switch (edgeEventAction) {
  483 + case ADDED:
  484 + case UPDATED:
  485 + case ASSIGNED_TO_EDGE:
  486 + RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId);
  487 + if (ruleChain != null) {
  488 + RuleChainUpdateMsg ruleChainUpdateMsg =
  489 + ctx.getRuleChainUpdateMsgConstructor().constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain);
  490 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  491 + .setRuleChainUpdateMsg(ruleChainUpdateMsg)
  492 + .build();
  493 + }
540 break; 494 break;
541 - case ENTITY_DELETED_RPC_MESSAGE:  
542 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() 495 + case DELETED:
  496 + case UNASSIGNED_FROM_EDGE:
  497 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
543 .setRuleChainUpdateMsg(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainDeleteMsg(ruleChainId)) 498 .setRuleChainUpdateMsg(ctx.getRuleChainUpdateMsgConstructor().constructRuleChainDeleteMsg(ruleChainId))
544 .build(); 499 .build();
545 - outputStream.onNext(ResponseMsg.newBuilder()  
546 - .setEntityUpdateMsg(entityUpdateMsg)  
547 - .build());  
548 break; 500 break;
549 } 501 }
  502 + if (entityUpdateMsg != null) {
  503 + outputStream.onNext(ResponseMsg.newBuilder()
  504 + .setEntityUpdateMsg(entityUpdateMsg)
  505 + .build());
  506 + }
550 } 507 }
551 508
552 - private void processRuleChainMetadataCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 509 + private void processRuleChainMetadata(EdgeEvent edgeEvent, UpdateMsgType msgType) {
553 RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); 510 RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId());
554 - ListenableFuture<RuleChain> ruleChainFuture = ctx.getRuleChainService().findRuleChainByIdAsync(edgeEvent.getTenantId(), ruleChainId);  
555 - Futures.addCallback(ruleChainFuture,  
556 - new FutureCallback<RuleChain>() {  
557 - @Override  
558 - public void onSuccess(@Nullable RuleChain ruleChain) {  
559 - if (ruleChain != null) {  
560 - RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId);  
561 - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =  
562 - ctx.getRuleChainUpdateMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData);  
563 - if (ruleChainMetadataUpdateMsg != null) {  
564 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
565 - .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg)  
566 - .build();  
567 - outputStream.onNext(ResponseMsg.newBuilder()  
568 - .setEntityUpdateMsg(entityUpdateMsg)  
569 - .build());  
570 - }  
571 - }  
572 - }  
573 -  
574 - @Override  
575 - public void onFailure(Throwable t) {  
576 - log.warn("Can't processRuleChainMetadataCRUD, edgeEvent [{}]", edgeEvent, t);  
577 - }  
578 - }, ctx.getDbCallbackExecutor()); 511 + RuleChain ruleChain = ctx.getRuleChainService().findRuleChainById(edgeEvent.getTenantId(), ruleChainId);
  512 + if (ruleChain != null) {
  513 + RuleChainMetaData ruleChainMetaData = ctx.getRuleChainService().loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId);
  514 + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =
  515 + ctx.getRuleChainUpdateMsgConstructor().constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData);
  516 + if (ruleChainMetadataUpdateMsg != null) {
  517 + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
  518 + .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg)
  519 + .build();
  520 + outputStream.onNext(ResponseMsg.newBuilder()
  521 + .setEntityUpdateMsg(entityUpdateMsg)
  522 + .build());
  523 + }
  524 + }
579 } 525 }
580 526
581 - private void processUserCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) { 527 + private void processUser(EdgeEvent edgeEvent, UpdateMsgType msgType, ActionType edgeActionType) {
582 UserId userId = new UserId(edgeEvent.getEntityId()); 528 UserId userId = new UserId(edgeEvent.getEntityId());
583 - switch (msgType) {  
584 - case ENTITY_CREATED_RPC_MESSAGE:  
585 - case ENTITY_UPDATED_RPC_MESSAGE:  
586 - case DEVICE_CONFLICT_RPC_MESSAGE:  
587 - ListenableFuture<User> userFuture = ctx.getUserService().findUserByIdAsync(edgeEvent.getTenantId(), userId);  
588 - Futures.addCallback(userFuture,  
589 - new FutureCallback<User>() {  
590 - @Override  
591 - public void onSuccess(@Nullable User user) {  
592 - if (user != null) {  
593 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
594 - .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user))  
595 - .build();  
596 - outputStream.onNext(ResponseMsg.newBuilder()  
597 - .setEntityUpdateMsg(entityUpdateMsg)  
598 - .build());  
599 - }  
600 - }  
601 -  
602 - @Override  
603 - public void onFailure(Throwable t) {  
604 - log.warn("Can't processUserCRUD, edgeEvent [{}]", edgeEvent, t);  
605 - }  
606 - }, ctx.getDbCallbackExecutor()); 529 + EntityUpdateMsg entityUpdateMsg = null;
  530 + switch (edgeActionType) {
  531 + case ADDED:
  532 + case UPDATED:
  533 + case ASSIGNED_TO_EDGE:
  534 + User user = ctx.getUserService().findUserById(edgeEvent.getTenantId(), userId);
  535 + if (user != null) {
  536 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  537 + .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserUpdatedMsg(msgType, user))
  538 + .build();
  539 + }
607 break; 540 break;
608 - case ENTITY_DELETED_RPC_MESSAGE:  
609 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() 541 + case DELETED:
  542 + case UNASSIGNED_FROM_EDGE:
  543 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
610 .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId)) 544 .setUserUpdateMsg(ctx.getUserUpdateMsgConstructor().constructUserDeleteMsg(userId))
611 .build(); 545 .build();
612 - outputStream.onNext(ResponseMsg.newBuilder()  
613 - .setEntityUpdateMsg(entityUpdateMsg)  
614 - .build());  
615 break; 546 break;
  547 + case CREDENTIALS_UPDATED:
  548 + UserCredentials userCredentialsByUserId = ctx.getUserService().findUserCredentialsByUserId(edge.getTenantId(), userId);
  549 + if (userCredentialsByUserId != null) {
  550 + UserCredentialsUpdateMsg userCredentialsUpdateMsg =
  551 + ctx.getUserUpdateMsgConstructor().constructUserCredentialsUpdatedMsg(userCredentialsByUserId);
  552 + entityUpdateMsg = EntityUpdateMsg.newBuilder()
  553 + .setUserCredentialsUpdateMsg(userCredentialsUpdateMsg)
  554 + .build();
  555 + }
  556 + }
  557 + if (entityUpdateMsg != null) {
  558 + outputStream.onNext(ResponseMsg.newBuilder()
  559 + .setEntityUpdateMsg(entityUpdateMsg)
  560 + .build());
616 } 561 }
617 } 562 }
618 563
619 - private void processRelationCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) {  
620 - EntityRelation entityRelation = objectMapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class); 564 + private void processRelation(EdgeEvent edgeEvent, UpdateMsgType msgType) {
  565 + EntityRelation entityRelation = mapper.convertValue(edgeEvent.getEntityBody(), EntityRelation.class);
621 EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() 566 EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
622 .setRelationUpdateMsg(ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation)) 567 .setRelationUpdateMsg(ctx.getRelationUpdateMsgConstructor().constructRelationUpdatedMsg(msgType, entityRelation))
623 .build(); 568 .build();
@@ -626,33 +571,27 @@ public final class EdgeGrpcSession implements Closeable { @@ -626,33 +571,27 @@ public final class EdgeGrpcSession implements Closeable {
626 .build()); 571 .build());
627 } 572 }
628 573
629 - private void processAlarmCRUD(EdgeEvent edgeEvent, UpdateMsgType msgType) {  
630 - AlarmId alarmId = new AlarmId(edgeEvent.getEntityId());  
631 - ListenableFuture<Alarm> alarmFuture = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId);  
632 - Futures.addCallback(alarmFuture,  
633 - new FutureCallback<Alarm>() {  
634 - @Override  
635 - public void onSuccess(@Nullable Alarm alarm) {  
636 - if (alarm != null) {  
637 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
638 - .setAlarmUpdateMsg(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm))  
639 - .build();  
640 - outputStream.onNext(ResponseMsg.newBuilder()  
641 - .setEntityUpdateMsg(entityUpdateMsg)  
642 - .build());  
643 - }  
644 - }  
645 -  
646 - @Override  
647 - public void onFailure(Throwable t) {  
648 - log.warn("Can't processAlarmCRUD, edgeEvent [{}]", edgeEvent, t);  
649 - }  
650 - }, ctx.getDbCallbackExecutor()); 574 + private void processAlarm(EdgeEvent edgeEvent, UpdateMsgType msgType) {
  575 + try {
  576 + AlarmId alarmId = new AlarmId(edgeEvent.getEntityId());
  577 + Alarm alarm = ctx.getAlarmService().findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get();
  578 + if (alarm != null) {
  579 + EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
  580 + .setAlarmUpdateMsg(ctx.getAlarmUpdateMsgConstructor().constructAlarmUpdatedMsg(edge.getTenantId(), msgType, alarm))
  581 + .build();
  582 + outputStream.onNext(ResponseMsg.newBuilder()
  583 + .setEntityUpdateMsg(entityUpdateMsg)
  584 + .build());
  585 + }
  586 + } catch (Exception e) {
  587 + log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e);
  588 + }
651 } 589 }
652 590
653 private UpdateMsgType getResponseMsgType(ActionType actionType) { 591 private UpdateMsgType getResponseMsgType(ActionType actionType) {
654 switch (actionType) { 592 switch (actionType) {
655 case UPDATED: 593 case UPDATED:
  594 + case CREDENTIALS_UPDATED:
656 return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; 595 return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE;
657 case ADDED: 596 case ADDED:
658 case ASSIGNED_TO_EDGE: 597 case ASSIGNED_TO_EDGE:
@@ -664,10 +603,6 @@ public final class EdgeGrpcSession implements Closeable { @@ -664,10 +603,6 @@ public final class EdgeGrpcSession implements Closeable {
664 return UpdateMsgType.ALARM_ACK_RPC_MESSAGE; 603 return UpdateMsgType.ALARM_ACK_RPC_MESSAGE;
665 case ALARM_CLEAR: 604 case ALARM_CLEAR:
666 return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE; 605 return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE;
667 - case ATTRIBUTES_UPDATED:  
668 - case ATTRIBUTES_DELETED:  
669 - case TIMESERIES_DELETED:  
670 - return null;  
671 default: 606 default:
672 throw new RuntimeException("Unsupported actionType [" + actionType + "]"); 607 throw new RuntimeException("Unsupported actionType [" + actionType + "]");
673 } 608 }
@@ -702,11 +637,17 @@ public final class EdgeGrpcSession implements Closeable { @@ -702,11 +637,17 @@ public final class EdgeGrpcSession implements Closeable {
702 } 637 }
703 } 638 }
704 } 639 }
  640 +
705 if (uplinkMsg.getDeviceUpdateMsgList() != null && !uplinkMsg.getDeviceUpdateMsgList().isEmpty()) { 641 if (uplinkMsg.getDeviceUpdateMsgList() != null && !uplinkMsg.getDeviceUpdateMsgList().isEmpty()) {
706 for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) { 642 for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) {
707 onDeviceUpdate(deviceUpdateMsg); 643 onDeviceUpdate(deviceUpdateMsg);
708 } 644 }
709 } 645 }
  646 + if (uplinkMsg.getDeviceCredentialsUpdateMsgList() != null && !uplinkMsg.getDeviceCredentialsUpdateMsgList().isEmpty()) {
  647 + for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) {
  648 + onDeviceCredentialsUpdate(deviceCredentialsUpdateMsg);
  649 + }
  650 + }
710 if (uplinkMsg.getAlarmUpdateMsgList() != null && !uplinkMsg.getAlarmUpdateMsgList().isEmpty()) { 651 if (uplinkMsg.getAlarmUpdateMsgList() != null && !uplinkMsg.getAlarmUpdateMsgList().isEmpty()) {
711 for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) { 652 for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) {
712 onAlarmUpdate(alarmUpdateMsg); 653 onAlarmUpdate(alarmUpdateMsg);
@@ -714,7 +655,27 @@ public final class EdgeGrpcSession implements Closeable { @@ -714,7 +655,27 @@ public final class EdgeGrpcSession implements Closeable {
714 } 655 }
715 if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) { 656 if (uplinkMsg.getRuleChainMetadataRequestMsgList() != null && !uplinkMsg.getRuleChainMetadataRequestMsgList().isEmpty()) {
716 for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) { 657 for (RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg : uplinkMsg.getRuleChainMetadataRequestMsgList()) {
717 - ctx.getSyncEdgeService().syncRuleChainMetadata(edge, ruleChainMetadataRequestMsg, outputStream); 658 + ctx.getSyncEdgeService().processRuleChainMetadataRequestMsg(edge, ruleChainMetadataRequestMsg);
  659 + }
  660 + }
  661 + if (uplinkMsg.getAttributesRequestMsgList() != null && !uplinkMsg.getAttributesRequestMsgList().isEmpty()) {
  662 + for (AttributesRequestMsg attributesRequestMsg : uplinkMsg.getAttributesRequestMsgList()) {
  663 + ctx.getSyncEdgeService().processAttributesRequestMsg(edge, attributesRequestMsg);
  664 + }
  665 + }
  666 + if (uplinkMsg.getRelationRequestMsgList() != null && !uplinkMsg.getRelationRequestMsgList().isEmpty()) {
  667 + for (RelationRequestMsg relationRequestMsg : uplinkMsg.getRelationRequestMsgList()) {
  668 + ctx.getSyncEdgeService().processRelationRequestMsg(edge, relationRequestMsg);
  669 + }
  670 + }
  671 + if (uplinkMsg.getUserCredentialsRequestMsgList() != null && !uplinkMsg.getUserCredentialsRequestMsgList().isEmpty()) {
  672 + for (UserCredentialsRequestMsg userCredentialsRequestMsg : uplinkMsg.getUserCredentialsRequestMsgList()) {
  673 + ctx.getSyncEdgeService().processUserCredentialsRequestMsg(edge, userCredentialsRequestMsg);
  674 + }
  675 + }
  676 + if (uplinkMsg.getDeviceCredentialsRequestMsgList() != null && !uplinkMsg.getDeviceCredentialsRequestMsgList().isEmpty()) {
  677 + for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg : uplinkMsg.getDeviceCredentialsRequestMsgList()) {
  678 + ctx.getSyncEdgeService().processDeviceCredentialsRequestMsg(edge, deviceCredentialsRequestMsg);
718 } 679 }
719 } 680 }
720 } catch (Exception e) { 681 } catch (Exception e) {
@@ -817,17 +778,19 @@ public final class EdgeGrpcSession implements Closeable { @@ -817,17 +778,19 @@ public final class EdgeGrpcSession implements Closeable {
817 Device deviceById = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId); 778 Device deviceById = ctx.getDeviceService().findDeviceById(edge.getTenantId(), edgeDeviceId);
818 if (deviceById != null) { 779 if (deviceById != null) {
819 // this ID already used by other device - create new device and update ID on the edge 780 // this ID already used by other device - create new device and update ID on the edge
820 - Device savedDevice = createDevice(deviceUpdateMsg); 781 + device = createDevice(deviceUpdateMsg);
821 EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder() 782 EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()
822 - .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, savedDevice)) 783 + .setDeviceUpdateMsg(ctx.getDeviceUpdateMsgConstructor().constructDeviceUpdatedMsg(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE, device))
823 .build(); 784 .build();
824 outputStream.onNext(ResponseMsg.newBuilder() 785 outputStream.onNext(ResponseMsg.newBuilder()
825 .setEntityUpdateMsg(entityUpdateMsg) 786 .setEntityUpdateMsg(entityUpdateMsg)
826 .build()); 787 .build());
827 } else { 788 } else {
828 - createDevice(deviceUpdateMsg); 789 + device = createDevice(deviceUpdateMsg);
829 } 790 }
830 } 791 }
  792 + // TODO: voba - assign device only in case device is not assigned yet. Missing functionality to check this relation prior assignment
  793 + ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
831 break; 794 break;
832 case ENTITY_UPDATED_RPC_MESSAGE: 795 case ENTITY_UPDATED_RPC_MESSAGE:
833 updateDevice(deviceUpdateMsg); 796 updateDevice(deviceUpdateMsg);
@@ -850,21 +813,57 @@ public final class EdgeGrpcSession implements Closeable { @@ -850,21 +813,57 @@ public final class EdgeGrpcSession implements Closeable {
850 device.setType(deviceUpdateMsg.getType()); 813 device.setType(deviceUpdateMsg.getType());
851 device.setLabel(deviceUpdateMsg.getLabel()); 814 device.setLabel(deviceUpdateMsg.getLabel());
852 device = ctx.getDeviceService().saveDevice(device); 815 device = ctx.getDeviceService().saveDevice(device);
853 - updateDeviceCredentials(deviceUpdateMsg, device); 816 +
  817 + requestDeviceCredentialsFromEdge(device);
854 } 818 }
855 819
856 - private void updateDeviceCredentials(DeviceUpdateMsg deviceUpdateMsg, Device device) {  
857 - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]",  
858 - device.getName(), deviceUpdateMsg.getCredentialsId(), deviceUpdateMsg.getCredentialsValue()); 820 + private void onDeviceCredentialsUpdate(DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) {
  821 + log.debug("Executing onDeviceCredentialsUpdate, deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg);
  822 + DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB()));
  823 + ListenableFuture<Device> deviceFuture = ctx.getDeviceService().findDeviceByIdAsync(edge.getTenantId(), deviceId);
859 824
860 - DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId());  
861 - deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceUpdateMsg.getCredentialsType()));  
862 - deviceCredentials.setCredentialsId(deviceUpdateMsg.getCredentialsId());  
863 - deviceCredentials.setCredentialsValue(deviceUpdateMsg.getCredentialsValue());  
864 - ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials);  
865 - log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]",  
866 - device.getName(), deviceUpdateMsg.getCredentialsId(), deviceUpdateMsg.getCredentialsValue()); 825 + Futures.addCallback(deviceFuture, new FutureCallback<Device>() {
  826 + @Override
  827 + public void onSuccess(@Nullable Device device) {
  828 + if (device != null) {
  829 + log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]",
  830 + device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue());
  831 + try {
  832 + DeviceCredentials deviceCredentials = ctx.getDeviceCredentialsService().findDeviceCredentialsByDeviceId(edge.getTenantId(), device.getId());
  833 + deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType()));
  834 + deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId());
  835 + deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue());
  836 + ctx.getDeviceCredentialsService().updateDeviceCredentials(edge.getTenantId(), deviceCredentials);
  837 + } catch (Exception e) {
  838 + log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e);
  839 + }
  840 + }
  841 + }
867 842
  843 + @Override
  844 + public void onFailure(Throwable t) {
  845 + log.error("Can't update device credentials for deviceCredentialsUpdateMsg [{}]", deviceCredentialsUpdateMsg, t);
  846 + }
  847 + }, ctx.getDbCallbackExecutor());
  848 + }
  849 +
  850 + private void requestDeviceCredentialsFromEdge(Device device) {
  851 + log.debug("Executing requestDeviceCredentialsFromEdge device [{}]", device);
  852 +
  853 + DownlinkMsg downlinkMsg = constructDeviceCredentialsRequestMsg(device.getId());
  854 + outputStream.onNext(ResponseMsg.newBuilder()
  855 + .setDownlinkMsg(downlinkMsg)
  856 + .build());
  857 + }
  858 +
  859 + private DownlinkMsg constructDeviceCredentialsRequestMsg(DeviceId deviceId) {
  860 + DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder()
  861 + .setDeviceIdMSB(deviceId.getId().getMostSignificantBits())
  862 + .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits())
  863 + .build();
  864 + DownlinkMsg.Builder builder = DownlinkMsg.newBuilder()
  865 + .addAllDeviceCredentialsRequestMsg(Collections.singletonList(deviceCredentialsRequestMsg));
  866 + return builder.build();
868 } 867 }
869 868
870 private Device createDevice(DeviceUpdateMsg deviceUpdateMsg) { 869 private Device createDevice(DeviceUpdateMsg deviceUpdateMsg) {
@@ -880,17 +879,68 @@ public final class EdgeGrpcSession implements Closeable { @@ -880,17 +879,68 @@ public final class EdgeGrpcSession implements Closeable {
880 device.setType(deviceUpdateMsg.getType()); 879 device.setType(deviceUpdateMsg.getType());
881 device.setLabel(deviceUpdateMsg.getLabel()); 880 device.setLabel(deviceUpdateMsg.getLabel());
882 device = ctx.getDeviceService().saveDevice(device); 881 device = ctx.getDeviceService().saveDevice(device);
883 - device = ctx.getDeviceService().assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId()); 882 + createDeviceCredentials(device);
884 createRelationFromEdge(device.getId()); 883 createRelationFromEdge(device.getId());
885 - ctx.getRelationService().saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(edge.getId(), device.getId(), "Created"));  
886 ctx.getDeviceStateService().onDeviceAdded(device); 884 ctx.getDeviceStateService().onDeviceAdded(device);
887 - updateDeviceCredentials(deviceUpdateMsg, device); 885 + pushDeviceCreatedEventToRuleEngine(device);
  886 + requestDeviceCredentialsFromEdge(device);
888 } finally { 887 } finally {
889 deviceCreationLock.unlock(); 888 deviceCreationLock.unlock();
890 } 889 }
891 return device; 890 return device;
892 } 891 }
893 892
  893 + private void createDeviceCredentials(Device device) {
  894 + DeviceCredentials deviceCredentials = new DeviceCredentials();
  895 + deviceCredentials.setDeviceId(device.getId());
  896 + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
  897 + deviceCredentials.setCredentialsId(RandomStringUtils.randomAlphanumeric(20));
  898 + ctx.getDeviceCredentialsService().createDeviceCredentials(device.getTenantId(), deviceCredentials);
  899 + }
  900 +
  901 + private void pushDeviceCreatedEventToRuleEngine(Device device) {
  902 + try {
  903 + ObjectNode entityNode = mapper.valueToTree(device);
  904 + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, device.getId(), getActionTbMsgMetaData(device.getCustomerId()), mapper.writeValueAsString(entityNode));
  905 + sendToRuleEngine(edge.getTenantId(), tbMsg, new TbQueueCallback() {
  906 + @Override
  907 + public void onSuccess(TbQueueMsgMetadata metadata) {
  908 + // TODO: voba - handle success
  909 + }
  910 +
  911 + @Override
  912 + public void onFailure(Throwable t) {
  913 + // TODO: voba - handle failure
  914 + }
  915 + });
  916 + } catch (JsonProcessingException | IllegalArgumentException e) {
  917 + log.warn("[{}] Failed to push device action to rule engine: {}", device.getId(), DataConstants.ENTITY_CREATED, e);
  918 + }
  919 + }
  920 +
  921 + protected void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) {
  922 + TopicPartitionInfo tpi = ctx.getPartitionService().resolve(ServiceType.TB_RULE_ENGINE, tenantId, tbMsg.getOriginator());
  923 + TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder().setTbMsg(TbMsg.toByteString(tbMsg))
  924 + .setTenantIdMSB(tenantId.getId().getMostSignificantBits())
  925 + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()).build();
  926 + ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), callback);
  927 + }
  928 +
  929 + private TbMsgMetaData getActionTbMsgMetaData(CustomerId customerId) {
  930 + TbMsgMetaData metaData = getTbMsgMetaData(edge);
  931 + if (customerId != null && !customerId.isNullUid()) {
  932 + metaData.putValue("customerId", customerId.toString());
  933 + }
  934 + return metaData;
  935 + }
  936 +
  937 + private TbMsgMetaData getTbMsgMetaData(Edge edge) {
  938 + TbMsgMetaData metaData = new TbMsgMetaData();
  939 + metaData.putValue("edgeId", edge.getId().toString());
  940 + metaData.putValue("edgeName", edge.getName());
  941 + return metaData;
  942 + }
  943 +
894 private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) { 944 private EntityId getAlarmOriginator(String entityName, org.thingsboard.server.common.data.EntityType entityType) {
895 switch (entityType) { 945 switch (entityType) {
896 case DEVICE: 946 case DEVICE:
@@ -925,7 +975,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -925,7 +975,7 @@ public final class EdgeGrpcSession implements Closeable {
925 existentAlarm.setPropagate(alarmUpdateMsg.getPropagate()); 975 existentAlarm.setPropagate(alarmUpdateMsg.getPropagate());
926 } 976 }
927 existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); 977 existentAlarm.setEndTs(alarmUpdateMsg.getEndTs());
928 - existentAlarm.setDetails(objectMapper.readTree(alarmUpdateMsg.getDetails())); 978 + existentAlarm.setDetails(mapper.readTree(alarmUpdateMsg.getDetails()));
929 ctx.getAlarmService().createOrUpdateAlarm(existentAlarm); 979 ctx.getAlarmService().createOrUpdateAlarm(existentAlarm);
930 break; 980 break;
931 case ALARM_ACK_RPC_MESSAGE: 981 case ALARM_ACK_RPC_MESSAGE:
@@ -935,7 +985,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -935,7 +985,7 @@ public final class EdgeGrpcSession implements Closeable {
935 break; 985 break;
936 case ALARM_CLEAR_RPC_MESSAGE: 986 case ALARM_CLEAR_RPC_MESSAGE:
937 if (existentAlarm != null) { 987 if (existentAlarm != null) {
938 - ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), objectMapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs()); 988 + ctx.getAlarmService().clearAlarm(edge.getTenantId(), existentAlarm.getId(), mapper.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs());
939 } 989 }
940 break; 990 break;
941 case ENTITY_DELETED_RPC_MESSAGE: 991 case ENTITY_DELETED_RPC_MESSAGE:
@@ -16,11 +16,9 @@ @@ -16,11 +16,9 @@
16 package org.thingsboard.server.service.edge.rpc.constructor; 16 package org.thingsboard.server.service.edge.rpc.constructor;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 -import org.springframework.beans.factory.annotation.Autowired;  
20 import org.springframework.stereotype.Component; 19 import org.springframework.stereotype.Component;
21 import org.thingsboard.server.common.data.Dashboard; 20 import org.thingsboard.server.common.data.Dashboard;
22 import org.thingsboard.server.common.data.id.DashboardId; 21 import org.thingsboard.server.common.data.id.DashboardId;
23 -import org.thingsboard.server.dao.dashboard.DashboardService;  
24 import org.thingsboard.server.dao.util.mapping.JacksonUtil; 22 import org.thingsboard.server.dao.util.mapping.JacksonUtil;
25 import org.thingsboard.server.gen.edge.DashboardUpdateMsg; 23 import org.thingsboard.server.gen.edge.DashboardUpdateMsg;
26 import org.thingsboard.server.gen.edge.UpdateMsgType; 24 import org.thingsboard.server.gen.edge.UpdateMsgType;
@@ -29,11 +27,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -29,11 +27,7 @@ import org.thingsboard.server.gen.edge.UpdateMsgType;
29 @Slf4j 27 @Slf4j
30 public class DashboardUpdateMsgConstructor { 28 public class DashboardUpdateMsgConstructor {
31 29
32 - @Autowired  
33 - private DashboardService dashboardService;  
34 -  
35 public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) { 30 public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) {
36 - dashboard = dashboardService.findDashboardById(dashboard.getTenantId(), dashboard.getId());  
37 DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder() 31 DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder()
38 .setMsgType(msgType) 32 .setMsgType(msgType)
39 .setIdMSB(dashboard.getId().getId().getMostSignificantBits()) 33 .setIdMSB(dashboard.getId().getId().getMostSignificantBits())
@@ -16,12 +16,11 @@ @@ -16,12 +16,11 @@
16 package org.thingsboard.server.service.edge.rpc.constructor; 16 package org.thingsboard.server.service.edge.rpc.constructor;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 -import org.springframework.beans.factory.annotation.Autowired;  
20 import org.springframework.stereotype.Component; 19 import org.springframework.stereotype.Component;
21 import org.thingsboard.server.common.data.Device; 20 import org.thingsboard.server.common.data.Device;
22 import org.thingsboard.server.common.data.id.DeviceId; 21 import org.thingsboard.server.common.data.id.DeviceId;
23 import org.thingsboard.server.common.data.security.DeviceCredentials; 22 import org.thingsboard.server.common.data.security.DeviceCredentials;
24 -import org.thingsboard.server.dao.device.DeviceCredentialsService; 23 +import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg;
25 import org.thingsboard.server.gen.edge.DeviceUpdateMsg; 24 import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
26 import org.thingsboard.server.gen.edge.UpdateMsgType; 25 import org.thingsboard.server.gen.edge.UpdateMsgType;
27 26
@@ -29,9 +28,6 @@ import org.thingsboard.server.gen.edge.UpdateMsgType; @@ -29,9 +28,6 @@ import org.thingsboard.server.gen.edge.UpdateMsgType;
29 @Slf4j 28 @Slf4j
30 public class DeviceUpdateMsgConstructor { 29 public class DeviceUpdateMsgConstructor {
31 30
32 - @Autowired  
33 - private DeviceCredentialsService deviceCredentialsService;  
34 -  
35 public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) { 31 public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) {
36 DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder() 32 DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
37 .setMsgType(msgType) 33 .setMsgType(msgType)
@@ -42,20 +38,19 @@ public class DeviceUpdateMsgConstructor { @@ -42,20 +38,19 @@ public class DeviceUpdateMsgConstructor {
42 if (device.getLabel() != null) { 38 if (device.getLabel() != null) {
43 builder.setLabel(device.getLabel()); 39 builder.setLabel(device.getLabel());
44 } 40 }
45 - if (msgType.equals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE) ||  
46 - msgType.equals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE) ||  
47 - msgType.equals(UpdateMsgType.DEVICE_CONFLICT_RPC_MESSAGE)) {  
48 - DeviceCredentials deviceCredentials  
49 - = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());  
50 - if (deviceCredentials != null) {  
51 - if (deviceCredentials.getCredentialsType() != null) {  
52 - builder.setCredentialsType(deviceCredentials.getCredentialsType().name())  
53 - .setCredentialsId(deviceCredentials.getCredentialsId());  
54 - }  
55 - if (deviceCredentials.getCredentialsValue() != null) {  
56 - builder.setCredentialsValue(deviceCredentials.getCredentialsValue());  
57 - }  
58 - } 41 + return builder.build();
  42 + }
  43 +
  44 + public DeviceCredentialsUpdateMsg constructDeviceCredentialsUpdatedMsg(DeviceCredentials deviceCredentials) {
  45 + DeviceCredentialsUpdateMsg.Builder builder = DeviceCredentialsUpdateMsg.newBuilder()
  46 + .setDeviceIdMSB(deviceCredentials.getDeviceId().getId().getMostSignificantBits())
  47 + .setDeviceIdLSB(deviceCredentials.getDeviceId().getId().getLeastSignificantBits());
  48 + if (deviceCredentials.getCredentialsType() != null) {
  49 + builder.setCredentialsType(deviceCredentials.getCredentialsType().name())
  50 + .setCredentialsId(deviceCredentials.getCredentialsId());
  51 + }
  52 + if (deviceCredentials.getCredentialsValue() != null) {
  53 + builder.setCredentialsValue(deviceCredentials.getCredentialsValue());
59 } 54 }
60 return builder.build(); 55 return builder.build();
61 } 56 }
@@ -16,31 +16,26 @@ @@ -16,31 +16,26 @@
16 package org.thingsboard.server.service.edge.rpc.constructor; 16 package org.thingsboard.server.service.edge.rpc.constructor;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 -import org.springframework.beans.factory.annotation.Autowired;  
20 import org.springframework.stereotype.Component; 19 import org.springframework.stereotype.Component;
21 import org.thingsboard.server.common.data.User; 20 import org.thingsboard.server.common.data.User;
22 import org.thingsboard.server.common.data.id.UserId; 21 import org.thingsboard.server.common.data.id.UserId;
23 import org.thingsboard.server.common.data.security.UserCredentials; 22 import org.thingsboard.server.common.data.security.UserCredentials;
24 -import org.thingsboard.server.dao.user.UserService;  
25 import org.thingsboard.server.dao.util.mapping.JacksonUtil; 23 import org.thingsboard.server.dao.util.mapping.JacksonUtil;
26 import org.thingsboard.server.gen.edge.UpdateMsgType; 24 import org.thingsboard.server.gen.edge.UpdateMsgType;
  25 +import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg;
27 import org.thingsboard.server.gen.edge.UserUpdateMsg; 26 import org.thingsboard.server.gen.edge.UserUpdateMsg;
28 27
29 @Component 28 @Component
30 @Slf4j 29 @Slf4j
31 public class UserUpdateMsgConstructor { 30 public class UserUpdateMsgConstructor {
32 31
33 - @Autowired  
34 - private UserService userService;  
35 -  
36 public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user) { 32 public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user) {
37 UserUpdateMsg.Builder builder = UserUpdateMsg.newBuilder() 33 UserUpdateMsg.Builder builder = UserUpdateMsg.newBuilder()
38 .setMsgType(msgType) 34 .setMsgType(msgType)
39 .setIdMSB(user.getId().getId().getMostSignificantBits()) 35 .setIdMSB(user.getId().getId().getMostSignificantBits())
40 .setIdLSB(user.getId().getId().getLeastSignificantBits()) 36 .setIdLSB(user.getId().getId().getLeastSignificantBits())
41 .setEmail(user.getEmail()) 37 .setEmail(user.getEmail())
42 - .setAuthority(user.getAuthority().name())  
43 - .setEnabled(false); 38 + .setAuthority(user.getAuthority().name());
44 if (user.getFirstName() != null) { 39 if (user.getFirstName() != null) {
45 builder.setFirstName(user.getFirstName()); 40 builder.setFirstName(user.getFirstName());
46 } 41 }
@@ -53,13 +48,6 @@ public class UserUpdateMsgConstructor { @@ -53,13 +48,6 @@ public class UserUpdateMsgConstructor {
53 if (user.getAdditionalInfo() != null) { 48 if (user.getAdditionalInfo() != null) {
54 builder.setAdditionalInfo(JacksonUtil.toString(user.getAdditionalInfo())); 49 builder.setAdditionalInfo(JacksonUtil.toString(user.getAdditionalInfo()));
55 } 50 }
56 - if (msgType.equals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE) ||  
57 - msgType.equals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE)) {  
58 - UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());  
59 - if (userCredentials != null) {  
60 - builder.setEnabled(userCredentials.isEnabled()).setPassword(userCredentials.getPassword());  
61 - }  
62 - }  
63 return builder.build(); 51 return builder.build();
64 } 52 }
65 53
@@ -69,4 +57,13 @@ public class UserUpdateMsgConstructor { @@ -69,4 +57,13 @@ public class UserUpdateMsgConstructor {
69 .setIdMSB(userId.getId().getMostSignificantBits()) 57 .setIdMSB(userId.getId().getMostSignificantBits())
70 .setIdLSB(userId.getId().getLeastSignificantBits()).build(); 58 .setIdLSB(userId.getId().getLeastSignificantBits()).build();
71 } 59 }
  60 +
  61 + public UserCredentialsUpdateMsg constructUserCredentialsUpdatedMsg(UserCredentials userCredentials) {
  62 + UserCredentialsUpdateMsg.Builder builder = UserCredentialsUpdateMsg.newBuilder()
  63 + .setUserIdMSB(userCredentials.getUserId().getId().getMostSignificantBits())
  64 + .setUserIdLSB(userCredentials.getUserId().getId().getLeastSignificantBits())
  65 + .setEnabled(userCredentials.isEnabled())
  66 + .setPassword(userCredentials.getPassword());
  67 + return builder.build();
  68 + }
72 } 69 }
@@ -15,22 +15,36 @@ @@ -15,22 +15,36 @@
15 */ 15 */
16 package org.thingsboard.server.service.edge.rpc.init; 16 package org.thingsboard.server.service.edge.rpc.init;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import com.fasterxml.jackson.databind.ObjectMapper;
  20 +import com.fasterxml.jackson.databind.node.ObjectNode;
  21 +import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures; 22 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.ListenableFuture; 23 import com.google.common.util.concurrent.ListenableFuture;
20 -import com.google.common.util.concurrent.MoreExecutors;  
21 -import io.grpc.stub.StreamObserver;  
22 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
  25 +import org.checkerframework.checker.nullness.qual.Nullable;
23 import org.springframework.beans.factory.annotation.Autowired; 26 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
25 -import org.thingsboard.server.common.data.Dashboard;  
26 import org.thingsboard.server.common.data.DashboardInfo; 28 import org.thingsboard.server.common.data.DashboardInfo;
  29 +import org.thingsboard.server.common.data.DataConstants;
27 import org.thingsboard.server.common.data.Device; 30 import org.thingsboard.server.common.data.Device;
  31 +import org.thingsboard.server.common.data.EntityType;
28 import org.thingsboard.server.common.data.EntityView; 32 import org.thingsboard.server.common.data.EntityView;
29 import org.thingsboard.server.common.data.User; 33 import org.thingsboard.server.common.data.User;
30 import org.thingsboard.server.common.data.asset.Asset; 34 import org.thingsboard.server.common.data.asset.Asset;
  35 +import org.thingsboard.server.common.data.audit.ActionType;
31 import org.thingsboard.server.common.data.edge.Edge; 36 import org.thingsboard.server.common.data.edge.Edge;
  37 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  38 +import org.thingsboard.server.common.data.edge.EdgeEventType;
  39 +import org.thingsboard.server.common.data.id.DeviceId;
  40 +import org.thingsboard.server.common.data.id.EdgeId;
32 import org.thingsboard.server.common.data.id.EntityId; 41 import org.thingsboard.server.common.data.id.EntityId;
  42 +import org.thingsboard.server.common.data.id.EntityIdFactory;
33 import org.thingsboard.server.common.data.id.RuleChainId; 43 import org.thingsboard.server.common.data.id.RuleChainId;
  44 +import org.thingsboard.server.common.data.id.TenantId;
  45 +import org.thingsboard.server.common.data.id.UserId;
  46 +import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  47 +import org.thingsboard.server.common.data.kv.DataType;
34 import org.thingsboard.server.common.data.page.TextPageData; 48 import org.thingsboard.server.common.data.page.TextPageData;
35 import org.thingsboard.server.common.data.page.TextPageLink; 49 import org.thingsboard.server.common.data.page.TextPageLink;
36 import org.thingsboard.server.common.data.page.TimePageData; 50 import org.thingsboard.server.common.data.page.TimePageData;
@@ -40,45 +54,38 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; @@ -40,45 +54,38 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
40 import org.thingsboard.server.common.data.relation.EntitySearchDirection; 54 import org.thingsboard.server.common.data.relation.EntitySearchDirection;
41 import org.thingsboard.server.common.data.relation.RelationsSearchParameters; 55 import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
42 import org.thingsboard.server.common.data.rule.RuleChain; 56 import org.thingsboard.server.common.data.rule.RuleChain;
43 -import org.thingsboard.server.common.data.rule.RuleChainMetaData;  
44 import org.thingsboard.server.dao.asset.AssetService; 57 import org.thingsboard.server.dao.asset.AssetService;
  58 +import org.thingsboard.server.dao.attributes.AttributesService;
45 import org.thingsboard.server.dao.dashboard.DashboardService; 59 import org.thingsboard.server.dao.dashboard.DashboardService;
46 import org.thingsboard.server.dao.device.DeviceService; 60 import org.thingsboard.server.dao.device.DeviceService;
  61 +import org.thingsboard.server.dao.edge.EdgeEventService;
47 import org.thingsboard.server.dao.entityview.EntityViewService; 62 import org.thingsboard.server.dao.entityview.EntityViewService;
48 import org.thingsboard.server.dao.relation.RelationService; 63 import org.thingsboard.server.dao.relation.RelationService;
49 import org.thingsboard.server.dao.rule.RuleChainService; 64 import org.thingsboard.server.dao.rule.RuleChainService;
50 import org.thingsboard.server.dao.user.UserService; 65 import org.thingsboard.server.dao.user.UserService;
51 -import org.thingsboard.server.gen.edge.AssetUpdateMsg;  
52 -import org.thingsboard.server.gen.edge.DashboardUpdateMsg;  
53 -import org.thingsboard.server.gen.edge.DeviceUpdateMsg;  
54 -import org.thingsboard.server.gen.edge.EntityUpdateMsg;  
55 -import org.thingsboard.server.gen.edge.EntityViewUpdateMsg;  
56 -import org.thingsboard.server.gen.edge.RelationUpdateMsg;  
57 -import org.thingsboard.server.gen.edge.ResponseMsg; 66 +import org.thingsboard.server.gen.edge.AttributesRequestMsg;
  67 +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
  68 +import org.thingsboard.server.gen.edge.RelationRequestMsg;
58 import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; 69 import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg;
59 -import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg;  
60 -import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;  
61 -import org.thingsboard.server.gen.edge.UpdateMsgType;  
62 -import org.thingsboard.server.gen.edge.UserUpdateMsg;  
63 -import org.thingsboard.server.service.edge.EdgeContextComponent;  
64 -import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor;  
65 -import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor;  
66 -import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor;  
67 -import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgConstructor;  
68 -import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor;  
69 -import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor;  
70 -import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor; 70 +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg;
  71 +import org.thingsboard.server.service.executors.DbCallbackExecutorService;
71 72
72 import java.util.ArrayList; 73 import java.util.ArrayList;
73 -import java.util.HashSet;  
74 import java.util.List; 74 import java.util.List;
75 -import java.util.Set;  
76 import java.util.UUID; 75 import java.util.UUID;
77 76
78 @Service 77 @Service
79 @Slf4j 78 @Slf4j
80 public class DefaultSyncEdgeService implements SyncEdgeService { 79 public class DefaultSyncEdgeService implements SyncEdgeService {
81 80
  81 + private static final ObjectMapper mapper = new ObjectMapper();
  82 +
  83 + @Autowired
  84 + private EdgeEventService edgeEventService;
  85 +
  86 + @Autowired
  87 + private AttributesService attributesService;
  88 +
82 @Autowired 89 @Autowired
83 private RuleChainService ruleChainService; 90 private RuleChainService ruleChainService;
84 91
@@ -101,299 +108,323 @@ public class DefaultSyncEdgeService implements SyncEdgeService { @@ -101,299 +108,323 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
101 private UserService userService; 108 private UserService userService;
102 109
103 @Autowired 110 @Autowired
104 - private RuleChainUpdateMsgConstructor ruleChainUpdateMsgConstructor;  
105 -  
106 - @Autowired  
107 - private DeviceUpdateMsgConstructor deviceUpdateMsgConstructor;  
108 -  
109 - @Autowired  
110 - private AssetUpdateMsgConstructor assetUpdateMsgConstructor;  
111 -  
112 - @Autowired  
113 - private EntityViewUpdateMsgConstructor entityViewUpdateMsgConstructor;  
114 -  
115 - @Autowired  
116 - private DashboardUpdateMsgConstructor dashboardUpdateMsgConstructor;  
117 -  
118 - @Autowired  
119 - private UserUpdateMsgConstructor userUpdateMsgConstructor;  
120 -  
121 - @Autowired  
122 - private RelationUpdateMsgConstructor relationUpdateMsgConstructor; 111 + private DbCallbackExecutorService dbCallbackExecutorService;
123 112
124 @Override 113 @Override
125 - public void sync(EdgeContextComponent ctx, Edge edge, StreamObserver<ResponseMsg> outputStream) {  
126 - Set<EntityId> pushedEntityIds = new HashSet<>();  
127 - syncUsers(ctx, edge, pushedEntityIds, outputStream);  
128 - List<ListenableFuture<Void>> futures = new ArrayList<>();  
129 - futures.add(syncRuleChains(ctx, edge, pushedEntityIds, outputStream));  
130 - futures.add(syncDevices(ctx, edge, pushedEntityIds, outputStream));  
131 - futures.add(syncAssets(ctx, edge, pushedEntityIds, outputStream));  
132 - futures.add(syncEntityViews(ctx, edge, pushedEntityIds, outputStream));  
133 - futures.add(syncDashboards(ctx, edge, pushedEntityIds, outputStream));  
134 - ListenableFuture<List<Void>> joinFuture = Futures.allAsList(futures);  
135 - Futures.transform(joinFuture, result -> {  
136 - syncRelations(ctx, edge, pushedEntityIds, outputStream);  
137 - return null;  
138 - }, MoreExecutors.directExecutor()); 114 + public void sync(Edge edge) {
  115 + try {
  116 + syncUsers(edge);
  117 + syncRuleChains(edge);
  118 + syncDevices(edge);
  119 + syncAssets(edge);
  120 + syncEntityViews(edge);
  121 + syncDashboards(edge);
  122 + } catch (Exception e) {
  123 + log.error("Exception during sync process", e);
  124 + }
139 } 125 }
140 126
141 - private ListenableFuture<Void> syncRuleChains(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 127 + private void syncRuleChains(Edge edge) {
142 try { 128 try {
143 - ListenableFuture<TimePageData<RuleChain>> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));  
144 - return Futures.transform(future, pageData -> {  
145 - try { 129 + ListenableFuture<TimePageData<RuleChain>> future =
  130 + ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
  131 + Futures.addCallback(future, new FutureCallback<TimePageData<RuleChain>>() {
  132 + @Override
  133 + public void onSuccess(@Nullable TimePageData<RuleChain> pageData) {
146 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { 134 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
147 log.trace("[{}] [{}] rule chains(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); 135 log.trace("[{}] [{}] rule chains(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
148 for (RuleChain ruleChain : pageData.getData()) { 136 for (RuleChain ruleChain : pageData.getData()) {
149 - RuleChainUpdateMsg ruleChainUpdateMsg =  
150 - ruleChainUpdateMsgConstructor.constructRuleChainUpdatedMsg(  
151 - edge.getRootRuleChainId(),  
152 - UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE,  
153 - ruleChain);  
154 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
155 - .setRuleChainUpdateMsg(ruleChainUpdateMsg)  
156 - .build();  
157 - outputStream.onNext(ResponseMsg.newBuilder()  
158 - .setEntityUpdateMsg(entityUpdateMsg)  
159 - .build());  
160 - pushedEntityIds.add(ruleChain.getId()); 137 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN, ActionType.ADDED, ruleChain.getId(), null);
161 } 138 }
162 } 139 }
163 - } catch (Exception e) {  
164 - log.error("Exception during loading edge rule chain(s) on sync!", e);  
165 } 140 }
166 - return null;  
167 - }, ctx.getDbCallbackExecutor()); 141 +
  142 + @Override
  143 + public void onFailure(Throwable t) {
  144 + log.error("Exception during loading edge rule chain(s) on sync!", t);
  145 + }
  146 + }, dbCallbackExecutorService);
168 } catch (Exception e) { 147 } catch (Exception e) {
169 log.error("Exception during loading edge rule chain(s) on sync!", e); 148 log.error("Exception during loading edge rule chain(s) on sync!", e);
170 - return Futures.immediateFuture(null);  
171 } 149 }
172 } 150 }
173 151
174 - private ListenableFuture<Void> syncDevices(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 152 + private void syncDevices(Edge edge) {
175 try { 153 try {
176 - ListenableFuture<TimePageData<Device>> future = deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));  
177 - return Futures.transform(future, pageData -> {  
178 - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {  
179 - log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());  
180 - for (Device device : pageData.getData()) {  
181 - DeviceUpdateMsg deviceUpdateMsg =  
182 - deviceUpdateMsgConstructor.constructDeviceUpdatedMsg(  
183 - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,  
184 - device);  
185 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
186 - .setDeviceUpdateMsg(deviceUpdateMsg)  
187 - .build();  
188 - outputStream.onNext(ResponseMsg.newBuilder()  
189 - .setEntityUpdateMsg(entityUpdateMsg)  
190 - .build());  
191 - pushedEntityIds.add(device.getId()); 154 + ListenableFuture<TimePageData<Device>> future =
  155 + deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
  156 + Futures.addCallback(future, new FutureCallback<TimePageData<Device>>() {
  157 + @Override
  158 + public void onSuccess(@Nullable TimePageData<Device> pageData) {
  159 + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
  160 + log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
  161 + for (Device device : pageData.getData()) {
  162 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.ADDED, device.getId(), null);
  163 + }
192 } 164 }
193 } 165 }
194 - return null;  
195 - }, ctx.getDbCallbackExecutor()); 166 +
  167 + @Override
  168 + public void onFailure(Throwable t) {
  169 + log.error("Exception during loading edge device(s) on sync!", t);
  170 + }
  171 + }, dbCallbackExecutorService);
196 } catch (Exception e) { 172 } catch (Exception e) {
197 log.error("Exception during loading edge device(s) on sync!", e); 173 log.error("Exception during loading edge device(s) on sync!", e);
198 - return Futures.immediateFuture(null);  
199 } 174 }
200 } 175 }
201 176
202 - private ListenableFuture<Void> syncAssets(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 177 + private void syncAssets(Edge edge) {
203 try { 178 try {
204 ListenableFuture<TimePageData<Asset>> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); 179 ListenableFuture<TimePageData<Asset>> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
205 - return Futures.transform(future, pageData -> {  
206 - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {  
207 - log.trace("[{}] [{}] asset(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());  
208 - for (Asset asset : pageData.getData()) {  
209 - AssetUpdateMsg assetUpdateMsg =  
210 - assetUpdateMsgConstructor.constructAssetUpdatedMsg(  
211 - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,  
212 - asset);  
213 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
214 - .setAssetUpdateMsg(assetUpdateMsg)  
215 - .build();  
216 - outputStream.onNext(ResponseMsg.newBuilder()  
217 - .setEntityUpdateMsg(entityUpdateMsg)  
218 - .build());  
219 - pushedEntityIds.add(asset.getId()); 180 + Futures.addCallback(future, new FutureCallback<TimePageData<Asset>>() {
  181 + @Override
  182 + public void onSuccess(@Nullable TimePageData<Asset> pageData) {
  183 + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
  184 + log.trace("[{}] [{}] asset(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
  185 + for (Asset asset : pageData.getData()) {
  186 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ASSET, ActionType.ADDED, asset.getId(), null);
  187 + }
220 } 188 }
221 } 189 }
222 - return null;  
223 - }, ctx.getDbCallbackExecutor()); 190 +
  191 + @Override
  192 + public void onFailure(Throwable t) {
  193 + log.error("Exception during loading edge asset(s) on sync!", t);
  194 + }
  195 + }, dbCallbackExecutorService);
224 } catch (Exception e) { 196 } catch (Exception e) {
225 log.error("Exception during loading edge asset(s) on sync!", e); 197 log.error("Exception during loading edge asset(s) on sync!", e);
226 - return Futures.immediateFuture(null);  
227 } 198 }
228 } 199 }
229 200
230 - private ListenableFuture<Void> syncEntityViews(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 201 + private void syncEntityViews(Edge edge) {
231 try { 202 try {
232 ListenableFuture<TimePageData<EntityView>> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); 203 ListenableFuture<TimePageData<EntityView>> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
233 - return Futures.transform(future, pageData -> {  
234 - try { 204 + Futures.addCallback(future, new FutureCallback<TimePageData<EntityView>>() {
  205 + @Override
  206 + public void onSuccess(@Nullable TimePageData<EntityView> pageData) {
235 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { 207 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
236 log.trace("[{}] [{}] entity view(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); 208 log.trace("[{}] [{}] entity view(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
237 for (EntityView entityView : pageData.getData()) { 209 for (EntityView entityView : pageData.getData()) {
238 - EntityViewUpdateMsg entityViewUpdateMsg =  
239 - entityViewUpdateMsgConstructor.constructEntityViewUpdatedMsg(  
240 - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,  
241 - entityView);  
242 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
243 - .setEntityViewUpdateMsg(entityViewUpdateMsg)  
244 - .build();  
245 - outputStream.onNext(ResponseMsg.newBuilder()  
246 - .setEntityUpdateMsg(entityUpdateMsg)  
247 - .build());  
248 - pushedEntityIds.add(entityView.getId()); 210 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ENTITY_VIEW, ActionType.ADDED, entityView.getId(), null);
249 } 211 }
250 } 212 }
251 - } catch (Exception e) {  
252 - log.error("Exception during loading edge entity view(s) on sync!", e);  
253 } 213 }
254 - return null;  
255 - }, ctx.getDbCallbackExecutor()); 214 +
  215 + @Override
  216 + public void onFailure(Throwable t) {
  217 + log.error("Exception during loading edge entity view(s) on sync!", t);
  218 + }
  219 + }, dbCallbackExecutorService);
256 } catch (Exception e) { 220 } catch (Exception e) {
257 log.error("Exception during loading edge entity view(s) on sync!", e); 221 log.error("Exception during loading edge entity view(s) on sync!", e);
258 - return Futures.immediateFuture(null);  
259 } 222 }
260 } 223 }
261 224
262 - private ListenableFuture<Void> syncDashboards(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 225 + private void syncDashboards(Edge edge) {
263 try { 226 try {
264 ListenableFuture<TimePageData<DashboardInfo>> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); 227 ListenableFuture<TimePageData<DashboardInfo>> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE));
265 - return Futures.transform(future, pageData -> {  
266 - try { 228 + Futures.addCallback(future, new FutureCallback<TimePageData<DashboardInfo>>() {
  229 + @Override
  230 + public void onSuccess(@Nullable TimePageData<DashboardInfo> pageData) {
267 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { 231 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
268 log.trace("[{}] [{}] dashboard(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); 232 log.trace("[{}] [{}] dashboard(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
269 for (DashboardInfo dashboardInfo : pageData.getData()) { 233 for (DashboardInfo dashboardInfo : pageData.getData()) {
270 - Dashboard dashboard = dashboardService.findDashboardById(edge.getTenantId(), dashboardInfo.getId());  
271 - DashboardUpdateMsg dashboardUpdateMsg =  
272 - dashboardUpdateMsgConstructor.constructDashboardUpdatedMsg(  
273 - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,  
274 - dashboard);  
275 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
276 - .setDashboardUpdateMsg(dashboardUpdateMsg)  
277 - .build();  
278 - outputStream.onNext(ResponseMsg.newBuilder()  
279 - .setEntityUpdateMsg(entityUpdateMsg)  
280 - .build());  
281 - pushedEntityIds.add(dashboard.getId()); 234 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DASHBOARD, ActionType.ADDED, dashboardInfo.getId(), null);
282 } 235 }
283 } 236 }
284 - } catch (Exception e) {  
285 - log.error("Exception during loading edge dashboard(s) on sync!", e);  
286 } 237 }
287 - return null;  
288 - }, ctx.getDbCallbackExecutor()); 238 +
  239 + @Override
  240 + public void onFailure(Throwable t) {
  241 + log.error("Exception during loading edge dashboard(s) on sync!", t);
  242 + }
  243 + }, dbCallbackExecutorService);
289 } catch (Exception e) { 244 } catch (Exception e) {
290 log.error("Exception during loading edge dashboard(s) on sync!", e); 245 log.error("Exception during loading edge dashboard(s) on sync!", e);
291 - return Futures.immediateFuture(null);  
292 } 246 }
293 } 247 }
294 248
295 - private void syncUsers(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 249 + private void syncUsers(Edge edge) {
296 try { 250 try {
297 TextPageData<User> pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE)); 251 TextPageData<User> pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE));
298 - pushUsersToEdge(pageData, edge, pushedEntityIds, outputStream); 252 + pushUsersToEdge(pageData, edge);
299 if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { 253 if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) {
300 pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE)); 254 pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE));
301 - pushUsersToEdge(pageData, edge, pushedEntityIds, outputStream); 255 + pushUsersToEdge(pageData, edge);
302 } 256 }
303 } catch (Exception e) { 257 } catch (Exception e) {
304 log.error("Exception during loading edge user(s) on sync!", e); 258 log.error("Exception during loading edge user(s) on sync!", e);
305 } 259 }
306 } 260 }
307 261
308 - private void pushUsersToEdge(TextPageData<User> pageData, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) { 262 + private void pushUsersToEdge(TextPageData<User> pageData, Edge edge) {
309 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { 263 if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
310 log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); 264 log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
311 for (User user : pageData.getData()) { 265 for (User user : pageData.getData()) {
312 - UserUpdateMsg userUpdateMsg =  
313 - userUpdateMsgConstructor.constructUserUpdatedMsg(  
314 - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,  
315 - user);  
316 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
317 - .setUserUpdateMsg(userUpdateMsg)  
318 - .build();  
319 - outputStream.onNext(ResponseMsg.newBuilder()  
320 - .setEntityUpdateMsg(entityUpdateMsg)  
321 - .build());  
322 - pushedEntityIds.add(user.getId()); 266 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.ADDED, user.getId(), null);
323 } 267 }
324 } 268 }
325 } 269 }
326 270
327 - private ListenableFuture<Void> syncRelations(EdgeContextComponent ctx, Edge edge, Set<EntityId> pushedEntityIds, StreamObserver<ResponseMsg> outputStream) {  
328 - if (!pushedEntityIds.isEmpty()) {  
329 - List<ListenableFuture<List<EntityRelation>>> futures = new ArrayList<>();  
330 - for (EntityId entityId : pushedEntityIds) {  
331 - futures.add(syncRelations(edge, entityId, EntitySearchDirection.FROM));  
332 - futures.add(syncRelations(edge, entityId, EntitySearchDirection.TO));  
333 - }  
334 - ListenableFuture<List<List<EntityRelation>>> relationsListFuture = Futures.allAsList(futures);  
335 - return Futures.transform(relationsListFuture, relationsList -> {  
336 - try {  
337 - Set<EntityRelation> uniqueEntityRelations = new HashSet<>();  
338 - if (!relationsList.isEmpty()) {  
339 - for (List<EntityRelation> entityRelations : relationsList) {  
340 - if (!entityRelations.isEmpty()) {  
341 - uniqueEntityRelations.addAll(entityRelations); 271 + @Override
  272 + public void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) {
  273 + if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) {
  274 + RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB()));
  275 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null);
  276 + }
  277 + }
  278 +
  279 + @Override
  280 + public void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg) {
  281 + EntityId entityId = EntityIdFactory.getByTypeAndUuid(
  282 + EntityType.valueOf(attributesRequestMsg.getEntityType()),
  283 + new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB()));
  284 + final EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(entityId.getEntityType());
  285 + if (edgeEventType != null) {
  286 + ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE);
  287 + Futures.addCallback(ssAttrFuture, new FutureCallback<List<AttributeKvEntry>>() {
  288 + @Override
  289 + public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) {
  290 + if (ssAttributes != null && !ssAttributes.isEmpty()) {
  291 + try {
  292 + ObjectNode entityNode = mapper.createObjectNode();
  293 + for (AttributeKvEntry attr : ssAttributes) {
  294 + if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) {
  295 + entityNode.put(attr.getKey(), attr.getBooleanValue().get());
  296 + } else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) {
  297 + entityNode.put(attr.getKey(), attr.getDoubleValue().get());
  298 + } else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) {
  299 + entityNode.put(attr.getKey(), attr.getLongValue().get());
  300 + } else {
  301 + entityNode.put(attr.getKey(), attr.getValueAsString());
  302 + }
342 } 303 }
  304 + log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityNode);
  305 + saveEdgeEvent(edge.getTenantId(),
  306 + edge.getId(),
  307 + edgeEventType,
  308 + ActionType.ATTRIBUTES_UPDATED,
  309 + entityId,
  310 + entityNode);
  311 + } catch (Exception e) {
  312 + log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e);
343 } 313 }
344 } 314 }
345 - if (!uniqueEntityRelations.isEmpty()) {  
346 - log.trace("[{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), uniqueEntityRelations.size());  
347 - for (EntityRelation relation : uniqueEntityRelations) {  
348 - try {  
349 - RelationUpdateMsg relationUpdateMsg =  
350 - relationUpdateMsgConstructor.constructRelationUpdatedMsg(  
351 - UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,  
352 - relation);  
353 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
354 - .setRelationUpdateMsg(relationUpdateMsg)  
355 - .build();  
356 - outputStream.onNext(ResponseMsg.newBuilder()  
357 - .setEntityUpdateMsg(entityUpdateMsg)  
358 - .build());  
359 - } catch (Exception e) {  
360 - log.error("Exception during loading relation [{}] to edge on sync!", relation, e); 315 + }
  316 +
  317 + @Override
  318 + public void onFailure(Throwable t) {
  319 +
  320 + }
  321 + }, dbCallbackExecutorService);
  322 +
  323 + // TODO: voba - push shared attributes to edge?
  324 + ListenableFuture<List<AttributeKvEntry>> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE);
  325 + ListenableFuture<List<AttributeKvEntry>> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE);
  326 + }
  327 + }
  328 +
  329 + private EdgeEventType getEdgeQueueTypeByEntityType(EntityType entityType) {
  330 + switch (entityType) {
  331 + case DEVICE:
  332 + return EdgeEventType.DEVICE;
  333 + case ASSET:
  334 + return EdgeEventType.ASSET;
  335 + case ENTITY_VIEW:
  336 + return EdgeEventType.ENTITY_VIEW;
  337 + default:
  338 + return null;
  339 + }
  340 + }
  341 +
  342 + @Override
  343 + public void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg) {
  344 + EntityId entityId = EntityIdFactory.getByTypeAndUuid(
  345 + EntityType.valueOf(relationRequestMsg.getEntityType()),
  346 + new UUID(relationRequestMsg.getEntityIdMSB(), relationRequestMsg.getEntityIdLSB()));
  347 +
  348 + List<ListenableFuture<List<EntityRelation>>> futures = new ArrayList<>();
  349 + futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.FROM));
  350 + futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.TO));
  351 + ListenableFuture<List<List<EntityRelation>>> relationsListFuture = Futures.allAsList(futures);
  352 + Futures.addCallback(relationsListFuture, new FutureCallback<List<List<EntityRelation>>>() {
  353 + @Override
  354 + public void onSuccess(@Nullable List<List<EntityRelation>> relationsList) {
  355 + try {
  356 + if (!relationsList.isEmpty()) {
  357 + for (List<EntityRelation> entityRelations : relationsList) {
  358 + log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size());
  359 + for (EntityRelation relation : entityRelations) {
  360 + try {
  361 + if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
  362 + !relation.getTo().getEntityType().equals(EntityType.EDGE)) {
  363 + saveEdgeEvent(edge.getTenantId(),
  364 + edge.getId(),
  365 + EdgeEventType.RELATION,
  366 + ActionType.ADDED,
  367 + null,
  368 + mapper.valueToTree(relation));
  369 + }
  370 + } catch (Exception e) {
  371 + log.error("Exception during loading relation [{}] to edge on sync!", relation, e);
  372 + }
361 } 373 }
362 } 374 }
363 } 375 }
364 } catch (Exception e) { 376 } catch (Exception e) {
365 log.error("Exception during loading relation(s) to edge on sync!", e); 377 log.error("Exception during loading relation(s) to edge on sync!", e);
366 } 378 }
367 - return null;  
368 - }, ctx.getDbCallbackExecutor());  
369 - } else {  
370 - return Futures.immediateFuture(null);  
371 - } 379 + }
  380 +
  381 + @Override
  382 + public void onFailure(Throwable t) {
  383 + log.error("Exception during loading relation(s) to edge on sync!", t);
  384 + }
  385 + }, dbCallbackExecutorService);
372 } 386 }
373 387
374 - private ListenableFuture<List<EntityRelation>> syncRelations(Edge edge, EntityId entityId, EntitySearchDirection direction) { 388 + private ListenableFuture<List<EntityRelation>> findRelationByQuery(Edge edge, EntityId entityId, EntitySearchDirection direction) {
375 EntityRelationsQuery query = new EntityRelationsQuery(); 389 EntityRelationsQuery query = new EntityRelationsQuery();
376 query.setParameters(new RelationsSearchParameters(entityId, direction, -1, false)); 390 query.setParameters(new RelationsSearchParameters(entityId, direction, -1, false));
377 return relationService.findByQuery(edge.getTenantId(), query); 391 return relationService.findByQuery(edge.getTenantId(), query);
378 } 392 }
379 393
380 @Override 394 @Override
381 - public void syncRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver<ResponseMsg> outputStream) {  
382 - if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) {  
383 - RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB()));  
384 - RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(edge.getTenantId(), ruleChainId);  
385 - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =  
386 - ruleChainUpdateMsgConstructor.constructRuleChainMetadataUpdatedMsg(  
387 - UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE,  
388 - ruleChainMetaData);  
389 - if (ruleChainMetadataUpdateMsg != null) {  
390 - EntityUpdateMsg entityUpdateMsg = EntityUpdateMsg.newBuilder()  
391 - .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg)  
392 - .build();  
393 - outputStream.onNext(ResponseMsg.newBuilder()  
394 - .setEntityUpdateMsg(entityUpdateMsg)  
395 - .build());  
396 - } 395 + public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) {
  396 + if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) {
  397 + DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB()));
  398 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null);
  399 + }
  400 + }
  401 +
  402 + @Override
  403 + public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) {
  404 + if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) {
  405 + UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB()));
  406 + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null);
  407 + }
  408 + }
  409 +
  410 + private void saveEdgeEvent(TenantId tenantId,
  411 + EdgeId edgeId,
  412 + EdgeEventType edgeEventType,
  413 + ActionType edgeEventAction,
  414 + EntityId entityId,
  415 + JsonNode entityBody) {
  416 + log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], edgeEventType [{}], edgeEventAction[{}], entityId [{}], entityBody [{}]",
  417 + tenantId, edgeId, edgeEventType, edgeEventAction, entityId, entityBody);
  418 +
  419 + EdgeEvent edgeEvent = new EdgeEvent();
  420 + edgeEvent.setTenantId(tenantId);
  421 + edgeEvent.setEdgeId(edgeId);
  422 + edgeEvent.setEdgeEventType(edgeEventType);
  423 + edgeEvent.setEdgeEventAction(edgeEventAction.name());
  424 + if (entityId != null) {
  425 + edgeEvent.setEntityId(entityId.getId());
397 } 426 }
  427 + edgeEvent.setEntityBody(entityBody);
  428 + edgeEventService.saveAsync(edgeEvent);
398 } 429 }
399 } 430 }
@@ -15,15 +15,24 @@ @@ -15,15 +15,24 @@
15 */ 15 */
16 package org.thingsboard.server.service.edge.rpc.init; 16 package org.thingsboard.server.service.edge.rpc.init;
17 17
18 -import io.grpc.stub.StreamObserver;  
19 import org.thingsboard.server.common.data.edge.Edge; 18 import org.thingsboard.server.common.data.edge.Edge;
20 -import org.thingsboard.server.gen.edge.ResponseMsg; 19 +import org.thingsboard.server.gen.edge.AttributesRequestMsg;
  20 +import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
  21 +import org.thingsboard.server.gen.edge.RelationRequestMsg;
21 import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; 22 import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg;
22 -import org.thingsboard.server.service.edge.EdgeContextComponent; 23 +import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg;
23 24
24 public interface SyncEdgeService { 25 public interface SyncEdgeService {
25 26
26 - void sync(EdgeContextComponent ctx, Edge edge, StreamObserver<ResponseMsg> outputStream); 27 + void sync(Edge edge);
27 28
28 - void syncRuleChainMetadata(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg, StreamObserver<ResponseMsg> outputStream); 29 + void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg);
  30 +
  31 + void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg);
  32 +
  33 + void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg);
  34 +
  35 + void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg);
  36 +
  37 + void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg);
29 } 38 }
@@ -33,9 +33,9 @@ public class TbCoreConsumerStats { @@ -33,9 +33,9 @@ public class TbCoreConsumerStats {
33 private final AtomicInteger claimDeviceCounter = new AtomicInteger(0); 33 private final AtomicInteger claimDeviceCounter = new AtomicInteger(0);
34 34
35 private final AtomicInteger deviceStateCounter = new AtomicInteger(0); 35 private final AtomicInteger deviceStateCounter = new AtomicInteger(0);
36 - private final AtomicInteger edgeNotificationCounter = new AtomicInteger(0);  
37 private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0); 36 private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0);
38 private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0); 37 private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0);
  38 + private final AtomicInteger edgeNotificationMsgCounter = new AtomicInteger(0);
39 39
40 public void log(TransportProtos.TransportToDeviceActorMsg msg) { 40 public void log(TransportProtos.TransportToDeviceActorMsg msg) {
41 totalCounter.incrementAndGet(); 41 totalCounter.incrementAndGet();
@@ -69,7 +69,7 @@ public class TbCoreConsumerStats { @@ -69,7 +69,7 @@ public class TbCoreConsumerStats {
69 69
70 public void log(TransportProtos.EdgeNotificationMsgProto msg) { 70 public void log(TransportProtos.EdgeNotificationMsgProto msg) {
71 totalCounter.incrementAndGet(); 71 totalCounter.incrementAndGet();
72 - edgeNotificationCounter.incrementAndGet(); 72 + edgeNotificationMsgCounter.incrementAndGet();
73 } 73 }
74 74
75 public void log(TransportProtos.SubscriptionMgrMsgProto msg) { 75 public void log(TransportProtos.SubscriptionMgrMsgProto msg) {
@@ -86,12 +86,13 @@ public class TbCoreConsumerStats { @@ -86,12 +86,13 @@ public class TbCoreConsumerStats {
86 int total = totalCounter.getAndSet(0); 86 int total = totalCounter.getAndSet(0);
87 if (total > 0) { 87 if (total > 0) {
88 log.info("Total [{}] sessionEvents [{}] getAttr [{}] subToAttr [{}] subToRpc [{}] toDevRpc [{}] subInfo [{}] claimDevice [{}]" + 88 log.info("Total [{}] sessionEvents [{}] getAttr [{}] subToAttr [{}] subToRpc [{}] toDevRpc [{}] subInfo [{}] claimDevice [{}]" +
89 - " deviceState [{}] subMgr [{}] coreNfs [{}]", 89 + " deviceState [{}] subMgr [{}] coreNfs [{}] edgeNfs [{}]",
90 total, sessionEventCounter.getAndSet(0), 90 total, sessionEventCounter.getAndSet(0),
91 getAttributesCounter.getAndSet(0), subscribeToAttributesCounter.getAndSet(0), 91 getAttributesCounter.getAndSet(0), subscribeToAttributesCounter.getAndSet(0),
92 subscribeToRPCCounter.getAndSet(0), toDeviceRPCCallResponseCounter.getAndSet(0), 92 subscribeToRPCCounter.getAndSet(0), toDeviceRPCCallResponseCounter.getAndSet(0),
93 subscriptionInfoCounter.getAndSet(0), claimDeviceCounter.getAndSet(0) 93 subscriptionInfoCounter.getAndSet(0), claimDeviceCounter.getAndSet(0)
94 - , deviceStateCounter.getAndSet(0), subscriptionMsgCounter.getAndSet(0), toCoreNotificationsCounter.getAndSet(0)); 94 + , deviceStateCounter.getAndSet(0), subscriptionMsgCounter.getAndSet(0), toCoreNotificationsCounter.getAndSet(0),
  95 + edgeNotificationMsgCounter.getAndSet(0));
95 } 96 }
96 } 97 }
97 98
@@ -26,8 +26,6 @@ import org.thingsboard.server.common.data.page.TimePageLink; @@ -26,8 +26,6 @@ import org.thingsboard.server.common.data.page.TimePageLink;
26 26
27 public interface EdgeEventService { 27 public interface EdgeEventService {
28 28
29 - EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType);  
30 -  
31 ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent); 29 ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent);
32 30
33 TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); 31 TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
  18 +import org.thingsboard.server.common.data.edge.EdgeEventType;
18 import org.thingsboard.server.common.data.id.EdgeId; 19 import org.thingsboard.server.common.data.id.EdgeId;
19 20
20 import java.util.Set; 21 import java.util.Set;
@@ -24,50 +25,22 @@ public final class EdgeUtils { @@ -24,50 +25,22 @@ public final class EdgeUtils {
24 private EdgeUtils() { 25 private EdgeUtils() {
25 } 26 }
26 27
27 - public static boolean isAssignedToEdge(Set<ShortEdgeInfo> assignedEdges, EdgeId edgeId) {  
28 - return assignedEdges != null && assignedEdges.contains(new ShortEdgeInfo(edgeId, null, null));  
29 - }  
30 -  
31 - public static ShortEdgeInfo getAssignedEdgeInfo(Set<ShortEdgeInfo> assignedEdges, EdgeId edgeId) {  
32 - if (assignedEdges != null) {  
33 - for (ShortEdgeInfo edgeInfo : assignedEdges) {  
34 - if (edgeInfo.getEdgeId().equals(edgeId)) {  
35 - return edgeInfo;  
36 - }  
37 - }  
38 - }  
39 - return null;  
40 - }  
41 -  
42 - public static boolean addAssignedEdge(Set<ShortEdgeInfo> assignedEdges, ShortEdgeInfo edgeInfo) {  
43 - if (assignedEdges != null && assignedEdges.contains(edgeInfo)) {  
44 - return false;  
45 - } else {  
46 - if (assignedEdges != null) {  
47 - assignedEdges.add(edgeInfo);  
48 - return true;  
49 - } else {  
50 - return false;  
51 - }  
52 - }  
53 - }  
54 -  
55 - public static boolean updateAssignedEdge(Set<ShortEdgeInfo> assignedEdges, ShortEdgeInfo edgeInfo) {  
56 - if (assignedEdges != null && assignedEdges.contains(edgeInfo)) {  
57 - assignedEdges.remove(edgeInfo);  
58 - assignedEdges.add(edgeInfo);  
59 - return true;  
60 - } else {  
61 - return false;  
62 - }  
63 - }  
64 -  
65 - public static boolean removeAssignedEdge(Set<ShortEdgeInfo> assignedEdges, ShortEdgeInfo edgeInfo) {  
66 - if (assignedEdges != null && assignedEdges.contains(edgeInfo)) {  
67 - assignedEdges.remove(edgeInfo);  
68 - return true;  
69 - } else {  
70 - return false; 28 + public static EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType) {
  29 + switch (entityType) {
  30 + case DEVICE:
  31 + return EdgeEventType.DEVICE;
  32 + case ASSET:
  33 + return EdgeEventType.ASSET;
  34 + case ENTITY_VIEW:
  35 + return EdgeEventType.ENTITY_VIEW;
  36 + case DASHBOARD:
  37 + return EdgeEventType.DASHBOARD;
  38 + case USER:
  39 + return EdgeEventType.USER;
  40 + case ALARM:
  41 + return EdgeEventType.ALARM;
  42 + default:
  43 + return null;
71 } 44 }
72 } 45 }
73 } 46 }
@@ -43,7 +43,8 @@ public enum ActionType { @@ -43,7 +43,8 @@ public enum ActionType {
43 LOGOUT(false), 43 LOGOUT(false),
44 LOCKOUT(false), 44 LOCKOUT(false),
45 ASSIGNED_TO_EDGE(false), // log edge name 45 ASSIGNED_TO_EDGE(false), // log edge name
46 - UNASSIGNED_FROM_EDGE(false); // log edge name 46 + UNASSIGNED_FROM_EDGE(false), // log edge name
  47 + CREDENTIALS_REQUEST(false); // request credentials from edge
47 48
48 private final boolean isRead; 49 private final boolean isRead;
49 50
@@ -20,7 +20,6 @@ import lombok.Data; @@ -20,7 +20,6 @@ import lombok.Data;
20 import org.thingsboard.server.common.data.BaseData; 20 import org.thingsboard.server.common.data.BaseData;
21 import org.thingsboard.server.common.data.id.EdgeEventId; 21 import org.thingsboard.server.common.data.id.EdgeEventId;
22 import org.thingsboard.server.common.data.id.EdgeId; 22 import org.thingsboard.server.common.data.id.EdgeId;
23 -import org.thingsboard.server.common.data.id.EntityId;  
24 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
25 24
26 import java.util.UUID; 25 import java.util.UUID;
@@ -16,5 +16,15 @@ @@ -16,5 +16,15 @@
16 package org.thingsboard.server.common.data.edge; 16 package org.thingsboard.server.common.data.edge;
17 17
18 public enum EdgeEventType { 18 public enum EdgeEventType {
19 - DASHBOARD, ASSET, DEVICE, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA, EDGE, USER, CUSTOMER, RELATION 19 + DASHBOARD,
  20 + ASSET,
  21 + DEVICE,
  22 + ENTITY_VIEW,
  23 + ALARM,
  24 + RULE_CHAIN,
  25 + RULE_CHAIN_METADATA,
  26 + EDGE,
  27 + USER,
  28 + CUSTOMER,
  29 + RELATION
20 } 30 }
@@ -48,15 +48,17 @@ message ResponseMsg { @@ -48,15 +48,17 @@ message ResponseMsg {
48 48
49 message EntityUpdateMsg { 49 message EntityUpdateMsg {
50 DeviceUpdateMsg deviceUpdateMsg = 1; 50 DeviceUpdateMsg deviceUpdateMsg = 1;
51 - RuleChainUpdateMsg ruleChainUpdateMsg = 2;  
52 - RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 3;  
53 - DashboardUpdateMsg dashboardUpdateMsg = 4;  
54 - AssetUpdateMsg assetUpdateMsg = 5;  
55 - EntityViewUpdateMsg entityViewUpdateMsg = 6;  
56 - AlarmUpdateMsg alarmUpdateMsg = 7;  
57 - UserUpdateMsg userUpdateMsg = 8;  
58 - CustomerUpdateMsg customerUpdateMsg = 9;  
59 - RelationUpdateMsg relationUpdateMsg = 10; 51 + DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 2;
  52 + RuleChainUpdateMsg ruleChainUpdateMsg = 3;
  53 + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 4;
  54 + DashboardUpdateMsg dashboardUpdateMsg = 5;
  55 + AssetUpdateMsg assetUpdateMsg = 6;
  56 + EntityViewUpdateMsg entityViewUpdateMsg = 7;
  57 + AlarmUpdateMsg alarmUpdateMsg = 8;
  58 + UserUpdateMsg userUpdateMsg = 9;
  59 + UserCredentialsUpdateMsg userCredentialsUpdateMsg = 10;
  60 + CustomerUpdateMsg customerUpdateMsg = 11;
  61 + RelationUpdateMsg relationUpdateMsg = 12;
60 } 62 }
61 63
62 enum RequestMsgType { 64 enum RequestMsgType {
@@ -169,9 +171,14 @@ message DeviceUpdateMsg { @@ -169,9 +171,14 @@ message DeviceUpdateMsg {
169 string name = 4; 171 string name = 4;
170 string type = 5; 172 string type = 5;
171 string label = 6; 173 string label = 6;
172 - string credentialsType = 7;  
173 - string credentialsId = 8;  
174 - string credentialsValue = 9; 174 +}
  175 +
  176 +message DeviceCredentialsUpdateMsg {
  177 + int64 deviceIdMSB = 1;
  178 + int64 deviceIdLSB = 2;
  179 + string credentialsType = 3;
  180 + string credentialsId = 4;
  181 + string credentialsValue = 5;
175 } 182 }
176 183
177 message AssetUpdateMsg { 184 message AssetUpdateMsg {
@@ -248,8 +255,13 @@ message UserUpdateMsg { @@ -248,8 +255,13 @@ message UserUpdateMsg {
248 string firstName = 6; 255 string firstName = 6;
249 string lastName = 7; 256 string lastName = 7;
250 string additionalInfo = 8; 257 string additionalInfo = 8;
251 - bool enabled = 9;  
252 - string password = 10; 258 +}
  259 +
  260 +message UserCredentialsUpdateMsg {
  261 + int64 userIdMSB = 1;
  262 + int64 userIdLSB = 2;
  263 + bool enabled = 3;
  264 + string password = 4;
253 } 265 }
254 266
255 message RuleChainMetadataRequestMsg { 267 message RuleChainMetadataRequestMsg {
@@ -257,6 +269,28 @@ message RuleChainMetadataRequestMsg { @@ -257,6 +269,28 @@ message RuleChainMetadataRequestMsg {
257 int64 ruleChainIdLSB = 2; 269 int64 ruleChainIdLSB = 2;
258 } 270 }
259 271
  272 +message AttributesRequestMsg {
  273 + int64 entityIdMSB = 1;
  274 + int64 entityIdLSB = 2;
  275 + string entityType = 3;
  276 +}
  277 +
  278 +message RelationRequestMsg {
  279 + int64 entityIdMSB = 1;
  280 + int64 entityIdLSB = 2;
  281 + string entityType = 3;
  282 +}
  283 +
  284 +message UserCredentialsRequestMsg {
  285 + int64 userIdMSB = 1;
  286 + int64 userIdLSB = 2;
  287 +}
  288 +
  289 +message DeviceCredentialsRequestMsg {
  290 + int64 deviceIdMSB = 1;
  291 + int64 deviceIdLSB = 2;
  292 +}
  293 +
260 enum EdgeEntityType { 294 enum EdgeEntityType {
261 DEVICE = 0; 295 DEVICE = 0;
262 ASSET = 1; 296 ASSET = 1;
@@ -270,8 +304,13 @@ message UplinkMsg { @@ -270,8 +304,13 @@ message UplinkMsg {
270 int32 uplinkMsgId = 1; 304 int32 uplinkMsgId = 1;
271 repeated EntityDataProto entityData = 2; 305 repeated EntityDataProto entityData = 2;
272 repeated DeviceUpdateMsg deviceUpdateMsg = 3; 306 repeated DeviceUpdateMsg deviceUpdateMsg = 3;
273 - repeated AlarmUpdateMsg alarmUpdateMsg = 4;  
274 - repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 5; 307 + repeated DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 4;
  308 + repeated AlarmUpdateMsg alarmUpdateMsg = 5;
  309 + repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 6;
  310 + repeated AttributesRequestMsg attributesRequestMsg = 7;
  311 + repeated RelationRequestMsg relationRequestMsg = 8;
  312 + repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 9;
  313 + repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 10;
275 } 314 }
276 315
277 message UplinkResponseMsg { 316 message UplinkResponseMsg {
@@ -282,5 +321,6 @@ message UplinkResponseMsg { @@ -282,5 +321,6 @@ message UplinkResponseMsg {
282 message DownlinkMsg { 321 message DownlinkMsg {
283 int32 downlinkMsgId = 1; 322 int32 downlinkMsgId = 1;
284 repeated EntityDataProto entityData = 2; 323 repeated EntityDataProto entityData = 2;
  324 + repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 3;
285 } 325 }
286 326
@@ -232,7 +232,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb @@ -232,7 +232,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
232 if (edge == null) { 232 if (edge == null) {
233 throw new DataValidationException("Can't assign dashboard to non-existent edge!"); 233 throw new DataValidationException("Can't assign dashboard to non-existent edge!");
234 } 234 }
235 - if (!edge.getTenantId().getId().equals(dashboard.getTenantId().getId())) { 235 + if (!edge.getTenantId().equals(dashboard.getTenantId())) {
236 throw new DataValidationException("Can't assign dashboard to edge from different tenant!"); 236 throw new DataValidationException("Can't assign dashboard to edge from different tenant!");
237 } 237 }
238 try { 238 try {
@@ -20,9 +20,7 @@ import lombok.extern.slf4j.Slf4j; @@ -20,9 +20,7 @@ import lombok.extern.slf4j.Slf4j;
20 import org.apache.commons.lang3.StringUtils; 20 import org.apache.commons.lang3.StringUtils;
21 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
23 -import org.thingsboard.server.common.data.EntityType;  
24 import org.thingsboard.server.common.data.edge.EdgeEvent; 23 import org.thingsboard.server.common.data.edge.EdgeEvent;
25 -import org.thingsboard.server.common.data.edge.EdgeEventType;  
26 import org.thingsboard.server.common.data.id.EdgeId; 24 import org.thingsboard.server.common.data.id.EdgeId;
27 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.common.data.page.TimePageData; 26 import org.thingsboard.server.common.data.page.TimePageData;
@@ -40,27 +38,6 @@ public class BaseEdgeEventService implements EdgeEventService { @@ -40,27 +38,6 @@ public class BaseEdgeEventService implements EdgeEventService {
40 public EdgeEventDao edgeEventDao; 38 public EdgeEventDao edgeEventDao;
41 39
42 @Override 40 @Override
43 - public EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType) {  
44 - switch (entityType) {  
45 - case DEVICE:  
46 - return EdgeEventType.DEVICE;  
47 - case ASSET:  
48 - return EdgeEventType.ASSET;  
49 - case ENTITY_VIEW:  
50 - return EdgeEventType.ENTITY_VIEW;  
51 - case DASHBOARD:  
52 - return EdgeEventType.DASHBOARD;  
53 - case USER:  
54 - return EdgeEventType.USER;  
55 - case ALARM:  
56 - return EdgeEventType.ALARM;  
57 - default:  
58 - log.warn("Failed to push notification to edge service. Unsupported entity type [{}]", entityType);  
59 - return null;  
60 - }  
61 - }  
62 -  
63 - @Override  
64 public ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent) { 41 public ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent) {
65 edgeEventValidator.validate(edgeEvent, EdgeEvent::getTenantId); 42 edgeEventValidator.validate(edgeEvent, EdgeEvent::getTenantId);
66 return edgeEventDao.saveAsync(edgeEvent); 43 return edgeEventDao.saveAsync(edgeEvent);
@@ -22,17 +22,13 @@ import lombok.extern.slf4j.Slf4j; @@ -22,17 +22,13 @@ import lombok.extern.slf4j.Slf4j;
22 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
24 import org.thingsboard.server.common.data.EntitySubtype; 24 import org.thingsboard.server.common.data.EntitySubtype;
25 -import org.thingsboard.server.common.data.EntityType;  
26 import org.thingsboard.server.common.data.edge.Edge; 25 import org.thingsboard.server.common.data.edge.Edge;
27 import org.thingsboard.server.common.data.id.DashboardId; 26 import org.thingsboard.server.common.data.id.DashboardId;
28 -import org.thingsboard.server.common.data.id.EdgeId;  
29 import org.thingsboard.server.common.data.id.RuleChainId; 27 import org.thingsboard.server.common.data.id.RuleChainId;
30 import org.thingsboard.server.common.data.id.TenantId; 28 import org.thingsboard.server.common.data.id.TenantId;
31 import org.thingsboard.server.common.data.page.TextPageLink; 29 import org.thingsboard.server.common.data.page.TextPageLink;
32 -import org.thingsboard.server.common.data.page.TimePageLink;  
33 import org.thingsboard.server.common.data.relation.EntityRelation; 30 import org.thingsboard.server.common.data.relation.EntityRelation;
34 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 31 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
35 -import org.thingsboard.server.common.data.rule.RuleChain;  
36 import org.thingsboard.server.dao.model.nosql.EdgeEntity; 32 import org.thingsboard.server.dao.model.nosql.EdgeEntity;
37 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; 33 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
38 import org.thingsboard.server.dao.relation.RelationDao; 34 import org.thingsboard.server.dao.relation.RelationDao;
@@ -113,19 +109,17 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao<EdgeEntity, @@ -113,19 +109,17 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao<EdgeEntity,
113 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndRuleChainId(UUID tenantId, UUID ruleChainId) { 109 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndRuleChainId(UUID tenantId, UUID ruleChainId) {
114 log.debug("Try to find edges by tenantId [{}], ruleChainId [{}]", tenantId, ruleChainId); 110 log.debug("Try to find edges by tenantId [{}], ruleChainId [{}]", tenantId, ruleChainId);
115 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new RuleChainId(ruleChainId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); 111 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new RuleChainId(ruleChainId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
116 - return Futures.transformAsync(relations, input -> {  
117 - List<ListenableFuture<Edge>> edgeFutures = new ArrayList<>(input.size());  
118 - for (EntityRelation relation : input) {  
119 - edgeFutures.add(findByIdAsync(new TenantId(tenantId), relation.getFrom().getId()));  
120 - }  
121 - return Futures.successfulAsList(edgeFutures);  
122 - }, MoreExecutors.directExecutor()); 112 + return transformFromRelationToEdge(tenantId, relations);
123 } 113 }
124 114
125 @Override 115 @Override
126 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndDashboardId(UUID tenantId, UUID dashboardId) { 116 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndDashboardId(UUID tenantId, UUID dashboardId) {
127 log.debug("Try to find edges by tenantId [{}], dashboardId [{}]", tenantId, dashboardId); 117 log.debug("Try to find edges by tenantId [{}], dashboardId [{}]", tenantId, dashboardId);
128 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new DashboardId(dashboardId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); 118 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new DashboardId(dashboardId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
  119 + return transformFromRelationToEdge(tenantId, relations);
  120 + }
  121 +
  122 + private ListenableFuture<List<Edge>> transformFromRelationToEdge(UUID tenantId, ListenableFuture<List<EntityRelation>> relations) {
129 return Futures.transformAsync(relations, input -> { 123 return Futures.transformAsync(relations, input -> {
130 List<ListenableFuture<Edge>> edgeFutures = new ArrayList<>(input.size()); 124 List<ListenableFuture<Edge>> edgeFutures = new ArrayList<>(input.size());
131 for (EntityRelation relation : input) { 125 for (EntityRelation relation : input) {
@@ -414,7 +414,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -414,7 +414,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
414 if (edge == null) { 414 if (edge == null) {
415 throw new DataValidationException("Can't assign ruleChain to non-existent edge!"); 415 throw new DataValidationException("Can't assign ruleChain to non-existent edge!");
416 } 416 }
417 - if (!edge.getTenantId().getId().equals(ruleChain.getTenantId().getId())) { 417 + if (!edge.getTenantId().equals(ruleChain.getTenantId())) {
418 throw new DataValidationException("Can't assign ruleChain to edge from different tenant!"); 418 throw new DataValidationException("Can't assign ruleChain to edge from different tenant!");
419 } 419 }
420 try { 420 try {
@@ -151,19 +151,17 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao<EdgeEntity, Edge> imple @@ -151,19 +151,17 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao<EdgeEntity, Edge> imple
151 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndRuleChainId(UUID tenantId, UUID ruleChainId) { 151 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndRuleChainId(UUID tenantId, UUID ruleChainId) {
152 log.debug("Try to find edges by tenantId [{}], ruleChainId [{}]", tenantId, ruleChainId); 152 log.debug("Try to find edges by tenantId [{}], ruleChainId [{}]", tenantId, ruleChainId);
153 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new RuleChainId(ruleChainId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); 153 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new RuleChainId(ruleChainId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
154 - return Futures.transformAsync(relations, input -> {  
155 - List<ListenableFuture<Edge>> edgeFutures = new ArrayList<>(input.size());  
156 - for (EntityRelation relation : input) {  
157 - edgeFutures.add(findByIdAsync(new TenantId(tenantId), relation.getFrom().getId()));  
158 - }  
159 - return Futures.successfulAsList(edgeFutures);  
160 - }, MoreExecutors.directExecutor()); 154 + return transformFromRelationToEdge(tenantId, relations);
161 } 155 }
162 156
163 @Override 157 @Override
164 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndDashboardId(UUID tenantId, UUID dashboardId) { 158 public ListenableFuture<List<Edge>> findEdgesByTenantIdAndDashboardId(UUID tenantId, UUID dashboardId) {
165 log.debug("Try to find edges by tenantId [{}], dashboardId [{}]", tenantId, dashboardId); 159 log.debug("Try to find edges by tenantId [{}], dashboardId [{}]", tenantId, dashboardId);
166 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new DashboardId(dashboardId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); 160 ListenableFuture<List<EntityRelation>> relations = relationDao.findAllByToAndType(new TenantId(tenantId), new DashboardId(dashboardId), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
  161 + return transformFromRelationToEdge(tenantId, relations);
  162 + }
  163 +
  164 + private ListenableFuture<List<Edge>> transformFromRelationToEdge(UUID tenantId, ListenableFuture<List<EntityRelation>> relations) {
167 return Futures.transformAsync(relations, input -> { 165 return Futures.transformAsync(relations, input -> {
168 List<ListenableFuture<Edge>> edgeFutures = new ArrayList<>(input.size()); 166 List<ListenableFuture<Edge>> edgeFutures = new ArrayList<>(input.size());
169 for (EntityRelation relation : input) { 167 for (EntityRelation relation : input) {
@@ -332,6 +332,21 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest { @@ -332,6 +332,21 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
332 Assert.assertEquals(1, result.size()); 332 Assert.assertEquals(1, result.size());
333 } 333 }
334 334
  335 + @Test
  336 + public void setDefaultRootEdgeRuleChain() throws Exception {
  337 + RuleChainId ruleChainId1 = saveRuleChainAndSetDefaultEdge("Default Edge Rule Chain 1");
  338 + RuleChainId ruleChainId2 = saveRuleChainAndSetDefaultEdge("Default Edge Rule Chain 2");
  339 +
  340 + ruleChainService.setDefaultRootEdgeRuleChain(tenantId, ruleChainId1);
  341 + ruleChainService.setDefaultRootEdgeRuleChain(tenantId, ruleChainId2);
  342 +
  343 + RuleChain ruleChainById = ruleChainService.findRuleChainById(tenantId, ruleChainId1);
  344 + Assert.assertFalse(ruleChainById.isRoot());
  345 +
  346 + ruleChainById = ruleChainService.findRuleChainById(tenantId, ruleChainId2);
  347 + Assert.assertTrue(ruleChainById.isRoot());
  348 + }
  349 +
335 private RuleChainId saveRuleChainAndSetDefaultEdge(String name) { 350 private RuleChainId saveRuleChainAndSetDefaultEdge(String name) {
336 RuleChain edgeRuleChain = new RuleChain(); 351 RuleChain edgeRuleChain = new RuleChain();
337 edgeRuleChain.setTenantId(tenantId); 352 edgeRuleChain.setTenantId(tenantId);
@@ -45,7 +45,8 @@ import org.thingsboard.server.common.data.Tenant; @@ -45,7 +45,8 @@ import org.thingsboard.server.common.data.Tenant;
45 import org.thingsboard.server.common.data.UpdateMessage; 45 import org.thingsboard.server.common.data.UpdateMessage;
46 import org.thingsboard.server.common.data.User; 46 import org.thingsboard.server.common.data.User;
47 import org.thingsboard.server.common.data.alarm.Alarm; 47 import org.thingsboard.server.common.data.alarm.Alarm;
48 -import org.thingsboard.server.common.data.id.AlarmId; 48 +import org.thingsboard.server.common.data.edge.Edge;
  49 +import org.thingsboard.server.common.data.edge.EdgeSearchQuery;
49 import org.thingsboard.server.common.data.alarm.AlarmInfo; 50 import org.thingsboard.server.common.data.alarm.AlarmInfo;
50 import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; 51 import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
51 import org.thingsboard.server.common.data.alarm.AlarmSeverity; 52 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
@@ -56,10 +57,12 @@ import org.thingsboard.server.common.data.audit.ActionType; @@ -56,10 +57,12 @@ import org.thingsboard.server.common.data.audit.ActionType;
56 import org.thingsboard.server.common.data.audit.AuditLog; 57 import org.thingsboard.server.common.data.audit.AuditLog;
57 import org.thingsboard.server.common.data.device.DeviceSearchQuery; 58 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
58 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; 59 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
  60 +import org.thingsboard.server.common.data.id.AlarmId;
59 import org.thingsboard.server.common.data.id.AssetId; 61 import org.thingsboard.server.common.data.id.AssetId;
60 import org.thingsboard.server.common.data.id.CustomerId; 62 import org.thingsboard.server.common.data.id.CustomerId;
61 import org.thingsboard.server.common.data.id.DashboardId; 63 import org.thingsboard.server.common.data.id.DashboardId;
62 import org.thingsboard.server.common.data.id.DeviceId; 64 import org.thingsboard.server.common.data.id.DeviceId;
  65 +import org.thingsboard.server.common.data.id.EdgeId;
63 import org.thingsboard.server.common.data.id.EntityId; 66 import org.thingsboard.server.common.data.id.EntityId;
64 import org.thingsboard.server.common.data.id.EntityViewId; 67 import org.thingsboard.server.common.data.id.EntityViewId;
65 import org.thingsboard.server.common.data.id.RuleChainId; 68 import org.thingsboard.server.common.data.id.RuleChainId;
@@ -1978,6 +1981,190 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1978,6 +1981,190 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1978 } 1981 }
1979 } 1982 }
1980 1983
  1984 + public Edge saveEdge(Edge edge) {
  1985 + return restTemplate.postForEntity(baseURL + "/api/edge", edge, Edge.class).getBody();
  1986 + }
  1987 +
  1988 + public void deleteEdge(EdgeId edgeId) {
  1989 + restTemplate.delete(baseURL + "/api/edge/{edgeId}", edgeId.getId());
  1990 + }
  1991 +
  1992 + public Optional<Edge> getEdgeById(EdgeId edgeId) {
  1993 + try {
  1994 + ResponseEntity<Edge> edge = restTemplate.getForEntity(baseURL + "/api/edge/{edgeId}", Edge.class, edgeId.getId());
  1995 + return Optional.ofNullable(edge.getBody());
  1996 + } catch (HttpClientErrorException exception) {
  1997 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  1998 + return Optional.empty();
  1999 + } else {
  2000 + throw exception;
  2001 + }
  2002 + }
  2003 + }
  2004 +
  2005 + public Optional<Edge> assignEdgeToCustomer(CustomerId customerId, EdgeId edgeId) {
  2006 + try {
  2007 + ResponseEntity<Edge> edge = restTemplate.postForEntity(baseURL + "/api/customer/{customerId}/edge/{edgeId}", null, Edge.class, customerId.getId(), edgeId.getId());
  2008 + return Optional.ofNullable(edge.getBody());
  2009 + } catch (HttpClientErrorException exception) {
  2010 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2011 + return Optional.empty();
  2012 + } else {
  2013 + throw exception;
  2014 + }
  2015 + }
  2016 + }
  2017 +
  2018 + public Optional<Edge> unassignEdgeFromCustomer(EdgeId edgeId) {
  2019 + try {
  2020 + ResponseEntity<Edge> edge = restTemplate.exchange(baseURL + "/api/customer/edge/{edgeId}", HttpMethod.DELETE, HttpEntity.EMPTY, Edge.class, edgeId.getId());
  2021 + return Optional.ofNullable(edge.getBody());
  2022 + } catch (HttpClientErrorException exception) {
  2023 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2024 + return Optional.empty();
  2025 + } else {
  2026 + throw exception;
  2027 + }
  2028 + }
  2029 + }
  2030 +
  2031 + public Optional<Device> assignDeviceToEdge(EdgeId edgeId, DeviceId deviceId) {
  2032 + try {
  2033 + ResponseEntity<Device> device = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/device/{deviceId}", null, Device.class, edgeId.getId(), deviceId.getId());
  2034 + return Optional.ofNullable(device.getBody());
  2035 + } catch (HttpClientErrorException exception) {
  2036 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2037 + return Optional.empty();
  2038 + } else {
  2039 + throw exception;
  2040 + }
  2041 + }
  2042 + }
  2043 +
  2044 + public Optional<Device> unassignDeviceFromEdge(DeviceId deviceId) {
  2045 + try {
  2046 + ResponseEntity<Device> device = restTemplate.exchange(baseURL + "/api/edge/device/{deviceId}", HttpMethod.DELETE, HttpEntity.EMPTY, Device.class, deviceId.getId());
  2047 + return Optional.ofNullable(device.getBody());
  2048 + } catch (HttpClientErrorException exception) {
  2049 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2050 + return Optional.empty();
  2051 + } else {
  2052 + throw exception;
  2053 + }
  2054 + }
  2055 + }
  2056 +
  2057 + public TextPageData<Device> getEdgeDevices(EdgeId edgeId, String deviceType, TextPageLink pageLink) {
  2058 + Map<String, String> params = new HashMap<>();
  2059 + params.put("edgeId", edgeId.getId().toString());
  2060 + params.put("type", deviceType);
  2061 + addPageLinkToParam(params, pageLink);
  2062 + return restTemplate.exchange(
  2063 + baseURL + "/api/edge/{edgeId}/devices?type={type}&" + getUrlParams(pageLink),
  2064 + HttpMethod.GET, HttpEntity.EMPTY,
  2065 + new ParameterizedTypeReference<TextPageData<Device>>() {
  2066 + }, params).getBody();
  2067 + }
  2068 +
  2069 + public Optional<Asset> assignAssetToEdge(EdgeId edgeId, AssetId assetId) {
  2070 + try {
  2071 + ResponseEntity<Asset> asset = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/asset/{assetId}", null, Asset.class, edgeId.getId(), assetId.getId());
  2072 + return Optional.ofNullable(asset.getBody());
  2073 + } catch (HttpClientErrorException exception) {
  2074 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2075 + return Optional.empty();
  2076 + } else {
  2077 + throw exception;
  2078 + }
  2079 + }
  2080 + }
  2081 +
  2082 + public Optional<Asset> unassignAssetFromEdge(AssetId assetId) {
  2083 + try {
  2084 + ResponseEntity<Asset> asset = restTemplate.exchange(baseURL + "/api/edge/asset/{assetId}", HttpMethod.DELETE, HttpEntity.EMPTY, Asset.class, assetId.getId());
  2085 + return Optional.ofNullable(asset.getBody());
  2086 + } catch (HttpClientErrorException exception) {
  2087 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2088 + return Optional.empty();
  2089 + } else {
  2090 + throw exception;
  2091 + }
  2092 + }
  2093 + }
  2094 +
  2095 + public TextPageData<Asset> getEdgeAssets(EdgeId edgeId, String assetType, TextPageLink pageLink) {
  2096 + Map<String, String> params = new HashMap<>();
  2097 + params.put("edgeId", edgeId.getId().toString());
  2098 + params.put("type", assetType);
  2099 + addPageLinkToParam(params, pageLink);
  2100 + return restTemplate.exchange(
  2101 + baseURL + "/api/edge/{edgeId}/assets?type={type}&" + getUrlParams(pageLink),
  2102 + HttpMethod.GET, HttpEntity.EMPTY,
  2103 + new ParameterizedTypeReference<TextPageData<Asset>>() {
  2104 + }, params).getBody();
  2105 + }
  2106 +
  2107 + public TextPageData<Edge> getTenantEdges(String type, TextPageLink pageLink) {
  2108 + Map<String, String> params = new HashMap<>();
  2109 + params.put("type", type);
  2110 + addPageLinkToParam(params, pageLink);
  2111 + return restTemplate.exchange(
  2112 + baseURL + "/api/tenant/edges?type={type}&" + getUrlParams(pageLink),
  2113 + HttpMethod.GET, HttpEntity.EMPTY,
  2114 + new ParameterizedTypeReference<TextPageData<Edge>>() {
  2115 + }, params).getBody();
  2116 + }
  2117 +
  2118 + public Optional<Edge> getTenantEdge(String edgeName) {
  2119 + try {
  2120 + ResponseEntity<Edge> edge = restTemplate.getForEntity(baseURL + "/api/tenant/edges?edgeName={edgeName}", Edge.class, edgeName);
  2121 + return Optional.ofNullable(edge.getBody());
  2122 + } catch (HttpClientErrorException exception) {
  2123 + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
  2124 + return Optional.empty();
  2125 + } else {
  2126 + throw exception;
  2127 + }
  2128 + }
  2129 + }
  2130 +
  2131 + public TextPageData<Edge> getCustomerEdges(CustomerId customerId, String edgeType, TextPageLink pageLink) {
  2132 + Map<String, String> params = new HashMap<>();
  2133 + params.put("customerId", customerId.getId().toString());
  2134 + params.put("type", edgeType);
  2135 + addPageLinkToParam(params, pageLink);
  2136 + return restTemplate.exchange(
  2137 + baseURL + "/api/customer/{customerId}/edges?type={type}&" + getUrlParams(pageLink),
  2138 + HttpMethod.GET, HttpEntity.EMPTY,
  2139 + new ParameterizedTypeReference<TextPageData<Edge>>() {
  2140 + }, params).getBody();
  2141 + }
  2142 +
  2143 + public List<Edge> getEdgesByIds(List<EdgeId> edgeIds) {
  2144 + return restTemplate.exchange(baseURL + "/api/edges?edgeIds={edgeIds}",
  2145 + HttpMethod.GET,
  2146 + HttpEntity.EMPTY, new ParameterizedTypeReference<List<Edge>>() {
  2147 + }, listIdsToString(edgeIds)).getBody();
  2148 + }
  2149 +
  2150 + public List<Edge> findByQuery(EdgeSearchQuery query) {
  2151 + return restTemplate.exchange(
  2152 + baseURL + "/api/edges",
  2153 + HttpMethod.POST,
  2154 + new HttpEntity<>(query),
  2155 + new ParameterizedTypeReference<List<Edge>>() {
  2156 + }).getBody();
  2157 + }
  2158 +
  2159 + public List<EntitySubtype> getEdgeTypes() {
  2160 + return restTemplate.exchange(
  2161 + baseURL + "/api/edge/types",
  2162 + HttpMethod.GET,
  2163 + HttpEntity.EMPTY,
  2164 + new ParameterizedTypeReference<List<EntitySubtype>>() {
  2165 + }).getBody();
  2166 + }
  2167 +
1981 @Deprecated 2168 @Deprecated
1982 public Optional<JsonNode> getAttributes(String accessToken, String clientKeys, String sharedKeys) { 2169 public Optional<JsonNode> getAttributes(String accessToken, String clientKeys, String sharedKeys) {
1983 Map<String, String> params = new HashMap<>(); 2170 Map<String, String> params = new HashMap<>();
@@ -58,6 +58,6 @@ public @interface RuleNode { @@ -58,6 +58,6 @@ public @interface RuleNode {
58 58
59 boolean customRelations() default false; 59 boolean customRelations() default false;
60 60
61 - RuleChainType[] ruleChainTypes() default RuleChainType.CORE; 61 + RuleChainType[] ruleChainTypes() default {RuleChainType.CORE, RuleChainType.EDGE};
62 62
63 } 63 }
@@ -37,9 +37,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -37,9 +37,7 @@ import org.thingsboard.server.common.msg.TbMsg;
37 "Will create new Customer if it doesn't exists and 'Create new Customer if not exists' is set to true.", 37 "Will create new Customer if it doesn't exists and 'Create new Customer if not exists' is set to true.",
38 uiResources = {"static/rulenode/rulenode-core-config.js"}, 38 uiResources = {"static/rulenode/rulenode-core-config.js"},
39 configDirective = "tbActionNodeAssignToCustomerConfig", 39 configDirective = "tbActionNodeAssignToCustomerConfig",
40 - icon = "add_circle",  
41 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
42 -) 40 + icon = "add_circle")
43 public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode<TbAssignToCustomerNodeConfiguration> { 41 public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode<TbAssignToCustomerNodeConfiguration> {
44 42
45 @Override 43 @Override
@@ -45,9 +45,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -45,9 +45,7 @@ import org.thingsboard.server.common.msg.TbMsg;
45 "Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.", 45 "Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.",
46 uiResources = {"static/rulenode/rulenode-core-config.js"}, 46 uiResources = {"static/rulenode/rulenode-core-config.js"},
47 configDirective = "tbActionNodeClearAlarmConfig", 47 configDirective = "tbActionNodeClearAlarmConfig",
48 - icon = "notifications_off",  
49 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
50 -) 48 + icon = "notifications_off")
51 public class TbClearAlarmNode extends TbAbstractAlarmNode<TbClearAlarmNodeConfiguration> { 49 public class TbClearAlarmNode extends TbAbstractAlarmNode<TbClearAlarmNodeConfiguration> {
52 50
53 @Override 51 @Override
@@ -57,9 +57,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -57,9 +57,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
57 "Changes message originator to related entity view and produces new messages according to count of updated entity views", 57 "Changes message originator to related entity view and produces new messages according to count of updated entity views",
58 uiResources = {"static/rulenode/rulenode-core-config.js"}, 58 uiResources = {"static/rulenode/rulenode-core-config.js"},
59 configDirective = "tbNodeEmptyConfig", 59 configDirective = "tbNodeEmptyConfig",
60 - icon = "content_copy",  
61 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
62 -) 60 + icon = "content_copy")
63 public class TbCopyAttributesToEntityViewNode implements TbNode { 61 public class TbCopyAttributesToEntityViewNode implements TbNode {
64 62
65 EmptyNodeConfiguration config; 63 EmptyNodeConfiguration config;
@@ -51,9 +51,7 @@ import java.util.List; @@ -51,9 +51,7 @@ import java.util.List;
51 "Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.", 51 "Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.",
52 uiResources = {"static/rulenode/rulenode-core-config.js"}, 52 uiResources = {"static/rulenode/rulenode-core-config.js"},
53 configDirective = "tbActionNodeCreateAlarmConfig", 53 configDirective = "tbActionNodeCreateAlarmConfig",
54 - icon = "notifications_active",  
55 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
56 -) 54 + icon = "notifications_active")
57 public class TbCreateAlarmNode extends TbAbstractAlarmNode<TbCreateAlarmNodeConfiguration> { 55 public class TbCreateAlarmNode extends TbAbstractAlarmNode<TbCreateAlarmNodeConfiguration> {
58 56
59 private static ObjectMapper mapper = new ObjectMapper(); 57 private static ObjectMapper mapper = new ObjectMapper();
@@ -54,9 +54,7 @@ import java.util.List; @@ -54,9 +54,7 @@ import java.util.List;
54 nodeDetails = "If the relation already exists or successfully created - Message send via <b>Success</b> chain, otherwise <b>Failure</b> chain will be used.", 54 nodeDetails = "If the relation already exists or successfully created - Message send via <b>Success</b> chain, otherwise <b>Failure</b> chain will be used.",
55 uiResources = {"static/rulenode/rulenode-core-config.js"}, 55 uiResources = {"static/rulenode/rulenode-core-config.js"},
56 configDirective = "tbActionNodeCreateRelationConfig", 56 configDirective = "tbActionNodeCreateRelationConfig",
57 - icon = "add_circle",  
58 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
59 -) 57 + icon = "add_circle")
60 public class TbCreateRelationNode extends TbAbstractRelationActionNode<TbCreateRelationNodeConfiguration> { 58 public class TbCreateRelationNode extends TbAbstractRelationActionNode<TbCreateRelationNodeConfiguration> {
61 59
62 @Override 60 @Override
@@ -44,9 +44,7 @@ import java.util.List; @@ -44,9 +44,7 @@ import java.util.List;
44 nodeDetails = "If the relation(s) successfully deleted - Message send via <b>Success</b> chain, otherwise <b>Failure</b> chain will be used.", 44 nodeDetails = "If the relation(s) successfully deleted - Message send via <b>Success</b> chain, otherwise <b>Failure</b> chain will be used.",
45 uiResources = {"static/rulenode/rulenode-core-config.js"}, 45 uiResources = {"static/rulenode/rulenode-core-config.js"},
46 configDirective = "tbActionNodeDeleteRelationConfig", 46 configDirective = "tbActionNodeDeleteRelationConfig",
47 - icon = "remove_circle",  
48 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
49 -) 47 + icon = "remove_circle")
50 public class TbDeleteRelationNode extends TbAbstractRelationActionNode<TbDeleteRelationNodeConfiguration> { 48 public class TbDeleteRelationNode extends TbAbstractRelationActionNode<TbDeleteRelationNodeConfiguration> {
51 49
52 @Override 50 @Override
@@ -37,10 +37,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -37,10 +37,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
37 "Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.", 37 "Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.",
38 uiResources = {"static/rulenode/rulenode-core-config.js"}, 38 uiResources = {"static/rulenode/rulenode-core-config.js"},
39 configDirective = "tbActionNodeLogConfig", 39 configDirective = "tbActionNodeLogConfig",
40 - icon = "menu",  
41 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
42 -)  
43 - 40 + icon = "menu")
44 public class TbLogNode implements TbNode { 41 public class TbLogNode implements TbNode {
45 42
46 private TbLogNodeConfiguration config; 43 private TbLogNodeConfiguration config;
@@ -44,9 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -44,9 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
44 nodeDetails = "Count incoming messages for specified interval and produces POST_TELEMETRY_REQUEST msg with messages count", 44 nodeDetails = "Count incoming messages for specified interval and produces POST_TELEMETRY_REQUEST msg with messages count",
45 icon = "functions", 45 icon = "functions",
46 uiResources = {"static/rulenode/rulenode-core-config.js"}, 46 uiResources = {"static/rulenode/rulenode-core-config.js"},
47 - configDirective = "tbActionNodeMsgCountConfig",  
48 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}  
49 -) 47 + configDirective = "tbActionNodeMsgCountConfig")
50 public class TbMsgCountNode implements TbNode { 48 public class TbMsgCountNode implements TbNode {
51 49
52 private static final String TB_MSG_COUNT_NODE_MSG = "TbMsgCountNodeMsg"; 50 private static final String TB_MSG_COUNT_NODE_MSG = "TbMsgCountNodeMsg";
@@ -78,7 +78,8 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -78,7 +78,8 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
78 " otherwise, the message will be routed via <b>success</b> chain.", 78 " otherwise, the message will be routed via <b>success</b> chain.",
79 uiResources = {"static/rulenode/rulenode-core-config.js"}, 79 uiResources = {"static/rulenode/rulenode-core-config.js"},
80 configDirective = "tbActionNodeCustomTableConfig", 80 configDirective = "tbActionNodeCustomTableConfig",
81 - icon = "file_upload" 81 + icon = "file_upload",
  82 + ruleChainTypes = RuleChainType.CORE
82 ) 83 )
83 public class TbSaveToCustomCassandraTableNode implements TbNode { 84 public class TbSaveToCustomCassandraTableNode implements TbNode {
84 85
@@ -21,9 +21,13 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; @@ -21,9 +21,13 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
21 import org.thingsboard.rule.engine.api.TbNodeException; 21 import org.thingsboard.rule.engine.api.TbNodeException;
22 import org.thingsboard.rule.engine.api.util.TbNodeUtils; 22 import org.thingsboard.rule.engine.api.util.TbNodeUtils;
23 import org.thingsboard.server.common.data.EntityType; 23 import org.thingsboard.server.common.data.EntityType;
24 -import org.thingsboard.server.common.data.id.*; 24 +import org.thingsboard.server.common.data.id.AssetId;
  25 +import org.thingsboard.server.common.data.id.CustomerId;
  26 +import org.thingsboard.server.common.data.id.DashboardId;
  27 +import org.thingsboard.server.common.data.id.DeviceId;
  28 +import org.thingsboard.server.common.data.id.EdgeId;
  29 +import org.thingsboard.server.common.data.id.EntityViewId;
25 import org.thingsboard.server.common.data.plugin.ComponentType; 30 import org.thingsboard.server.common.data.plugin.ComponentType;
26 -import org.thingsboard.server.common.data.rule.RuleChainType;  
27 import org.thingsboard.server.common.msg.TbMsg; 31 import org.thingsboard.server.common.msg.TbMsg;
28 32
29 @RuleNode( 33 @RuleNode(
@@ -34,8 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -34,8 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg;
34 nodeDetails = "Finds target Entity Customer by Customer name pattern and then unassign Originator Entity from this customer.", 38 nodeDetails = "Finds target Entity Customer by Customer name pattern and then unassign Originator Entity from this customer.",
35 uiResources = {"static/rulenode/rulenode-core-config.js"}, 39 uiResources = {"static/rulenode/rulenode-core-config.js"},
36 configDirective = "tbActionNodeUnAssignToCustomerConfig", 40 configDirective = "tbActionNodeUnAssignToCustomerConfig",
37 - icon = "remove_circle",  
38 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 41 + icon = "remove_circle"
39 ) 42 )
40 public class TbUnassignFromCustomerNode extends TbAbstractCustomerActionNode<TbUnassignFromCustomerNodeConfiguration> { 43 public class TbUnassignFromCustomerNode extends TbAbstractCustomerActionNode<TbUnassignFromCustomerNodeConfiguration> {
41 44
@@ -46,8 +46,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -46,8 +46,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
46 "For example <b>requestId</b> field can be accessed with <code>metadata.requestId</code>.", 46 "For example <b>requestId</b> field can be accessed with <code>metadata.requestId</code>.",
47 uiResources = {"static/rulenode/rulenode-core-config.js"}, 47 uiResources = {"static/rulenode/rulenode-core-config.js"},
48 configDirective = "tbActionNodeSnsConfig", 48 configDirective = "tbActionNodeSnsConfig",
49 - iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+",  
50 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 49 + iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"
51 ) 50 )
52 public class TbSnsNode implements TbNode { 51 public class TbSnsNode implements TbNode {
53 52
@@ -51,8 +51,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -51,8 +51,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
51 " For example <b>requestId</b> field can be accessed with <code>metadata.requestId</code>.", 51 " For example <b>requestId</b> field can be accessed with <code>metadata.requestId</code>.",
52 uiResources = {"static/rulenode/rulenode-core-config.js"}, 52 uiResources = {"static/rulenode/rulenode-core-config.js"},
53 configDirective = "tbActionNodeSqsConfig", 53 configDirective = "tbActionNodeSqsConfig",
54 - iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+",  
55 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 54 + iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"
56 ) 55 )
57 public class TbSqsNode implements TbNode { 56 public class TbSqsNode implements TbNode {
58 57
@@ -45,8 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -45,8 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
45 inEnabled = false, 45 inEnabled = false,
46 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 46 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
47 configDirective = "tbActionNodeGeneratorConfig", 47 configDirective = "tbActionNodeGeneratorConfig",
48 - icon = "repeat",  
49 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 48 + icon = "repeat"
50 ) 49 )
51 50
52 public class TbMsgGeneratorNode implements TbNode { 51 public class TbMsgGeneratorNode implements TbNode {
@@ -46,8 +46,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -46,8 +46,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
46 nodeDetails = "Delays messages for configurable period. Please note, this node acknowledges the message from the current queue (message will be removed from queue)", 46 nodeDetails = "Delays messages for configurable period. Please note, this node acknowledges the message from the current queue (message will be removed from queue)",
47 icon = "pause", 47 icon = "pause",
48 uiResources = {"static/rulenode/rulenode-core-config.js"}, 48 uiResources = {"static/rulenode/rulenode-core-config.js"},
49 - configDirective = "tbActionNodeMsgDelayConfig",  
50 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 49 + configDirective = "tbActionNodeMsgDelayConfig"
51 ) 50 )
52 51
53 public class TbMsgDelayNode implements TbNode { 52 public class TbMsgDelayNode implements TbNode {
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.rule.engine.edge; 16 package org.thingsboard.rule.engine.edge;
17 17
  18 +import com.fasterxml.jackson.core.JsonProcessingException;
18 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.google.common.util.concurrent.FutureCallback; 20 import com.google.common.util.concurrent.FutureCallback;
20 import com.google.common.util.concurrent.Futures; 21 import com.google.common.util.concurrent.Futures;
@@ -28,6 +29,7 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; @@ -28,6 +29,7 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
28 import org.thingsboard.rule.engine.api.TbNodeException; 29 import org.thingsboard.rule.engine.api.TbNodeException;
29 import org.thingsboard.rule.engine.api.util.TbNodeUtils; 30 import org.thingsboard.rule.engine.api.util.TbNodeUtils;
30 import org.thingsboard.server.common.data.DataConstants; 31 import org.thingsboard.server.common.data.DataConstants;
  32 +import org.thingsboard.server.common.data.EdgeUtils;
31 import org.thingsboard.server.common.data.EntityType; 33 import org.thingsboard.server.common.data.EntityType;
32 import org.thingsboard.server.common.data.audit.ActionType; 34 import org.thingsboard.server.common.data.audit.ActionType;
33 import org.thingsboard.server.common.data.edge.EdgeEvent; 35 import org.thingsboard.server.common.data.edge.EdgeEvent;
@@ -38,6 +40,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -38,6 +40,7 @@ import org.thingsboard.server.common.data.id.TenantId;
38 import org.thingsboard.server.common.data.plugin.ComponentType; 40 import org.thingsboard.server.common.data.plugin.ComponentType;
39 import org.thingsboard.server.common.data.relation.EntityRelation; 41 import org.thingsboard.server.common.data.relation.EntityRelation;
40 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 42 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
  43 +import org.thingsboard.server.common.data.rule.RuleChainType;
41 import org.thingsboard.server.common.msg.TbMsg; 44 import org.thingsboard.server.common.msg.TbMsg;
42 import org.thingsboard.server.common.msg.session.SessionMsgType; 45 import org.thingsboard.server.common.msg.session.SessionMsgType;
43 46
@@ -55,7 +58,8 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -55,7 +58,8 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
55 nodeDetails = "Pushes messages to edge, if Message Originator assigned to particular edge or is EDGE entity. This node is used only on Cloud instances to push messages from Cloud to Edge. Supports only DEVICE, ENTITY_VIEW, ASSET and EDGE Message Originator(s).", 58 nodeDetails = "Pushes messages to edge, if Message Originator assigned to particular edge or is EDGE entity. This node is used only on Cloud instances to push messages from Cloud to Edge. Supports only DEVICE, ENTITY_VIEW, ASSET and EDGE Message Originator(s).",
56 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 59 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
57 configDirective = "tbNodeEmptyConfig", 60 configDirective = "tbNodeEmptyConfig",
58 - icon = "cloud_download" 61 + icon = "cloud_download",
  62 + ruleChainTypes = RuleChainType.CORE
59 ) 63 )
60 public class TbMsgPushToEdgeNode implements TbNode { 64 public class TbMsgPushToEdgeNode implements TbNode {
61 65
@@ -77,33 +81,38 @@ public class TbMsgPushToEdgeNode implements TbNode { @@ -77,33 +81,38 @@ public class TbMsgPushToEdgeNode implements TbNode {
77 if (isSupportedOriginator(msg.getOriginator().getEntityType())) { 81 if (isSupportedOriginator(msg.getOriginator().getEntityType())) {
78 if (isSupportedMsgType(msg.getType())) { 82 if (isSupportedMsgType(msg.getType())) {
79 ListenableFuture<EdgeId> getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator()); 83 ListenableFuture<EdgeId> getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator());
80 - Futures.transform(getEdgeIdFuture, edgeId -> {  
81 - EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType());  
82 - if (edgeEventTypeByEntityType == null) {  
83 - log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType());  
84 - ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'"));  
85 - }  
86 - EdgeEvent edgeEvent = new EdgeEvent();  
87 - edgeEvent.setTenantId(ctx.getTenantId());  
88 - edgeEvent.setEdgeId(edgeId);  
89 - edgeEvent.setEdgeEventAction(getActionTypeByMsgType(msg.getType()).name());  
90 - edgeEvent.setEntityId(msg.getOriginator().getId());  
91 - edgeEvent.setEdgeEventType(edgeEventTypeByEntityType);  
92 - edgeEvent.setEntityBody(json.valueToTree(msg.getData()));  
93 - ListenableFuture<EdgeEvent> saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent);  
94 - Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {  
95 - @Override  
96 - public void onSuccess(@Nullable EdgeEvent event) {  
97 - ctx.tellNext(msg, SUCCESS); 84 + Futures.addCallback(getEdgeIdFuture, new FutureCallback<EdgeId>() {
  85 + @Override
  86 + public void onSuccess(@Nullable EdgeId edgeId) {
  87 + EdgeEventType edgeEventTypeByEntityType = EdgeUtils.getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType());
  88 + if (edgeEventTypeByEntityType == null) {
  89 + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType());
  90 + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'"));
98 } 91 }
99 -  
100 - @Override  
101 - public void onFailure(Throwable th) {  
102 - log.error("Could not save edge event", th);  
103 - ctx.tellFailure(msg, th); 92 + EdgeEvent edgeEvent = null;
  93 + try {
  94 + edgeEvent = buildEdgeEvent(ctx, msg, edgeId, edgeEventTypeByEntityType);
  95 + } catch (JsonProcessingException e) {
  96 + log.error("Failed to build edge event", e);
104 } 97 }
105 - }, ctx.getDbCallbackExecutor());  
106 - return null; 98 + ListenableFuture<EdgeEvent> saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent);
  99 + Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
  100 + @Override
  101 + public void onSuccess(@Nullable EdgeEvent event) {
  102 + ctx.tellNext(msg, SUCCESS);
  103 + }
  104 + @Override
  105 + public void onFailure(Throwable th) {
  106 + log.error("Could not save edge event", th);
  107 + ctx.tellFailure(msg, th);
  108 + }
  109 + }, ctx.getDbCallbackExecutor());
  110 + }
  111 + @Override
  112 + public void onFailure(Throwable t) {
  113 + ctx.tellFailure(msg, t);
  114 + }
  115 +
107 }, ctx.getDbCallbackExecutor()); 116 }, ctx.getDbCallbackExecutor());
108 } else { 117 } else {
109 log.debug("Unsupported msg type {}", msg.getType()); 118 log.debug("Unsupported msg type {}", msg.getType());
@@ -115,6 +124,17 @@ public class TbMsgPushToEdgeNode implements TbNode { @@ -115,6 +124,17 @@ public class TbMsgPushToEdgeNode implements TbNode {
115 } 124 }
116 } 125 }
117 126
  127 + private EdgeEvent buildEdgeEvent(TbContext ctx, TbMsg msg, EdgeId edgeId, EdgeEventType edgeEventTypeByEntityType) throws JsonProcessingException {
  128 + EdgeEvent edgeEvent = new EdgeEvent();
  129 + edgeEvent.setTenantId(ctx.getTenantId());
  130 + edgeEvent.setEdgeId(edgeId);
  131 + edgeEvent.setEdgeEventAction(getActionTypeByMsgType(msg.getType()).name());
  132 + edgeEvent.setEntityId(msg.getOriginator().getId());
  133 + edgeEvent.setEdgeEventType(edgeEventTypeByEntityType);
  134 + edgeEvent.setEntityBody(json.readTree(msg.getData()));
  135 + return edgeEvent;
  136 + }
  137 +
118 private ActionType getActionTypeByMsgType(String msgType) { 138 private ActionType getActionTypeByMsgType(String msgType) {
119 ActionType actionType; 139 ActionType actionType;
120 if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msgType)) { 140 if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msgType)) {
@@ -40,8 +40,7 @@ import java.util.Map; @@ -40,8 +40,7 @@ import java.util.Map;
40 nodeDetails = "If selected checkbox 'Check that all selected keys are present'\" and all keys in message data and metadata are exist - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.\n" + 40 nodeDetails = "If selected checkbox 'Check that all selected keys are present'\" and all keys in message data and metadata are exist - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.\n" +
41 "Else if the checkbox is not selected, and at least one of the keys from data or metadata of the message exists - send Message via <b>True</b> chain, otherwise, <b>False</b> chain is used. ", 41 "Else if the checkbox is not selected, and at least one of the keys from data or metadata of the message exists - send Message via <b>True</b> chain, otherwise, <b>False</b> chain is used. ",
42 uiResources = {"static/rulenode/rulenode-core-config.js"}, 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 - configDirective = "tbFilterNodeCheckMessageConfig",  
44 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 43 + configDirective = "tbFilterNodeCheckMessageConfig"
45 ) 44 )
46 public class TbCheckMessageNode implements TbNode { 45 public class TbCheckMessageNode implements TbNode {
47 46
@@ -52,8 +52,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -52,8 +52,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
52 " any relation to the originator of the message by type and direction.", 52 " any relation to the originator of the message by type and direction.",
53 nodeDetails = "If at least one relation exists - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.", 53 nodeDetails = "If at least one relation exists - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
54 uiResources = {"static/rulenode/rulenode-core-config.js"}, 54 uiResources = {"static/rulenode/rulenode-core-config.js"},
55 - configDirective = "tbFilterNodeCheckRelationConfig",  
56 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 55 + configDirective = "tbFilterNodeCheckRelationConfig"
57 ) 56 )
58 public class TbCheckRelationNode implements TbNode { 57 public class TbCheckRelationNode implements TbNode {
59 58
@@ -37,8 +37,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -37,8 +37,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
37 "Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" + 37 "Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" +
38 "Message type can be accessed via <code>msgType</code> property.", 38 "Message type can be accessed via <code>msgType</code> property.",
39 uiResources = {"static/rulenode/rulenode-core-config.js"}, 39 uiResources = {"static/rulenode/rulenode-core-config.js"},
40 - configDirective = "tbFilterNodeScriptConfig",  
41 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 40 + configDirective = "tbFilterNodeScriptConfig"
42 ) 41 )
43 42
44 public class TbJsFilterNode implements TbNode { 43 public class TbJsFilterNode implements TbNode {
@@ -40,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -40,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
40 "Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" + 40 "Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" +
41 "Message type can be accessed via <code>msgType</code> property.", 41 "Message type can be accessed via <code>msgType</code> property.",
42 uiResources = {"static/rulenode/rulenode-core-config.js"}, 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 - configDirective = "tbFilterNodeSwitchConfig",  
44 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 43 + configDirective = "tbFilterNodeSwitchConfig"
45 ) 44 )
46 public class TbJsSwitchNode implements TbNode { 45 public class TbJsSwitchNode implements TbNode {
47 46
@@ -34,8 +34,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -34,8 +34,7 @@ import org.thingsboard.server.common.msg.TbMsg;
34 nodeDescription = "Filter incoming messages by Message Type", 34 nodeDescription = "Filter incoming messages by Message Type",
35 nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.", 35 nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
36 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 36 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
37 - configDirective = "tbFilterNodeMessageTypeConfig",  
38 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 37 + configDirective = "tbFilterNodeMessageTypeConfig"
39 ) 38 )
40 public class TbMsgTypeFilterNode implements TbNode { 39 public class TbMsgTypeFilterNode implements TbNode {
41 40
@@ -35,8 +35,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; @@ -35,8 +35,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
35 nodeDescription = "Route incoming messages by Message Type", 35 nodeDescription = "Route incoming messages by Message Type",
36 nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b> etc. via corresponding chain, otherwise <b>Other</b> chain is used.", 36 nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b> etc. via corresponding chain, otherwise <b>Other</b> chain is used.",
37 uiResources = {"static/rulenode/rulenode-core-config.js"}, 37 uiResources = {"static/rulenode/rulenode-core-config.js"},
38 - configDirective = "tbNodeEmptyConfig",  
39 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 38 + configDirective = "tbNodeEmptyConfig"
40 ) 39 )
41 public class TbMsgTypeSwitchNode implements TbNode { 40 public class TbMsgTypeSwitchNode implements TbNode {
42 41
@@ -32,8 +32,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -32,8 +32,7 @@ import org.thingsboard.server.common.msg.TbMsg;
32 nodeDescription = "Filter incoming messages by message Originator Type", 32 nodeDescription = "Filter incoming messages by message Originator Type",
33 nodeDetails = "If Originator Type of incoming message is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.", 33 nodeDetails = "If Originator Type of incoming message is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
34 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 34 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
35 - configDirective = "tbFilterNodeOriginatorTypeConfig",  
36 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 35 + configDirective = "tbFilterNodeOriginatorTypeConfig"
37 ) 36 )
38 public class TbOriginatorTypeFilterNode implements TbNode { 37 public class TbOriginatorTypeFilterNode implements TbNode {
39 38
@@ -32,8 +32,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -32,8 +32,7 @@ import org.thingsboard.server.common.msg.TbMsg;
32 nodeDescription = "Route incoming messages by Message Originator Type", 32 nodeDescription = "Route incoming messages by Message Originator Type",
33 nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).", 33 nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).",
34 uiResources = {"static/rulenode/rulenode-core-config.js"}, 34 uiResources = {"static/rulenode/rulenode-core-config.js"},
35 - configDirective = "tbNodeEmptyConfig",  
36 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 35 + configDirective = "tbNodeEmptyConfig"
37 ) 36 )
38 public class TbOriginatorTypeSwitchNode implements TbNode { 37 public class TbOriginatorTypeSwitchNode implements TbNode {
39 38
@@ -50,8 +50,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -50,8 +50,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
50 "<b>messageId</b> field can be accessed with <code>metadata.messageId</code>.", 50 "<b>messageId</b> field can be accessed with <code>metadata.messageId</code>.",
51 uiResources = {"static/rulenode/rulenode-core-config.js"}, 51 uiResources = {"static/rulenode/rulenode-core-config.js"},
52 configDirective = "tbActionNodePubSubConfig", 52 configDirective = "tbActionNodePubSubConfig",
53 - iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=",  
54 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 53 + iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo="
55 ) 54 )
56 public class TbPubSubNode implements TbNode { 55 public class TbPubSubNode implements TbNode {
57 56
@@ -52,8 +52,7 @@ import java.util.concurrent.TimeoutException; @@ -52,8 +52,7 @@ import java.util.concurrent.TimeoutException;
52 nodeDescription = "Produces incoming messages using GPS based geofencing", 52 nodeDescription = "Produces incoming messages using GPS based geofencing",
53 nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters", 53 nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters",
54 uiResources = {"static/rulenode/rulenode-core-config.js"}, 54 uiResources = {"static/rulenode/rulenode-core-config.js"},
55 - configDirective = "tbActionNodeGpsGeofencingConfig",  
56 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 55 + configDirective = "tbActionNodeGpsGeofencingConfig"
57 ) 56 )
58 public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> { 57 public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> {
59 58
@@ -53,8 +53,7 @@ import java.util.List; @@ -53,8 +53,7 @@ import java.util.List;
53 nodeDescription = "Filter incoming messages by GPS based geofencing", 53 nodeDescription = "Filter incoming messages by GPS based geofencing",
54 nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.", 54 nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.",
55 uiResources = {"static/rulenode/rulenode-core-config.js"}, 55 uiResources = {"static/rulenode/rulenode-core-config.js"},
56 - configDirective = "tbFilterNodeGpsGeofencingConfig",  
57 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 56 + configDirective = "tbFilterNodeGpsGeofencingConfig"
58 ) 57 )
59 public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode<TbGpsGeofencingFilterNodeConfiguration> { 58 public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode<TbGpsGeofencingFilterNodeConfiguration> {
60 59
@@ -52,8 +52,7 @@ import java.util.Properties; @@ -52,8 +52,7 @@ import java.util.Properties;
52 " from the Kafka in the Message Metadata. For example <b>partition</b> field can be accessed with <code>metadata.partition</code>.", 52 " from the Kafka in the Message Metadata. For example <b>partition</b> field can be accessed with <code>metadata.partition</code>.",
53 uiResources = {"static/rulenode/rulenode-core-config.js"}, 53 uiResources = {"static/rulenode/rulenode-core-config.js"},
54 configDirective = "tbActionNodeKafkaConfig", 54 configDirective = "tbActionNodeKafkaConfig",
55 - iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==",  
56 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 55 + iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg=="
57 ) 56 )
58 public class TbKafkaNode implements TbNode { 57 public class TbKafkaNode implements TbNode {
59 58
@@ -41,8 +41,7 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE; @@ -41,8 +41,7 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE;
41 "Set 'SEND_EMAIL' output message type.", 41 "Set 'SEND_EMAIL' output message type.",
42 uiResources = {"static/rulenode/rulenode-core-config.js"}, 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 configDirective = "tbTransformationNodeToEmailConfig", 43 configDirective = "tbTransformationNodeToEmailConfig",
44 - icon = "email",  
45 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 44 + icon = "email"
46 ) 45 )
47 public class TbMsgToEmailNode implements TbNode { 46 public class TbMsgToEmailNode implements TbNode {
48 47
@@ -47,8 +47,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -47,8 +47,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
47 "with <code>to Email</code> Node using <code>Successful</code> chain.", 47 "with <code>to Email</code> Node using <code>Successful</code> chain.",
48 uiResources = {"static/rulenode/rulenode-core-config.js"}, 48 uiResources = {"static/rulenode/rulenode-core-config.js"},
49 configDirective = "tbActionNodeSendEmailConfig", 49 configDirective = "tbActionNodeSendEmailConfig",
50 - icon = "send",  
51 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 50 + icon = "send"
52 ) 51 )
53 public class TbSendEmailNode implements TbNode { 52 public class TbSendEmailNode implements TbNode {
54 53
@@ -41,8 +41,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -41,8 +41,7 @@ import org.thingsboard.server.common.msg.TbMsg;
41 "To access those attributes in other nodes this template can be used " + 41 "To access those attributes in other nodes this template can be used " +
42 "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ", 42 "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ",
43 uiResources = {"static/rulenode/rulenode-core-config.js"}, 43 uiResources = {"static/rulenode/rulenode-core-config.js"},
44 - configDirective = "tbEnrichmentNodeOriginatorAttributesConfig",  
45 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 44 + configDirective = "tbEnrichmentNodeOriginatorAttributesConfig"
46 ) 45 )
47 public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> { 46 public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> {
48 47
@@ -34,8 +34,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; @@ -34,8 +34,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
34 "To access those attributes in other nodes this template can be used " + 34 "To access those attributes in other nodes this template can be used " +
35 "<code>metadata.temperature</code>.", 35 "<code>metadata.temperature</code>.",
36 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 36 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
37 - configDirective = "tbEnrichmentNodeCustomerAttributesConfig",  
38 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 37 + configDirective = "tbEnrichmentNodeCustomerAttributesConfig"
39 ) 38 )
40 public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> { 39 public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> {
41 40
@@ -43,8 +43,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -43,8 +43,7 @@ import org.thingsboard.server.common.msg.TbMsg;
43 "<b>Note:</b> only Device, Asset, and Entity View type are allowed.<br><br>" + 43 "<b>Note:</b> only Device, Asset, and Entity View type are allowed.<br><br>" +
44 "If the originator of the message is not assigned to Customer, or originator type is not supported - Message will be forwarded to <b>Failure</b> chain, otherwise, <b>Success</b> chain will be used.", 44 "If the originator of the message is not assigned to Customer, or originator type is not supported - Message will be forwarded to <b>Failure</b> chain, otherwise, <b>Success</b> chain will be used.",
45 uiResources = {"static/rulenode/rulenode-core-config.js"}, 45 uiResources = {"static/rulenode/rulenode-core-config.js"},
46 - configDirective = "tbEnrichmentNodeEntityDetailsConfig",  
47 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 46 + configDirective = "tbEnrichmentNodeEntityDetailsConfig"
48 ) 47 )
49 public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration> { 48 public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration> {
50 49
@@ -39,8 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -39,8 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg;
39 "To access those attributes in other nodes this template can be used " + 39 "To access those attributes in other nodes this template can be used " +
40 "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ", 40 "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ",
41 uiResources = {"static/rulenode/rulenode-core-config.js"}, 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 - configDirective = "tbEnrichmentNodeDeviceAttributesConfig",  
43 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 42 + configDirective = "tbEnrichmentNodeDeviceAttributesConfig"
44 ) 43 )
45 public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> { 44 public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> {
46 45
@@ -44,8 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -44,8 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
44 nodeDescription = "Add Message Originator fields values into Message Metadata", 44 nodeDescription = "Add Message Originator fields values into Message Metadata",
45 nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.", 45 nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.",
46 uiResources = {"static/rulenode/rulenode-core-config.js"}, 46 uiResources = {"static/rulenode/rulenode-core-config.js"},
47 - configDirective = "tbEnrichmentNodeOriginatorFieldsConfig",  
48 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 47 + configDirective = "tbEnrichmentNodeOriginatorFieldsConfig"
49 ) 48 )
50 public class TbGetOriginatorFieldsNode implements TbNode { 49 public class TbGetOriginatorFieldsNode implements TbNode {
51 50
@@ -36,8 +36,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; @@ -36,8 +36,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
36 "To access those attributes in other nodes this template can be used " + 36 "To access those attributes in other nodes this template can be used " +
37 "<code>metadata.temperature</code>.", 37 "<code>metadata.temperature</code>.",
38 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 38 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
39 - configDirective = "tbEnrichmentNodeRelatedAttributesConfig",  
40 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 39 + configDirective = "tbEnrichmentNodeRelatedAttributesConfig"
41 ) 40 )
42 41
43 public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> { 42 public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {
@@ -67,8 +67,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE; @@ -67,8 +67,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE;
67 "Also, the rule node allows you to select telemetry sampling order: <b>ASC</b> or <b>DESC</b>. </br>" + 67 "Also, the rule node allows you to select telemetry sampling order: <b>ASC</b> or <b>DESC</b>. </br>" +
68 "<b>Note</b>: The maximum size of the fetched array is 1000 records.\n ", 68 "<b>Note</b>: The maximum size of the fetched array is 1000 records.\n ",
69 uiResources = {"static/rulenode/rulenode-core-config.js"}, 69 uiResources = {"static/rulenode/rulenode-core-config.js"},
70 - configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase",  
71 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 70 + configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase"
72 ) 71 )
73 public class TbGetTelemetryNode implements TbNode { 72 public class TbGetTelemetryNode implements TbNode {
74 73
@@ -36,8 +36,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; @@ -36,8 +36,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
36 "To access those attributes in other nodes this template can be used " + 36 "To access those attributes in other nodes this template can be used " +
37 "<code>metadata.temperature</code>.", 37 "<code>metadata.temperature</code>.",
38 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 38 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
39 - configDirective = "tbEnrichmentNodeTenantAttributesConfig",  
40 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 39 + configDirective = "tbEnrichmentNodeTenantAttributesConfig"
41 ) 40 )
42 public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> { 41 public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> {
43 42
@@ -38,8 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -38,8 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg;
38 "<b>Note:</b> only Device, Asset, and Entity View type are allowed.<br><br>" + 38 "<b>Note:</b> only Device, Asset, and Entity View type are allowed.<br><br>" +
39 "If the originator of the message is not assigned to Tenant, or originator type is not supported - Message will be forwarded to <b>Failure</b> chain, otherwise, <b>Success</b> chain will be used.", 39 "If the originator of the message is not assigned to Tenant, or originator type is not supported - Message will be forwarded to <b>Failure</b> chain, otherwise, <b>Success</b> chain will be used.",
40 uiResources = {"static/rulenode/rulenode-core-config.js"}, 40 uiResources = {"static/rulenode/rulenode-core-config.js"},
41 - configDirective = "tbEnrichmentNodeEntityDetailsConfig",  
42 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 41 + configDirective = "tbEnrichmentNodeEntityDetailsConfig"
43 ) 42 )
44 public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration> { 43 public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration> {
45 44
@@ -50,8 +50,7 @@ import java.util.concurrent.TimeoutException; @@ -50,8 +50,7 @@ import java.util.concurrent.TimeoutException;
50 nodeDetails = "Will publish message payload to the MQTT broker with QoS <b>AT_LEAST_ONCE</b>.", 50 nodeDetails = "Will publish message payload to the MQTT broker with QoS <b>AT_LEAST_ONCE</b>.",
51 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 51 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
52 configDirective = "tbActionNodeMqttConfig", 52 configDirective = "tbActionNodeMqttConfig",
53 - icon = "call_split",  
54 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 53 + icon = "call_split"
55 ) 54 )
56 public class TbMqttNode implements TbNode { 55 public class TbMqttNode implements TbNode {
57 56
@@ -40,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -40,8 +40,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
40 nodeDetails = "Will publish message payload to RabbitMQ queue.", 40 nodeDetails = "Will publish message payload to RabbitMQ queue.",
41 uiResources = {"static/rulenode/rulenode-core-config.js"}, 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 configDirective = "tbActionNodeRabbitMqConfig", 42 configDirective = "tbActionNodeRabbitMqConfig",
43 - iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=",  
44 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 43 + iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4="
45 ) 44 )
46 public class TbRabbitMqNode implements TbNode { 45 public class TbRabbitMqNode implements TbNode {
47 46
@@ -42,8 +42,7 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -42,8 +42,7 @@ import org.thingsboard.server.common.msg.TbMsg;
42 "and if your proxy with auth, the next ones should be added: \"tb.proxy.user\" and \"tb.proxy.password\" to the thingsboard.conf file.", 42 "and if your proxy with auth, the next ones should be added: \"tb.proxy.user\" and \"tb.proxy.password\" to the thingsboard.conf file.",
43 uiResources = {"static/rulenode/rulenode-core-config.js"}, 43 uiResources = {"static/rulenode/rulenode-core-config.js"},
44 configDirective = "tbActionNodeRestApiCallConfig", 44 configDirective = "tbActionNodeRestApiCallConfig",
45 - iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+",  
46 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 45 + iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+"
47 ) 46 )
48 public class TbRestApiCallNode implements TbNode { 47 public class TbRestApiCallNode implements TbNode {
49 48
@@ -40,8 +40,7 @@ import java.util.UUID; @@ -40,8 +40,7 @@ import java.util.UUID;
40 nodeDetails = "Expects messages with any message type. Will forward message body to the device.", 40 nodeDetails = "Expects messages with any message type. Will forward message body to the device.",
41 uiResources = {"static/rulenode/rulenode-core-config.js"}, 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 configDirective = "tbActionNodeRpcReplyConfig", 42 configDirective = "tbActionNodeRpcReplyConfig",
43 - icon = "call_merge",  
44 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 43 + icon = "call_merge"
45 ) 44 )
46 public class TbSendRPCReplyNode implements TbNode { 45 public class TbSendRPCReplyNode implements TbNode {
47 46
@@ -51,8 +51,7 @@ import java.util.concurrent.TimeUnit; @@ -51,8 +51,7 @@ import java.util.concurrent.TimeUnit;
51 "If the RPC call request is originated by REST API call from user, will forward the response to user immediately.", 51 "If the RPC call request is originated by REST API call from user, will forward the response to user immediately.",
52 uiResources = {"static/rulenode/rulenode-core-config.js"}, 52 uiResources = {"static/rulenode/rulenode-core-config.js"},
53 configDirective = "tbActionNodeRpcRequestConfig", 53 configDirective = "tbActionNodeRpcRequestConfig",
54 - icon = "call_made",  
55 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 54 + icon = "call_made"
56 ) 55 )
57 public class TbSendRPCRequestNode implements TbNode { 56 public class TbSendRPCRequestNode implements TbNode {
58 57
@@ -45,8 +45,7 @@ import java.util.Set; @@ -45,8 +45,7 @@ import java.util.Set;
45 nodeDetails = "Saves entity attributes based on configurable scope parameter. Expects messages with 'POST_ATTRIBUTES_REQUEST' message type", 45 nodeDetails = "Saves entity attributes based on configurable scope parameter. Expects messages with 'POST_ATTRIBUTES_REQUEST' message type",
46 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 46 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
47 configDirective = "tbActionNodeAttributesConfig", 47 configDirective = "tbActionNodeAttributesConfig",
48 - icon = "file_upload",  
49 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 48 + icon = "file_upload"
50 ) 49 )
51 public class TbMsgAttributesNode implements TbNode { 50 public class TbMsgAttributesNode implements TbNode {
52 51
@@ -46,8 +46,7 @@ import java.util.Map; @@ -46,8 +46,7 @@ import java.util.Map;
46 nodeDetails = "Saves timeseries telemetry data based on configurable TTL parameter. Expects messages with 'POST_TELEMETRY_REQUEST' message type", 46 nodeDetails = "Saves timeseries telemetry data based on configurable TTL parameter. Expects messages with 'POST_TELEMETRY_REQUEST' message type",
47 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 47 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
48 configDirective = "tbActionNodeTimeseriesConfig", 48 configDirective = "tbActionNodeTimeseriesConfig",
49 - icon = "file_upload",  
50 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 49 + icon = "file_upload"
51 ) 50 )
52 public class TbMsgTimeseriesNode implements TbNode { 51 public class TbMsgTimeseriesNode implements TbNode {
53 52
@@ -39,8 +39,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -39,8 +39,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
39 "Subsequent messages will not be processed until the previous message processing is completed or timeout event occurs.\n" + 39 "Subsequent messages will not be processed until the previous message processing is completed or timeout event occurs.\n" +
40 "Size of the queue per originator and timeout values are configurable on a system level", 40 "Size of the queue per originator and timeout values are configurable on a system level",
41 uiResources = {"static/rulenode/rulenode-core-config.js"}, 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 - configDirective = "tbNodeEmptyConfig",  
43 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 42 + configDirective = "tbNodeEmptyConfig"
44 ) 43 )
45 @Deprecated 44 @Deprecated
46 public class TbSynchronizationBeginNode implements TbNode { 45 public class TbSynchronizationBeginNode implements TbNode {
@@ -39,8 +39,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -39,8 +39,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
39 nodeDescription = "This Node is now deprecated. Use \"Checkpoint\" instead.", 39 nodeDescription = "This Node is now deprecated. Use \"Checkpoint\" instead.",
40 nodeDetails = "", 40 nodeDetails = "",
41 uiResources = {"static/rulenode/rulenode-core-config.js"}, 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 - configDirective = ("tbNodeEmptyConfig"),  
43 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 42 + configDirective = ("tbNodeEmptyConfig")
44 ) 43 )
45 @Deprecated 44 @Deprecated
46 public class TbSynchronizationEndNode implements TbNode { 45 public class TbSynchronizationEndNode implements TbNode {
@@ -47,8 +47,7 @@ import java.util.HashSet; @@ -47,8 +47,7 @@ import java.util.HashSet;
47 "Alarm Originator found only in case original Originator is <code>Alarm</code> entity.", 47 "Alarm Originator found only in case original Originator is <code>Alarm</code> entity.",
48 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 48 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
49 configDirective = "tbTransformationNodeChangeOriginatorConfig", 49 configDirective = "tbTransformationNodeChangeOriginatorConfig",
50 - icon = "find_replace",  
51 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 50 + icon = "find_replace"
52 ) 51 )
53 public class TbChangeOriginatorNode extends TbAbstractTransformNode { 52 public class TbChangeOriginatorNode extends TbAbstractTransformNode {
54 53
@@ -38,8 +38,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @@ -38,8 +38,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
38 "<code>{ msg: <i style=\"color: #666;\">new payload</i>,<br/>&nbsp&nbsp&nbspmetadata: <i style=\"color: #666;\">new metadata</i>,<br/>&nbsp&nbsp&nbspmsgType: <i style=\"color: #666;\">new msgType</i> }</code><br/>" + 38 "<code>{ msg: <i style=\"color: #666;\">new payload</i>,<br/>&nbsp&nbsp&nbspmetadata: <i style=\"color: #666;\">new metadata</i>,<br/>&nbsp&nbsp&nbspmsgType: <i style=\"color: #666;\">new msgType</i> }</code><br/>" +
39 "All fields in resulting object are optional and will be taken from original message if not specified.", 39 "All fields in resulting object are optional and will be taken from original message if not specified.",
40 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, 40 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
41 - configDirective = "tbTransformationNodeScriptConfig",  
42 - ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE} 41 + configDirective = "tbTransformationNodeScriptConfig"
43 ) 42 )
44 public class TbTransformMsgNode extends TbAbstractTransformNode { 43 public class TbTransformMsgNode extends TbAbstractTransformNode {
45 44
@@ -1180,7 +1180,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time @@ -1180,7 +1180,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
1180 var saveRuleChainPromise; 1180 var saveRuleChainPromise;
1181 if (vm.isImport) { 1181 if (vm.isImport) {
1182 if (angular.isUndefined(vm.ruleChain.type)) { 1182 if (angular.isUndefined(vm.ruleChain.type)) {
1183 - vm.ruleChain.type = types.systemRuleChainType; 1183 + vm.ruleChain.type = types.coreRuleChainType;
1184 } 1184 }
1185 saveRuleChainPromise = ruleChainService.saveRuleChain(vm.ruleChain); 1185 saveRuleChainPromise = ruleChainService.saveRuleChain(vm.ruleChain);
1186 } else { 1186 } else {
@@ -1269,7 +1269,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time @@ -1269,7 +1269,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
1269 vm.isDirty = false; 1269 vm.isDirty = false;
1270 vm.isImport = false; 1270 vm.isImport = false;
1271 $mdUtil.nextTick(() => { 1271 $mdUtil.nextTick(() => {
1272 - if (vm.ruleChain.type === vm.types.systemRuleChainType) { 1272 + if (vm.ruleChain.type === vm.types.coreRuleChainType) {
1273 $state.go('home.ruleChains.core.ruleChain', {ruleChainId: vm.ruleChain.id.id}); 1273 $state.go('home.ruleChains.core.ruleChain', {ruleChainId: vm.ruleChain.id.id});
1274 } else { 1274 } else {
1275 $state.go('home.ruleChains.edge.ruleChain', {ruleChainId: vm.ruleChain.id.id}); 1275 $state.go('home.ruleChains.edge.ruleChain', {ruleChainId: vm.ruleChain.id.id});
@@ -1293,7 +1293,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time @@ -1293,7 +1293,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
1293 ruleNode.configuration = angular.copy(ruleNode.component.configurationDescriptor.nodeDefinition.defaultConfiguration); 1293 ruleNode.configuration = angular.copy(ruleNode.component.configurationDescriptor.nodeDefinition.defaultConfiguration);
1294 1294
1295 var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null; 1295 var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null;
1296 - var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.systemRuleChainType; 1296 + var ruleChainType = vm.ruleChain.type ? vm.ruleChain.type : types.coreRuleChainType;
1297 1297
1298 vm.enableHotKeys = false; 1298 vm.enableHotKeys = false;
1299 1299
@@ -82,7 +82,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider @@ -82,7 +82,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider
82 ruleNodeComponents: 82 ruleNodeComponents:
83 /*@ngInject*/ 83 /*@ngInject*/
84 function($stateParams, ruleChainService) { 84 function($stateParams, ruleChainService) {
85 - return ruleChainService.getRuleNodeComponents(types.systemRuleChainType); 85 + return ruleChainService.getRuleNodeComponents(types.coreRuleChainType);
86 } 86 }
87 }, 87 },
88 data: { 88 data: {
@@ -114,7 +114,7 @@ export default function RuleChainsController(ruleChainService, userService, edge @@ -114,7 +114,7 @@ export default function RuleChainsController(ruleChainService, userService, edge
114 114
115 if (vm.ruleChainsScope === 'tenant') { 115 if (vm.ruleChainsScope === 'tenant') {
116 fetchRuleChainsFunction = function (pageLink) { 116 fetchRuleChainsFunction = function (pageLink) {
117 - return fetchRuleChains(pageLink, types.systemRuleChainType); 117 + return fetchRuleChains(pageLink, types.coreRuleChainType);
118 }; 118 };
119 deleteRuleChainFunction = function (ruleChainId) { 119 deleteRuleChainFunction = function (ruleChainId) {
120 return deleteRuleChain(ruleChainId); 120 return deleteRuleChain(ruleChainId);
@@ -162,9 +162,9 @@ export default function RuleChainsController(ruleChainService, userService, edge @@ -162,9 +162,9 @@ export default function RuleChainsController(ruleChainService, userService, edge
162 }); 162 });
163 vm.ruleChainGridConfig.addItemActions.push({ 163 vm.ruleChainGridConfig.addItemActions.push({
164 onAction: function ($event) { 164 onAction: function ($event) {
165 - importExport.importRuleChain($event, types.systemRuleChainType).then( 165 + importExport.importRuleChain($event, types.coreRuleChainType).then(
166 function(ruleChainImport) { 166 function(ruleChainImport) {
167 - $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.systemRuleChainType}); 167 + $state.go('home.ruleChains.importRuleChain', {ruleChainImport:ruleChainImport, ruleChainType: types.coreRuleChainType});
168 } 168 }
169 ); 169 );
170 }, 170 },
@@ -385,7 +385,7 @@ export default function RuleChainsController(ruleChainService, userService, edge @@ -385,7 +385,7 @@ export default function RuleChainsController(ruleChainService, userService, edge
385 if (vm.ruleChainsScope === 'edges') { 385 if (vm.ruleChainsScope === 'edges') {
386 ruleChain.type = types.edgeRuleChainType; 386 ruleChain.type = types.edgeRuleChainType;
387 } else { 387 } else {
388 - ruleChain.type = types.systemRuleChainType; 388 + ruleChain.type = types.coreRuleChainType;
389 } 389 }
390 } 390 }
391 return ruleChainService.saveRuleChain(ruleChain); 391 return ruleChainService.saveRuleChain(ruleChain);