Commit cd2908fb59ec4628429adae6684809d3f40d9de1

Authored by Volodymyr Babak
1 parent 600c9ec5

Refactoring notification engine

Showing 100 changed files with 1315 additions and 307 deletions

Too many changes to show.

To preserve performance only 100 of 110 files are displayed.

... ... @@ -58,6 +58,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
58 58 import org.thingsboard.server.dao.dashboard.DashboardService;
59 59 import org.thingsboard.server.dao.device.ClaimDevicesService;
60 60 import org.thingsboard.server.dao.device.DeviceService;
  61 +import org.thingsboard.server.dao.edge.EdgeEventService;
61 62 import org.thingsboard.server.dao.edge.EdgeService;
62 63 import org.thingsboard.server.dao.entityview.EntityViewService;
63 64 import org.thingsboard.server.dao.event.EventService;
... ... @@ -258,6 +259,11 @@ public class ActorSystemContext {
258 259 @Getter
259 260 private EdgeService edgeService;
260 261
  262 + @Lazy
  263 + @Autowired
  264 + @Getter
  265 + private EdgeEventService edgeEventService;
  266 +
261 267 @Value("${actors.session.max_concurrent_sessions_per_device:1}")
262 268 @Getter
263 269 private long maxConcurrentSessionsPerDevice;
... ...
... ... @@ -51,6 +51,7 @@ import org.thingsboard.server.dao.cassandra.CassandraCluster;
51 51 import org.thingsboard.server.dao.customer.CustomerService;
52 52 import org.thingsboard.server.dao.dashboard.DashboardService;
53 53 import org.thingsboard.server.dao.device.DeviceService;
  54 +import org.thingsboard.server.dao.edge.EdgeEventService;
54 55 import org.thingsboard.server.dao.edge.EdgeService;
55 56 import org.thingsboard.server.dao.entityview.EntityViewService;
56 57 import org.thingsboard.server.dao.nosql.CassandraStatementTask;
... ... @@ -407,6 +408,11 @@ class DefaultTbContext implements TbContext {
407 408 }
408 409
409 410 @Override
  411 + public EdgeEventService getEdgeEventService() {
  412 + return mainCtx.getEdgeEventService();
  413 + }
  414 +
  415 + @Override
410 416 public EventLoopGroup getSharedEventLoop() {
411 417 return mainCtx.getSharedEventLoopGroupService().getSharedEventLoopGroup();
412 418 }
... ...
... ... @@ -18,14 +18,11 @@ package org.thingsboard.server.actors.ruleChain;
18 18 import akka.actor.ActorContext;
19 19 import akka.actor.ActorRef;
20 20 import akka.actor.Props;
21   -import com.google.common.util.concurrent.FutureCallback;
22   -import com.sun.istack.Nullable;
23 21 import lombok.extern.slf4j.Slf4j;
24 22 import org.thingsboard.rule.engine.api.TbRelationTypes;
25 23 import org.thingsboard.server.actors.ActorSystemContext;
26 24 import org.thingsboard.server.actors.service.DefaultActorService;
27 25 import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
28   -import org.thingsboard.server.common.data.DataConstants;
29 26 import org.thingsboard.server.common.data.EntityType;
30 27 import org.thingsboard.server.common.data.id.EntityId;
31 28 import org.thingsboard.server.common.data.id.RuleChainId;
... ... @@ -102,7 +99,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
102 99 if (!started) {
103 100 RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
104 101 if (ruleChain != null) {
105   - if (ruleChain.getType().equals(RuleChainType.SYSTEM)) {
  102 + if (ruleChain.getType().equals(RuleChainType.CORE)) {
106 103 List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
107 104 log.trace("[{}][{}] Starting rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
108 105 // Creating and starting the actors;
... ... @@ -124,7 +121,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
124 121 public void onUpdate(ActorContext context) {
125 122 RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
126 123 if (ruleChain != null) {
127   - if (ruleChain.getType().equals(RuleChainType.SYSTEM)) {
  124 + if (ruleChain.getType().equals(RuleChainType.CORE)) {
128 125 ruleChainName = ruleChain.getName();
129 126 List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
130 127 log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
... ... @@ -224,7 +221,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
224 221 if (targetCtx != null) {
225 222 log.trace("[{}][{}] Pushing message to target rule node", entityId, targetId);
226 223 pushMsgToNode(targetCtx, msg, "");
227   - pushUpdatesToEdges(msg);
228 224 } else {
229 225 log.trace("[{}][{}] Rule node does not exist. Probably old message", entityId, targetId);
230 226 msg.getCallback().onSuccess();
... ... @@ -354,30 +350,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
354 350 }
355 351 }
356 352
357   - private void pushUpdatesToEdges(TbMsg msg) {
358   - switch (msg.getType()) {
359   - case DataConstants.ENTITY_CREATED:
360   - case DataConstants.ENTITY_UPDATED:
361   - case DataConstants.ENTITY_DELETED:
362   - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
363   - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
364   - case DataConstants.ALARM_ACK:
365   - case DataConstants.ALARM_CLEAR:
366   - edgeService.pushEventToEdge(tenantId, msg, new FutureCallback<Void>() {
367   - @Override
368   - public void onSuccess(@Nullable Void aVoid) {
369   - log.debug("Event saved successfully!");
370   - }
371   -
372   - @Override
373   - public void onFailure(Throwable t) {
374   - log.debug("Failure during event save", t);
375   - }
376   - });
377   - }
378   -
379   - }
380   -
381 353 @Override
382 354 protected RuleNodeException getInactiveException() {
383 355 RuleNode firstRuleNode = firstNode != null ? firstNode.getSelf() : null;
... ...
... ... @@ -56,7 +56,7 @@ public abstract class RuleChainManagerActor extends ContextAwareActor {
56 56 }
57 57
58 58 protected void initRuleChains() {
59   - for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, link), ContextAwareActor.ENTITY_PACK_LIMIT)) {
  59 + for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, link), ContextAwareActor.ENTITY_PACK_LIMIT)) {
60 60 RuleChainId ruleChainId = ruleChain.getId();
61 61 log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId());
62 62 //TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa.
... ... @@ -67,7 +67,7 @@ public abstract class RuleChainManagerActor extends ContextAwareActor {
67 67 }
68 68
69 69 protected void visit(RuleChain entity, ActorRef actorRef) {
70   - if (entity != null && entity.isRoot() && entity.getType().equals(RuleChainType.SYSTEM)) {
  70 + if (entity != null && entity.isRoot() && entity.getType().equals(RuleChainType.CORE)) {
71 71 rootChain = entity;
72 72 rootChainActor = actorRef;
73 73 }
... ...
... ... @@ -206,7 +206,7 @@ public class TenantActor extends RuleChainManagerActor {
206 206 if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) {
207 207 RuleChain ruleChain = systemContext.getRuleChainService().
208 208 findRuleChainById(tenantId, new RuleChainId(msg.getEntityId().getId()));
209   - if (ruleChain != null && ruleChain.getType().equals(RuleChainType.SYSTEM)) {
  209 + if (ruleChain != null && ruleChain.getType().equals(RuleChainType.CORE)) {
210 210 visit(ruleChain, target);
211 211 }
212 212 }
... ...
... ... @@ -125,6 +125,8 @@ public class AlarmController extends BaseController {
125 125 alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, ackTs).get();
126 126 alarm.setAckTs(ackTs);
127 127 logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null);
  128 +
  129 + sendNotificationMsgToEdgeService(getTenantId(), alarmId, ActionType.ALARM_ACK);
128 130 } catch (Exception e) {
129 131 throw handleException(e);
130 132 }
... ... @@ -142,6 +144,8 @@ public class AlarmController extends BaseController {
142 144 alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, clearTs).get();
143 145 alarm.setClearTs(clearTs);
144 146 logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null);
  147 +
  148 + sendNotificationMsgToEdgeService(getTenantId(), alarmId, ActionType.ALARM_CLEAR);
145 149 } catch (Exception e) {
146 150 throw handleException(e);
147 151 }
... ...
... ... @@ -27,12 +27,14 @@ import org.springframework.web.bind.annotation.ResponseBody;
27 27 import org.springframework.web.bind.annotation.ResponseStatus;
28 28 import org.springframework.web.bind.annotation.RestController;
29 29 import org.thingsboard.server.common.data.Customer;
  30 +import org.thingsboard.server.common.data.DataConstants;
30 31 import org.thingsboard.server.common.data.EntitySubtype;
31 32 import org.thingsboard.server.common.data.EntityType;
32 33 import org.thingsboard.server.common.data.asset.Asset;
33 34 import org.thingsboard.server.common.data.asset.AssetSearchQuery;
34 35 import org.thingsboard.server.common.data.audit.ActionType;
35 36 import org.thingsboard.server.common.data.edge.Edge;
  37 +import org.thingsboard.server.common.data.edge.EdgeEventType;
36 38 import org.thingsboard.server.common.data.exception.ThingsboardException;
37 39 import org.thingsboard.server.common.data.id.AssetId;
38 40 import org.thingsboard.server.common.data.id.CustomerId;
... ... @@ -86,6 +88,8 @@ public class AssetController extends BaseController {
86 88
87 89 Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
88 90
  91 + sendNotificationMsgToEdgeService(savedAsset.getTenantId(), savedAsset.getId(), EdgeEventType.ASSET, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
  92 +
89 93 logEntityAction(savedAsset.getId(), savedAsset,
90 94 savedAsset.getCustomerId(),
91 95 asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
... ... @@ -112,6 +116,7 @@ public class AssetController extends BaseController {
112 116 asset.getCustomerId(),
113 117 ActionType.DELETED, null, strAssetId);
114 118
  119 + sendNotificationMsgToEdgeService(getTenantId(), assetId, EdgeEventType.ASSET, ActionType.DELETED);
115 120 } catch (Exception e) {
116 121 logEntityAction(emptyId(EntityType.ASSET),
117 122 null,
... ... @@ -354,6 +359,8 @@ public class AssetController extends BaseController {
354 359 savedAsset.getCustomerId(),
355 360 ActionType.ASSIGNED_TO_EDGE, null, strAssetId, strEdgeId, edge.getName());
356 361
  362 + sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(), EdgeEventType.ASSET, ActionType.ASSIGNED_TO_EDGE);
  363 +
357 364 return savedAsset;
358 365 } catch (Exception e) {
359 366
... ... @@ -385,6 +392,8 @@ public class AssetController extends BaseController {
385 392 asset.getCustomerId(),
386 393 ActionType.UNASSIGNED_FROM_EDGE, null, strAssetId, edge.getId().toString(), edge.getName());
387 394
  395 + sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(), EdgeEventType.ASSET, ActionType.UNASSIGNED_FROM_EDGE);
  396 +
388 397 return savedAsset;
389 398 } catch (Exception e) {
390 399
... ...
... ... @@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.HasTenantId;
39 39 import org.thingsboard.server.common.data.Tenant;
40 40 import org.thingsboard.server.common.data.User;
41 41 import org.thingsboard.server.common.data.alarm.Alarm;
  42 +import org.thingsboard.server.common.data.edge.EdgeEventType;
42 43 import org.thingsboard.server.common.data.id.AlarmId;
43 44 import org.thingsboard.server.common.data.alarm.AlarmInfo;
44 45 import org.thingsboard.server.common.data.asset.Asset;
... ... @@ -66,6 +67,7 @@ import org.thingsboard.server.common.data.page.TextPageLink;
66 67 import org.thingsboard.server.common.data.page.TimePageLink;
67 68 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
68 69 import org.thingsboard.server.common.data.plugin.ComponentType;
  70 +import org.thingsboard.server.common.data.relation.EntityRelation;
69 71 import org.thingsboard.server.common.data.rule.RuleChain;
70 72 import org.thingsboard.server.common.data.rule.RuleChainType;
71 73 import org.thingsboard.server.common.data.rule.RuleNode;
... ... @@ -83,6 +85,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
83 85 import org.thingsboard.server.dao.device.ClaimDevicesService;
84 86 import org.thingsboard.server.dao.device.DeviceCredentialsService;
85 87 import org.thingsboard.server.dao.device.DeviceService;
  88 +import org.thingsboard.server.dao.edge.EdgeEventService;
86 89 import org.thingsboard.server.dao.edge.EdgeService;
87 90 import org.thingsboard.server.dao.entityview.EntityViewService;
88 91 import org.thingsboard.server.dao.exception.DataValidationException;
... ... @@ -95,10 +98,12 @@ import org.thingsboard.server.dao.user.UserService;
95 98 import org.thingsboard.server.dao.widget.WidgetTypeService;
96 99 import org.thingsboard.server.dao.widget.WidgetsBundleService;
97 100 import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
  101 +import org.thingsboard.server.gen.transport.TransportProtos;
98 102 import org.thingsboard.server.queue.discovery.PartitionService;
99 103 import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
100 104 import org.thingsboard.server.queue.util.TbCoreComponent;
101 105 import org.thingsboard.server.service.component.ComponentDiscoveryService;
  106 +import org.thingsboard.server.service.edge.EdgeNotificationService;
102 107 import org.thingsboard.server.service.queue.TbClusterService;
103 108 import org.thingsboard.server.service.security.model.SecurityUser;
104 109 import org.thingsboard.server.service.security.permission.AccessControlService;
... ... @@ -108,6 +113,7 @@ import org.thingsboard.server.service.state.DeviceStateService;
108 113 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
109 114
110 115 import javax.mail.MessagingException;
  116 +import javax.management.relation.Relation;
111 117 import javax.servlet.http.HttpServletResponse;
112 118 import java.util.List;
113 119 import java.util.Optional;
... ... @@ -200,6 +206,12 @@ public abstract class BaseController {
200 206 @Autowired
201 207 protected EdgeService edgeService;
202 208
  209 + @Autowired
  210 + protected EdgeNotificationService edgeNotificationService;
  211 +
  212 + @Autowired
  213 + protected EdgeEventService edgeEventService;
  214 +
203 215 @Value("${server.log_controller_error_stack_trace}")
204 216 @Getter
205 217 private boolean logControllerErrorStackTrace;
... ... @@ -559,7 +571,6 @@ public abstract class BaseController {
559 571 }
560 572 if (e == null) {
561 573 pushEntityActionToRuleEngine(entityId, entity, user, customerId, actionType, additionalInfo);
562   - // TODO: voba - refactor to push events to edge queue directly, instead of the rule engine flow
563 574 }
564 575 auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo);
565 576 }
... ... @@ -600,16 +611,6 @@ public abstract class BaseController {
600 611 case ALARM_CLEAR:
601 612 msgType = DataConstants.ALARM_CLEAR;
602 613 break;
603   - case ASSIGNED_TO_EDGE:
604   - msgType = DataConstants.ENTITY_ASSIGNED_TO_EDGE;
605   - break;
606   - case UNASSIGNED_FROM_EDGE:
607   - msgType = DataConstants.ENTITY_UNASSIGNED_FROM_EDGE;
608   - break;
609   - case CREDENTIALS_UPDATED:
610   - //TODO: voba - this is not efficient way to do this. Refactor on later stages
611   - msgType = DataConstants.ENTITY_UPDATED;
612   - break;
613 614 }
614 615 if (!StringUtils.isEmpty(msgType)) {
615 616 try {
... ... @@ -698,5 +699,42 @@ public abstract class BaseController {
698 699 return result;
699 700 }
700 701
  702 + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) {
  703 + try {
  704 + sendNotificationMsgToEdgeService(tenantId, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction);
  705 + } catch (Exception e) {
  706 + log.warn("Failed to push relation to core: {}", relation, e);
  707 + }
  708 + }
  709 +
  710 + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) {
  711 + EdgeEventType edgeEventType = edgeEventService.getEdgeEventTypeByEntityType(entityId.getEntityType());
  712 + if (edgeEventType != null) {
  713 + sendNotificationMsgToEdgeService(tenantId, entityId, null, edgeEventType, edgeEventAction);
  714 + }
  715 + }
  716 +
  717 + protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, EdgeEventType edgeEventType, ActionType edgeEventAction) {
  718 + sendNotificationMsgToEdgeService(tenantId, entityId, null, edgeEventType, edgeEventAction);
  719 + }
  720 +
  721 + private void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, String entityBody, EdgeEventType edgeEventType, ActionType edgeEventAction) {
  722 + TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder();
  723 + builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits());
  724 + builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits());
  725 + builder.setEdgeEventType(edgeEventType.name());
  726 + builder.setEdgeEventAction(edgeEventAction.name());
  727 + if (entityId != null) {
  728 + builder.setEntityIdMSB(entityId.getId().getMostSignificantBits());
  729 + builder.setEntityIdLSB(entityId.getId().getLeastSignificantBits());
  730 + builder.setEntityType(entityId.getEntityType().name());
  731 + }
  732 + if (entityBody != null) {
  733 + builder.setEntityBody(entityBody);
  734 + }
  735 + TransportProtos.EdgeNotificationMsgProto msg = builder.build();
  736 + tbClusterService.pushMsgToCore(tenantId, entityId != null ? entityId : tenantId,
  737 + TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null);
  738 + }
701 739
702 740 }
... ...
... ... @@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.ShortCustomerInfo;
34 34 import org.thingsboard.server.common.data.ShortEdgeInfo;
35 35 import org.thingsboard.server.common.data.audit.ActionType;
36 36 import org.thingsboard.server.common.data.edge.Edge;
  37 +import org.thingsboard.server.common.data.edge.EdgeEventType;
37 38 import org.thingsboard.server.common.data.exception.ThingsboardException;
38 39 import org.thingsboard.server.common.data.id.CustomerId;
39 40 import org.thingsboard.server.common.data.id.DashboardId;
... ... @@ -116,6 +117,9 @@ public class DashboardController extends BaseController {
116 117 null,
117 118 dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
118 119
  120 + sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(),
  121 + EdgeEventType.DASHBOARD, savedDashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
  122 +
119 123 return savedDashboard;
120 124 } catch (Exception e) {
121 125 logEntityAction(emptyId(EntityType.DASHBOARD), dashboard,
... ... @@ -139,6 +143,7 @@ public class DashboardController extends BaseController {
139 143 null,
140 144 ActionType.DELETED, null, strDashboardId);
141 145
  146 + sendNotificationMsgToEdgeService(getTenantId(), dashboardId, EdgeEventType.DASHBOARD, ActionType.DELETED);
142 147 } catch (Exception e) {
143 148
144 149 logEntityAction(emptyId(EntityType.DASHBOARD),
... ... @@ -495,6 +500,7 @@ public class DashboardController extends BaseController {
495 500 null,
496 501 ActionType.ASSIGNED_TO_EDGE, null, strDashboardId, strEdgeId, edge.getName());
497 502
  503 + sendNotificationMsgToEdgeService(getTenantId(), savedDashboard.getId(), EdgeEventType.DASHBOARD, ActionType.ASSIGNED_TO_EDGE);
498 504
499 505 return savedDashboard;
500 506 } catch (Exception e) {
... ... @@ -526,6 +532,8 @@ public class DashboardController extends BaseController {
526 532 null,
527 533 ActionType.UNASSIGNED_FROM_EDGE, null, strDashboardId, edge.getId().toString(), edge.getName());
528 534
  535 + sendNotificationMsgToEdgeService(getTenantId(), savedDashboard.getId(), EdgeEventType.DASHBOARD, ActionType.UNASSIGNED_FROM_EDGE);
  536 +
529 537 return savedDashboard;
530 538 } catch (Exception e) {
531 539
... ...
... ... @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.EntityType;
42 42 import org.thingsboard.server.common.data.audit.ActionType;
43 43 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
44 44 import org.thingsboard.server.common.data.edge.Edge;
  45 +import org.thingsboard.server.common.data.edge.EdgeEventType;
45 46 import org.thingsboard.server.common.data.exception.ThingsboardException;
46 47 import org.thingsboard.server.common.data.id.CustomerId;
47 48 import org.thingsboard.server.common.data.id.DeviceId;
... ... @@ -57,6 +58,7 @@ import org.thingsboard.server.dao.device.claim.ClaimResponse;
57 58 import org.thingsboard.server.dao.device.claim.ClaimResult;
58 59 import org.thingsboard.server.dao.exception.IncorrectParameterException;
59 60 import org.thingsboard.server.dao.model.ModelConstants;
  61 +import org.thingsboard.server.gen.transport.TransportProtos;
60 62 import org.thingsboard.server.queue.util.TbCoreComponent;
61 63 import org.thingsboard.server.service.security.model.SecurityUser;
62 64 import org.thingsboard.server.service.security.permission.Operation;
... ... @@ -106,6 +108,8 @@ public class DeviceController extends BaseController {
106 108 tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(),
107 109 savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null);
108 110
  111 + sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(), EdgeEventType.DEVICE, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
  112 +
109 113 logEntityAction(savedDevice.getId(), savedDevice,
110 114 savedDevice.getCustomerId(),
111 115 device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
... ... @@ -137,6 +141,8 @@ public class DeviceController extends BaseController {
137 141 device.getCustomerId(),
138 142 ActionType.DELETED, null, strDeviceId);
139 143
  144 + sendNotificationMsgToEdgeService(getTenantId(), deviceId, EdgeEventType.DEVICE, ActionType.DELETED);
  145 +
140 146 deviceStateService.onDeviceDeleted(device);
141 147 } catch (Exception e) {
142 148 logEntityAction(emptyId(EntityType.DEVICE),
... ... @@ -260,6 +266,8 @@ public class DeviceController extends BaseController {
260 266
261 267 tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null);
262 268
  269 + sendNotificationMsgToEdgeService(getTenantId(), device.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED);
  270 +
263 271 logEntityAction(device.getId(), device,
264 272 device.getCustomerId(),
265 273 ActionType.CREDENTIALS_UPDATED, null, deviceCredentials);
... ... @@ -509,6 +517,8 @@ public class DeviceController extends BaseController {
509 517 savedDevice.getCustomerId(),
510 518 ActionType.ASSIGNED_TO_EDGE, null, strDeviceId, strEdgeId, edge.getName());
511 519
  520 + sendNotificationMsgToEdgeService(getTenantId(), savedDevice.getId(), EdgeEventType.DEVICE, ActionType.ASSIGNED_TO_EDGE);
  521 +
512 522 return savedDevice;
513 523 } catch (Exception e) {
514 524 logEntityAction(emptyId(EntityType.DEVICE), null,
... ... @@ -538,6 +548,8 @@ public class DeviceController extends BaseController {
538 548 device.getCustomerId(),
539 549 ActionType.UNASSIGNED_FROM_EDGE, null, strDeviceId, edge.getId().toString(), edge.getName());
540 550
  551 + sendNotificationMsgToEdgeService(getTenantId(), savedDevice.getId(), EdgeEventType.DEVICE, ActionType.UNASSIGNED_FROM_EDGE);
  552 +
541 553 return savedDevice;
542 554 } catch (Exception e) {
543 555 logEntityAction(emptyId(EntityType.DEVICE), null,
... ...
... ... @@ -97,7 +97,7 @@ public class EdgeController extends BaseController {
97 97
98 98 if (created) {
99 99 ruleChainService.assignRuleChainToEdge(tenantId, defaultRootEdgeRuleChain.getId(), savedEdge.getId());
100   - edgeService.setEdgeRootRuleChain(tenantId, savedEdge, defaultRootEdgeRuleChain.getId());
  100 + edgeNotificationService.setEdgeRootRuleChain(tenantId, savedEdge, defaultRootEdgeRuleChain.getId());
101 101 edgeService.assignDefaultRuleChainsToEdge(tenantId, savedEdge.getId());
102 102 }
103 103
... ... @@ -257,8 +257,7 @@ public class EdgeController extends BaseController {
257 257 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
258 258 @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET)
259 259 @ResponseBody
260   - public Edge getTenantEdge(
261   - @RequestParam String edgeName) throws ThingsboardException {
  260 + public Edge getTenantEdge(@RequestParam String edgeName) throws ThingsboardException {
262 261 try {
263 262 TenantId tenantId = getCurrentUser().getTenantId();
264 263 return checkNotNull(edgeService.findEdgeByTenantIdAndName(tenantId, edgeName));
... ... @@ -283,7 +282,7 @@ public class EdgeController extends BaseController {
283 282 accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.WRITE,
284 283 edge.getId(), edge);
285 284
286   - Edge updatedEdge = edgeService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId);
  285 + Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId);
287 286
288 287 logEntityAction(updatedEdge.getId(), updatedEdge, null, ActionType.UPDATED, null);
289 288
... ...
... ... @@ -24,7 +24,9 @@ import org.springframework.web.bind.annotation.RequestParam;
24 24 import org.springframework.web.bind.annotation.ResponseBody;
25 25 import org.springframework.web.bind.annotation.ResponseStatus;
26 26 import org.springframework.web.bind.annotation.RestController;
  27 +import org.thingsboard.server.common.data.DataConstants;
27 28 import org.thingsboard.server.common.data.audit.ActionType;
  29 +import org.thingsboard.server.common.data.edge.EdgeEventType;
28 30 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
29 31 import org.thingsboard.server.common.data.exception.ThingsboardException;
30 32 import org.thingsboard.server.common.data.id.EntityId;
... ... @@ -63,10 +65,13 @@ public class EntityRelationController extends BaseController {
63 65 relation.setTypeGroup(RelationTypeGroup.COMMON);
64 66 }
65 67 relationService.saveRelation(getTenantId(), relation);
  68 +
66 69 logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
67 70 ActionType.RELATION_ADD_OR_UPDATE, null, relation);
68 71 logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
69 72 ActionType.RELATION_ADD_OR_UPDATE, null, relation);
  73 +
  74 + sendNotificationMsgToEdgeService(getTenantId(), relation, ActionType.RELATION_ADD_OR_UPDATE);
70 75 } catch (Exception e) {
71 76 logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
72 77 ActionType.RELATION_ADD_OR_UPDATE, e, relation);
... ... @@ -104,6 +109,8 @@ public class EntityRelationController extends BaseController {
104 109 ActionType.RELATION_DELETED, null, relation);
105 110 logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
106 111 ActionType.RELATION_DELETED, null, relation);
  112 +
  113 + sendNotificationMsgToEdgeService(getTenantId(), relation, ActionType.RELATION_DELETED);
107 114 } catch (Exception e) {
108 115 logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
109 116 ActionType.RELATION_DELETED, e, relation);
... ... @@ -125,6 +132,8 @@ public class EntityRelationController extends BaseController {
125 132 try {
126 133 relationService.deleteEntityRelations(getTenantId(), entityId);
127 134 logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, null);
  135 +
  136 + sendNotificationMsgToEdgeService(getTenantId(), entityId, ActionType.RELATIONS_DELETED);
128 137 } catch (Exception e) {
129 138 logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, e);
130 139 throw handleException(e);
... ...
... ... @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.EntityType;
37 37 import org.thingsboard.server.common.data.EntityView;
38 38 import org.thingsboard.server.common.data.audit.ActionType;
39 39 import org.thingsboard.server.common.data.edge.Edge;
  40 +import org.thingsboard.server.common.data.edge.EdgeEventType;
40 41 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
41 42 import org.thingsboard.server.common.data.exception.ThingsboardException;
42 43 import org.thingsboard.server.common.data.id.CustomerId;
... ... @@ -116,6 +117,8 @@ public class EntityViewController extends BaseController {
116 117
117 118 logEntityAction(savedEntityView.getId(), savedEntityView, null,
118 119 entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  120 +
  121 + sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), EdgeEventType.ENTITY_VIEW, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
119 122 return savedEntityView;
120 123 } catch (Exception e) {
121 124 logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null,
... ... @@ -185,6 +188,8 @@ public class EntityViewController extends BaseController {
185 188 entityViewService.deleteEntityView(getTenantId(), entityViewId);
186 189 logEntityAction(entityViewId, entityView, entityView.getCustomerId(),
187 190 ActionType.DELETED, null, strEntityViewId);
  191 +
  192 + sendNotificationMsgToEdgeService(getTenantId(), entityViewId, EdgeEventType.ENTITY_VIEW, ActionType.DELETED);
188 193 } catch (Exception e) {
189 194 logEntityAction(emptyId(EntityType.ENTITY_VIEW),
190 195 null,
... ... @@ -389,6 +394,9 @@ public class EntityViewController extends BaseController {
389 394 logEntityAction(entityViewId, savedEntityView,
390 395 savedEntityView.getCustomerId(),
391 396 ActionType.ASSIGNED_TO_EDGE, null, strEntityViewId, strEdgeId, edge.getName());
  397 +
  398 + sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), EdgeEventType.ENTITY_VIEW, ActionType.ASSIGNED_TO_EDGE);
  399 +
392 400 return savedEntityView;
393 401 } catch (Exception e) {
394 402 logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
... ... @@ -417,6 +425,8 @@ public class EntityViewController extends BaseController {
417 425 entityView.getCustomerId(),
418 426 ActionType.UNASSIGNED_FROM_EDGE, null, strEntityViewId, edge.getId().toString(), edge.getName());
419 427
  428 + sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), EdgeEventType.ENTITY_VIEW, ActionType.UNASSIGNED_FROM_EDGE);
  429 +
420 430 return savedEntityView;
421 431 } catch (Exception e) {
422 432 logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
... ...
... ... @@ -41,6 +41,7 @@ import org.thingsboard.server.common.data.EntityType;
41 41 import org.thingsboard.server.common.data.Event;
42 42 import org.thingsboard.server.common.data.audit.ActionType;
43 43 import org.thingsboard.server.common.data.edge.Edge;
  44 +import org.thingsboard.server.common.data.edge.EdgeEventType;
44 45 import org.thingsboard.server.common.data.exception.ThingsboardException;
45 46 import org.thingsboard.server.common.data.id.EdgeId;
46 47 import org.thingsboard.server.common.data.id.RuleChainId;
... ... @@ -134,7 +135,7 @@ public class RuleChainController extends BaseController {
134 135
135 136 RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
136 137
137   - if (RuleChainType.SYSTEM.equals(savedRuleChain.getType())) {
  138 + if (RuleChainType.CORE.equals(savedRuleChain.getType())) {
138 139 tbClusterService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(),
139 140 created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
140 141 }
... ... @@ -143,6 +144,12 @@ public class RuleChainController extends BaseController {
143 144 null,
144 145 created ? ActionType.ADDED : ActionType.UPDATED, null);
145 146
  147 + if (RuleChainType.EDGE.equals(savedRuleChain.getType())) {
  148 + sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(),
  149 + savedRuleChain.getId(), EdgeEventType.RULE_CHAIN,
  150 + savedRuleChain.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
  151 + }
  152 +
146 153 return savedRuleChain;
147 154 } catch (Exception e) {
148 155
... ... @@ -209,7 +216,7 @@ public class RuleChainController extends BaseController {
209 216 RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE);
210 217 RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData));
211 218
212   - if (RuleChainType.SYSTEM.equals(ruleChain.getType())) {
  219 + if (RuleChainType.CORE.equals(ruleChain.getType())) {
213 220 tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);
214 221 }
215 222
... ... @@ -217,6 +224,12 @@ public class RuleChainController extends BaseController {
217 224 null,
218 225 ActionType.UPDATED, null, ruleChainMetaData);
219 226
  227 + if (RuleChainType.EDGE.equals(ruleChain.getType())) {
  228 + sendNotificationMsgToEdgeService(ruleChain.getTenantId(),
  229 + ruleChain.getId(), EdgeEventType.RULE_CHAIN,
  230 + ActionType.UPDATED);
  231 + }
  232 +
220 233 return savedRuleChainMetaData;
221 234 } catch (Exception e) {
222 235
... ... @@ -243,7 +256,7 @@ public class RuleChainController extends BaseController {
243 256 RuleChainType type = RuleChainType.valueOf(typeStr);
244 257 return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink));
245 258 } else {
246   - return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink));
  259 + return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink));
247 260 }
248 261 } catch (Exception e) {
249 262 throw handleException(e);
... ... @@ -267,7 +280,7 @@ public class RuleChainController extends BaseController {
267 280
268 281 referencingRuleChainIds.remove(ruleChain.getId());
269 282
270   - if (RuleChainType.SYSTEM.equals(ruleChain.getType())) {
  283 + if (RuleChainType.CORE.equals(ruleChain.getType())) {
271 284 referencingRuleChainIds.forEach(referencingRuleChainId ->
272 285 tbClusterService.onEntityStateChange(ruleChain.getTenantId(), referencingRuleChainId, ComponentLifecycleEvent.UPDATED));
273 286
... ... @@ -278,6 +291,12 @@ public class RuleChainController extends BaseController {
278 291 null,
279 292 ActionType.DELETED, null, strRuleChainId);
280 293
  294 + if (RuleChainType.EDGE.equals(ruleChain.getType())) {
  295 + sendNotificationMsgToEdgeService(ruleChain.getTenantId(),
  296 + ruleChain.getId(), EdgeEventType.RULE_CHAIN,
  297 + ActionType.DELETED);
  298 + }
  299 +
281 300 } catch (Exception e) {
282 301 logEntityAction(emptyId(EntityType.RULE_CHAIN),
283 302 null,
... ... @@ -407,6 +426,8 @@ public class RuleChainController extends BaseController {
407 426 null,
408 427 ActionType.ASSIGNED_TO_EDGE, null, strRuleChainId, strEdgeId, edge.getName());
409 428
  429 + sendNotificationMsgToEdgeService(getTenantId(), savedRuleChain.getId(),
  430 + EdgeEventType.RULE_CHAIN, ActionType.ASSIGNED_TO_EDGE);
410 431
411 432 return savedRuleChain;
412 433 } catch (Exception e) {
... ... @@ -438,6 +459,9 @@ public class RuleChainController extends BaseController {
438 459 null,
439 460 ActionType.UNASSIGNED_FROM_EDGE, null, strRuleChainId, edge.getId().toString(), edge.getName());
440 461
  462 + sendNotificationMsgToEdgeService(getTenantId(), savedRuleChain.getId(),
  463 + EdgeEventType.RULE_CHAIN, ActionType.UNASSIGNED_FROM_EDGE);
  464 +
441 465 return savedRuleChain;
442 466 } catch (Exception e) {
443 467
... ...
... ... @@ -116,7 +116,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
116 116 }
117 117
118 118 private void putComponentIntoMaps(ComponentType type, RuleNode ruleNodeAnnotation, ComponentDescriptor component) {
119   - if (ruleChainTypeContainsArray(RuleChainType.SYSTEM, ruleNodeAnnotation.ruleChainTypes())) {
  119 + if (ruleChainTypeContainsArray(RuleChainType.CORE, ruleNodeAnnotation.ruleChainTypes())) {
120 120 systemComponentsMap.computeIfAbsent(type, k -> new ArrayList<>()).add(component);
121 121 }
122 122 if (ruleChainTypeContainsArray(RuleChainType.EDGE, ruleNodeAnnotation.ruleChainTypes())) {
... ... @@ -225,7 +225,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
225 225
226 226 @Override
227 227 public List<ComponentDescriptor> getComponents(Set<ComponentType> types, RuleChainType ruleChainType) {
228   - if (RuleChainType.SYSTEM.equals(ruleChainType)) {
  228 + if (RuleChainType.CORE.equals(ruleChainType)) {
229 229 return getComponents(types, systemComponentsMap);
230 230 } else if (RuleChainType.EDGE.equals(ruleChainType)) {
231 231 return getComponents(types, edgeComponentsMap);
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
1 16 package org.thingsboard.server.service.edge;
2 17
3 18 import com.fasterxml.jackson.databind.ObjectMapper;
... ... @@ -17,9 +32,10 @@ import org.thingsboard.server.common.data.EntityView;
17 32 import org.thingsboard.server.common.data.Event;
18 33 import org.thingsboard.server.common.data.alarm.Alarm;
19 34 import org.thingsboard.server.common.data.asset.Asset;
  35 +import org.thingsboard.server.common.data.audit.ActionType;
20 36 import org.thingsboard.server.common.data.edge.Edge;
21   -import org.thingsboard.server.common.data.edge.EdgeQueueEntityType;
22   -import org.thingsboard.server.common.data.edge.EdgeQueueEntry;
  37 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  38 +import org.thingsboard.server.common.data.edge.EdgeEventType;
23 39 import org.thingsboard.server.common.data.id.EdgeId;
24 40 import org.thingsboard.server.common.data.id.EntityId;
25 41 import org.thingsboard.server.common.data.id.RuleChainId;
... ... @@ -36,6 +52,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback;
36 52 import org.thingsboard.server.common.msg.session.SessionMsgType;
37 53 import org.thingsboard.server.dao.asset.AssetService;
38 54 import org.thingsboard.server.dao.device.DeviceService;
  55 +import org.thingsboard.server.dao.edge.EdgeEventService;
39 56 import org.thingsboard.server.dao.edge.EdgeService;
40 57 import org.thingsboard.server.dao.entityview.EntityViewService;
41 58 import org.thingsboard.server.dao.event.EventService;
... ... @@ -79,7 +96,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
79 96 private RelationService relationService;
80 97
81 98 @Autowired
82   - private EventService eventService;
  99 + private EdgeEventService edgeEventService;
83 100
84 101 private ExecutorService tsCallBackExecutor;
85 102
... ... @@ -96,8 +113,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
96 113 }
97 114
98 115 @Override
99   - public TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
100   - return eventService.findEvents(tenantId, edgeId, DataConstants.EDGE_QUEUE_EVENT_TYPE, pageLink);
  116 + public TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
  117 + return edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink);
101 118 }
102 119
103 120 @Override
... ... @@ -105,7 +122,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
105 122 edge.setRootRuleChainId(ruleChainId);
106 123 Edge savedEdge = edgeService.saveEdge(edge);
107 124 RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId);
108   - saveEventToEdgeQueue(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, DataConstants.ENTITY_UPDATED, mapper.writeValueAsString(ruleChain), new FutureCallback<Void>() {
  125 + saveEventToEdgeQueue(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, DataConstants.ENTITY_UPDATED, mapper.writeValueAsString(ruleChain), new FutureCallback<Void>() {
109 126 @Override
110 127 public void onSuccess(@Nullable Void aVoid) {
111 128 log.debug("Event saved successfully!");
... ... @@ -119,28 +136,28 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
119 136 return savedEdge;
120 137 }
121 138
122   - private void saveEventToEdgeQueue(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, String type, String data, FutureCallback<Void> callback) throws IOException {
  139 + private void saveEventToEdgeQueue(TenantId tenantId, EdgeId edgeId, EdgeEventType entityType, String type, String data, FutureCallback<Void> callback) throws IOException {
123 140 log.debug("Pushing single event to edge queue. tenantId [{}], edgeId [{}], entityType [{}], type[{}], data [{}]", tenantId, edgeId, entityType, type, data);
124 141
125   - EdgeQueueEntry queueEntry = new EdgeQueueEntry();
126   - queueEntry.setEntityType(entityType);
127   - queueEntry.setType(type);
128   - queueEntry.setData(data);
  142 +// EdgeEQueueEntry queueEntry = new EdgeQueueEntry();
  143 +// queueEntry.setEntityType(entityType);
  144 +// queueEntry.setType(type);
  145 +// queueEntry.setData(data);
129 146
130   - Event event = new Event();
131   - event.setEntityId(edgeId);
132   - event.setTenantId(tenantId);
133   - event.setType(DataConstants.EDGE_QUEUE_EVENT_TYPE);
134   - event.setBody(mapper.valueToTree(queueEntry));
135   - ListenableFuture<Event> saveFuture = eventService.saveAsync(event);
  147 + EdgeEvent edgeEvent = new EdgeEvent();
  148 + edgeEvent.setEdgeId(edgeId);
  149 + edgeEvent.setTenantId(tenantId);
  150 +// event.setType(DataConstants.EDGE_QUEUE_EVENT_TYPE);
  151 +// event.setBody(mapper.valueToTree(queueEntry));
  152 + ListenableFuture<EdgeEvent> saveFuture = edgeEventService.saveAsync(edgeEvent);
136 153
137 154 addMainCallback(saveFuture, callback);
138 155 }
139 156
140   - private void addMainCallback(ListenableFuture<Event> saveFuture, final FutureCallback<Void> callback) {
141   - Futures.addCallback(saveFuture, new FutureCallback<Event>() {
  157 + private void addMainCallback(ListenableFuture<EdgeEvent> saveFuture, final FutureCallback<Void> callback) {
  158 + Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
142 159 @Override
143   - public void onSuccess(@Nullable Event result) {
  160 + public void onSuccess(@Nullable EdgeEvent result) {
144 161 callback.onSuccess(null);
145 162 }
146 163
... ... @@ -153,52 +170,52 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
153 170
154 171 @Override
155 172 public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) {
156   - if (tbMsg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) ||
157   - tbMsg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
158   - tbMsg.getType().equals(DataConstants.ATTRIBUTES_UPDATED) ||
159   - tbMsg.getType().equals(DataConstants.ATTRIBUTES_DELETED)) {
160   - processCustomTbMsg(tenantId, tbMsg, callback);
161   - } else {
162   - try {
163   - switch (tbMsg.getOriginator().getEntityType()) {
164   - case EDGE:
165   - processEdge(tenantId, tbMsg, callback);
166   - break;
167   - case ASSET:
168   - processAsset(tenantId, tbMsg, callback);
169   - break;
170   - case DEVICE:
171   - processDevice(tenantId, tbMsg, callback);
172   - break;
173   - case DASHBOARD:
174   - processDashboard(tenantId, tbMsg, callback);
175   - break;
176   - case RULE_CHAIN:
177   - processRuleChain(tenantId, tbMsg, callback);
178   - break;
179   - case ENTITY_VIEW:
180   - processEntityView(tenantId, tbMsg, callback);
181   - break;
182   - case ALARM:
183   - processAlarm(tenantId, tbMsg, callback);
184   - break;
185   - default:
186   - log.debug("Entity type [{}] is not designed to be pushed to edge", tbMsg.getOriginator().getEntityType());
187   - }
188   - } catch (IOException e) {
189   - log.error("Can't push to edge updates, entity type [{}], data [{}]", tbMsg.getOriginator().getEntityType(), tbMsg.getData(), e);
190   - }
191   - }
  173 +// if (tbMsg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) ||
  174 +// tbMsg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
  175 +// tbMsg.getType().equals(DataConstants.ATTRIBUTES_UPDATED) ||
  176 +// tbMsg.getType().equals(DataConstants.ATTRIBUTES_DELETED)) {
  177 +// processCustomTbMsg(tenantId, tbMsg, callback);
  178 +// } else {
  179 +// try {
  180 +// switch (tbMsg.getOriginator().getEntityType()) {
  181 +// case EDGE:
  182 +// processEdge(tenantId, tbMsg, callback);
  183 +// break;
  184 +// case ASSET:
  185 +// processAsset(tenantId, tbMsg, callback);
  186 +// break;
  187 +// case DEVICE:
  188 +// processDevice(tenantId, tbMsg, callback);
  189 +// break;
  190 +// case DASHBOARD:
  191 +// processDashboard(tenantId, tbMsg, callback);
  192 +// break;
  193 +// case RULE_CHAIN:
  194 +// processRuleChain(tenantId, tbMsg, callback);
  195 +// break;
  196 +// case ENTITY_VIEW:
  197 +// processEntityView(tenantId, tbMsg, callback);
  198 +// break;
  199 +// case ALARM:
  200 +// processAlarm(tenantId, tbMsg, callback);
  201 +// break;
  202 +// default:
  203 +// log.debug("Entity type [{}] is not designed to be pushed to edge", tbMsg.getOriginator().getEntityType());
  204 +// }
  205 +// } catch (IOException e) {
  206 +// log.error("Can't push to edge updates, entity type [{}], data [{}]", tbMsg.getOriginator().getEntityType(), tbMsg.getData(), e);
  207 +// }
  208 +// }
192 209 }
193 210
194 211
195 212 private void processCustomTbMsg(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) {
196 213 ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, tbMsg.getOriginator());
197 214 Futures.transform(edgeIdFuture, edgeId -> {
198   - EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(tbMsg.getOriginator().getEntityType());
199   - if (edgeId != null && edgeQueueEntityType != null) {
  215 + EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(tbMsg.getOriginator().getEntityType());
  216 + if (edgeId != null && edgeEventType != null) {
200 217 try {
201   - saveEventToEdgeQueue(tenantId, edgeId, edgeQueueEntityType, tbMsg.getType(), Base64.encodeBase64String(TbMsg.toByteArray(tbMsg)), callback);
  218 + saveEventToEdgeQueue(tenantId, edgeId, edgeEventType, tbMsg.getType(), Base64.encodeBase64String(TbMsg.toByteArray(tbMsg)), callback);
202 219 } catch (IOException e) {
203 220 log.error("Error while saving custom tbMsg into Edge Queue", e);
204 221 }
... ... @@ -211,13 +228,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
211 228 switch (tbMsg.getType()) {
212 229 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
213 230 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
214   - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DEVICE, callback);
  231 + processAssignedEntity(tenantId, tbMsg, EdgeEventType.DEVICE, callback);
215 232 break;
216 233 case DataConstants.ENTITY_DELETED:
217 234 case DataConstants.ENTITY_CREATED:
218 235 case DataConstants.ENTITY_UPDATED:
219 236 Device device = mapper.readValue(tbMsg.getData(), Device.class);
220   - pushEventToEdge(tenantId, device.getId(), EdgeQueueEntityType.DEVICE, tbMsg, callback);
  237 + pushEventToEdge(tenantId, device.getId(), EdgeEventType.DEVICE, tbMsg, callback);
221 238 break;
222 239 default:
223 240 log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
... ... @@ -240,13 +257,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
240 257 switch (tbMsg.getType()) {
241 258 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
242 259 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
243   - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ASSET, callback);
  260 + processAssignedEntity(tenantId, tbMsg, EdgeEventType.ASSET, callback);
244 261 break;
245 262 case DataConstants.ENTITY_DELETED:
246 263 case DataConstants.ENTITY_CREATED:
247 264 case DataConstants.ENTITY_UPDATED:
248 265 Asset asset = mapper.readValue(tbMsg.getData(), Asset.class);
249   - pushEventToEdge(tenantId, asset.getId(), EdgeQueueEntityType.ASSET, tbMsg, callback);
  266 + pushEventToEdge(tenantId, asset.getId(), EdgeEventType.ASSET, tbMsg, callback);
250 267 break;
251 268 default:
252 269 log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
... ... @@ -257,13 +274,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
257 274 switch (tbMsg.getType()) {
258 275 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
259 276 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
260   - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ENTITY_VIEW, callback);
  277 + processAssignedEntity(tenantId, tbMsg, EdgeEventType.ENTITY_VIEW, callback);
261 278 break;
262 279 case DataConstants.ENTITY_DELETED:
263 280 case DataConstants.ENTITY_CREATED:
264 281 case DataConstants.ENTITY_UPDATED:
265 282 EntityView entityView = mapper.readValue(tbMsg.getData(), EntityView.class);
266   - pushEventToEdge(tenantId, entityView.getId(), EdgeQueueEntityType.ENTITY_VIEW, tbMsg, callback);
  283 + pushEventToEdge(tenantId, entityView.getId(), EdgeEventType.ENTITY_VIEW, tbMsg, callback);
267 284 break;
268 285 default:
269 286 log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
... ... @@ -278,9 +295,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
278 295 case DataConstants.ALARM_ACK:
279 296 case DataConstants.ALARM_CLEAR:
280 297 Alarm alarm = mapper.readValue(tbMsg.getData(), Alarm.class);
281   - EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType());
282   - if (edgeQueueEntityType != null) {
283   - pushEventToEdge(tenantId, alarm.getOriginator(), EdgeQueueEntityType.ALARM, tbMsg, callback);
  298 + EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType());
  299 + if (edgeEventType != null) {
  300 + pushEventToEdge(tenantId, alarm.getOriginator(), EdgeEventType.ALARM, tbMsg, callback);
284 301 }
285 302 break;
286 303 default:
... ... @@ -292,7 +309,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
292 309 switch (tbMsg.getType()) {
293 310 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
294 311 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
295   - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DASHBOARD, callback);
  312 + processAssignedEntity(tenantId, tbMsg, EdgeEventType.DASHBOARD, callback);
296 313 break;
297 314 case DataConstants.ENTITY_DELETED:
298 315 case DataConstants.ENTITY_CREATED:
... ... @@ -303,7 +320,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
303 320 if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {
304 321 try {
305 322 for (Edge edge : edges.getData()) {
306   - pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.DASHBOARD, tbMsg, callback);
  323 + pushEventToEdge(tenantId, edge.getId(), EdgeEventType.DASHBOARD, tbMsg, callback);
307 324 }
308 325 } catch (IOException e) {
309 326 log.error("Can't push event to edge", e);
... ... @@ -321,7 +338,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
321 338 switch (tbMsg.getType()) {
322 339 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
323 340 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
324   - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.RULE_CHAIN, callback);
  341 + processAssignedEntity(tenantId, tbMsg, EdgeEventType.RULE_CHAIN, callback);
325 342 break;
326 343 case DataConstants.ENTITY_DELETED:
327 344 case DataConstants.ENTITY_CREATED:
... ... @@ -333,7 +350,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
333 350 if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {
334 351 try {
335 352 for (Edge edge : edges.getData()) {
336   - pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, tbMsg, callback);
  353 + pushEventToEdge(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, tbMsg, callback);
337 354 }
338 355 } catch (IOException e) {
339 356 log.error("Can't push event to edge", e);
... ... @@ -349,7 +366,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
349 366 }
350 367
351 368
352   - private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeQueueEntityType entityType, FutureCallback<Void> callback) throws IOException {
  369 + private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeEventType entityType, FutureCallback<Void> callback) throws IOException {
353 370 EdgeId edgeId;
354 371 switch (tbMsg.getType()) {
355 372 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
... ... @@ -364,13 +381,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
364 381 }
365 382 }
366 383
367   -
368   - private void pushEventToEdge(TenantId tenantId, EntityId originatorId, EdgeQueueEntityType edgeQueueEntityType, TbMsg tbMsg, FutureCallback<Void> callback) {
  384 + private void pushEventToEdge(TenantId tenantId, EntityId originatorId, EdgeEventType edgeEventType, TbMsg tbMsg, FutureCallback<Void> callback) {
369 385 ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, originatorId);
370 386 Futures.transform(edgeIdFuture, edgeId -> {
371 387 if (edgeId != null) {
372 388 try {
373   - pushEventToEdge(tenantId, edgeId, edgeQueueEntityType, tbMsg, callback);
  389 + pushEventToEdge(tenantId, edgeId, edgeEventType, tbMsg, callback);
374 390 } catch (Exception e) {
375 391 log.error("Failed to push event to edge, edgeId [{}], tbMsg [{}]", edgeId, tbMsg, e);
376 392 }
... ... @@ -380,7 +396,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
380 396 MoreExecutors.directExecutor());
381 397 }
382 398
383   -
384 399 private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TenantId tenantId, EntityId originatorId) {
385 400 List<EntityRelation> originatorEdgeRelations = relationService.findByToAndType(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
386 401 if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) {
... ... @@ -391,12 +406,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
391 406 }
392 407
393 408
394   - private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  409 + private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, EdgeEventType entityType, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
395 410 log.debug("Pushing event(s) to edge queue. tenantId [{}], edgeId [{}], entityType [{}], tbMsg [{}]", tenantId, edgeId, entityType, tbMsg);
396 411
397 412 saveEventToEdgeQueue(tenantId, edgeId, entityType, tbMsg.getType(), tbMsg.getData(), callback);
398 413
399   - if (entityType.equals(EdgeQueueEntityType.RULE_CHAIN)) {
  414 + if (entityType.equals(EdgeEventType.RULE_CHAIN)) {
400 415 pushRuleChainMetadataToEdge(tenantId, edgeId, tbMsg, callback);
401 416 }
402 417 }
... ... @@ -408,7 +423,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
408 423 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
409 424 case DataConstants.ENTITY_UPDATED:
410 425 RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId());
411   - saveEventToEdgeQueue(tenantId, edgeId, EdgeQueueEntityType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData), callback);
  426 + saveEventToEdgeQueue(tenantId, edgeId, EdgeEventType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData), callback);
412 427 break;
413 428 default:
414 429 log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
... ... @@ -416,14 +431,14 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
416 431 }
417 432
418 433
419   - private EdgeQueueEntityType getEdgeQueueTypeByEntityType(EntityType entityType) {
  434 + private EdgeEventType getEdgeQueueTypeByEntityType(EntityType entityType) {
420 435 switch (entityType) {
421 436 case DEVICE:
422   - return EdgeQueueEntityType.DEVICE;
  437 + return EdgeEventType.DEVICE;
423 438 case ASSET:
424   - return EdgeQueueEntityType.ASSET;
  439 + return EdgeEventType.ASSET;
425 440 case ENTITY_VIEW:
426   - return EdgeQueueEntityType.ENTITY_VIEW;
  441 + return EdgeEventType.ENTITY_VIEW;
427 442 default:
428 443 log.info("Unsupported entity type: [{}]", entityType);
429 444 return null;
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
1 16 package org.thingsboard.server.service.edge;
2 17
3 18 import org.thingsboard.server.common.data.Event;
4 19 import org.thingsboard.server.common.data.edge.Edge;
  20 +import org.thingsboard.server.common.data.edge.EdgeEvent;
5 21 import org.thingsboard.server.common.data.id.EdgeId;
6 22 import org.thingsboard.server.common.data.id.RuleChainId;
7 23 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -14,7 +30,7 @@ import java.io.IOException;
14 30
15 31 public interface EdgeNotificationService {
16 32
17   - TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
  33 + TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
18 34
19 35 Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException;
20 36
... ...
... ... @@ -33,14 +33,14 @@ import org.thingsboard.server.common.data.DataConstants;
33 33 import org.thingsboard.server.common.data.Device;
34 34 import org.thingsboard.server.common.data.EntityType;
35 35 import org.thingsboard.server.common.data.EntityView;
36   -import org.thingsboard.server.common.data.Event;
37 36 import org.thingsboard.server.common.data.User;
38 37 import org.thingsboard.server.common.data.alarm.Alarm;
39 38 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
40 39 import org.thingsboard.server.common.data.alarm.AlarmStatus;
41 40 import org.thingsboard.server.common.data.asset.Asset;
  41 +import org.thingsboard.server.common.data.audit.ActionType;
42 42 import org.thingsboard.server.common.data.edge.Edge;
43   -import org.thingsboard.server.common.data.edge.EdgeQueueEntry;
  43 +import org.thingsboard.server.common.data.edge.EdgeEvent;
44 44 import org.thingsboard.server.common.data.id.AssetId;
45 45 import org.thingsboard.server.common.data.id.DeviceId;
46 46 import org.thingsboard.server.common.data.id.EdgeId;
... ... @@ -63,7 +63,6 @@ import org.thingsboard.server.common.msg.TbMsg;
63 63 import org.thingsboard.server.common.msg.TbMsgDataType;
64 64 import org.thingsboard.server.common.msg.TbMsgMetaData;
65 65 import org.thingsboard.server.common.msg.queue.TbMsgCallback;
66   -import org.thingsboard.server.common.msg.session.SessionMsgType;
67 66 import org.thingsboard.server.gen.edge.AlarmUpdateMsg;
68 67 import org.thingsboard.server.gen.edge.ConnectRequestMsg;
69 68 import org.thingsboard.server.gen.edge.ConnectResponseCode;
... ... @@ -169,36 +168,28 @@ public final class EdgeGrpcSession implements Closeable {
169 168 void processHandleMessages() throws ExecutionException, InterruptedException {
170 169 Long queueStartTs = getQueueStartTs().get();
171 170 TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true);
172   - TimePageData<Event> pageData;
  171 + TimePageData<EdgeEvent> pageData;
173 172 UUID ifOffset = null;
174 173 do {
175   - pageData = ctx.getEdgeNotificationService().findQueueEvents(edge.getTenantId(), edge.getId(), pageLink);
  174 + pageData = ctx.getEdgeNotificationService().findEdgeEvents(edge.getTenantId(), edge.getId(), pageLink);
176 175 if (isConnected() && !pageData.getData().isEmpty()) {
177 176 log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size());
178   - for (Event event : pageData.getData()) {
179   - log.trace("[{}] Processing event [{}]", this.sessionId, event);
  177 + for (EdgeEvent edgeEvent : pageData.getData()) {
  178 + log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent);
180 179 try {
181   - EdgeQueueEntry entry = objectMapper.treeToValue(event.getBody(), EdgeQueueEntry.class);
182   - UpdateMsgType msgType = getResponseMsgType(entry.getType());
183   - switch (msgType) {
184   - case ENTITY_DELETED_RPC_MESSAGE:
185   - case ENTITY_UPDATED_RPC_MESSAGE:
186   - case ENTITY_CREATED_RPC_MESSAGE:
187   - case ALARM_ACK_RPC_MESSAGE:
188   - case ALARM_CLEAR_RPC_MESSAGE:
189   - processEntityCRUDMessage(entry, msgType);
190   - break;
191   - case RULE_CHAIN_CUSTOM_MESSAGE:
192   - processCustomDownlinkMessage(entry);
193   - break;
  180 + UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction()));
  181 + if (msgType == null) {
  182 + processTelemetryMessage(edgeEvent);
  183 + } else {
  184 + processEntityCRUDMessage(edgeEvent, msgType);
194 185 }
195 186 if (ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) {
196   - pushEntityAttributesToEdge(entry);
  187 + pushEntityAttributesToEdge(edgeEvent);
197 188 }
198 189 } catch (Exception e) {
199 190 log.error("Exception during processing records from queue", e);
200 191 }
201   - ifOffset = event.getUuidId();
  192 + ifOffset = edgeEvent.getUuidId();
202 193 }
203 194 }
204 195 if (isConnected() && pageData.hasNext()) {
... ... @@ -222,10 +213,10 @@ public final class EdgeGrpcSession implements Closeable {
222 213 }
223 214 }
224 215
225   - private void pushEntityAttributesToEdge(EdgeQueueEntry entry) throws IOException {
  216 + private void pushEntityAttributesToEdge(EdgeEvent edgeEvent) throws IOException {
226 217 EntityId entityId = null;
227 218 String entityName = null;
228   - switch (entry.getEntityType()) {
  219 + switch (edgeEvent.getEdgeEventType()) {
229 220 case EDGE:
230 221 Edge edge = objectMapper.readValue(entry.getData(), Edge.class);
231 222 entityId = edge.getId();
... ... @@ -277,7 +268,7 @@ public final class EdgeGrpcSession implements Closeable {
277 268 , objectMapper.writeValueAsString(entityNode));
278 269 log.debug("Sending donwlink entity data msg, entityName [{}], tbMsg [{}]", finalEntityName, tbMsg);
279 270 outputStream.onNext(ResponseMsg.newBuilder()
280   - .setDownlinkMsg(constructDownlinkEntityDataMsg(finalEntityName, finalEntityId, tbMsg))
  271 + .setDownlinkMsg(constructEntityDataProtoMsg(finalEntityName, finalEntityId, tbMsg))
281 272 .build());
282 273 } catch (Exception e) {
283 274 log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e);
... ... @@ -290,12 +281,12 @@ public final class EdgeGrpcSession implements Closeable {
290 281 }
291 282 }
292 283
293   - private void processCustomDownlinkMessage(EdgeQueueEntry entry) throws IOException {
294   - log.trace("Executing processCustomDownlinkMessage, entry [{}]", entry);
  284 + private void processTelemetryMessage(EdgeEvent edgeEvent) throws IOException {
  285 + log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent);
295 286 TbMsg tbMsg = TbMsg.fromBytes(Base64.decodeBase64(entry.getData()), TbMsgCallback.EMPTY);
296 287 String entityName = null;
297 288 EntityId entityId = null;
298   - switch (entry.getEntityType()) {
  289 + switch (edgeEvent.getEdgeEventType()) {
299 290 case DEVICE:
300 291 Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), new DeviceId(tbMsg.getOriginator().getId()));
301 292 entityName = device.getName();
... ... @@ -316,14 +307,14 @@ public final class EdgeGrpcSession implements Closeable {
316 307 if (entityName != null && entityId != null) {
317 308 log.debug("Sending downlink entity data msg, entityName [{}], tbMsg [{}]", entityName, tbMsg);
318 309 outputStream.onNext(ResponseMsg.newBuilder()
319   - .setDownlinkMsg(constructDownlinkEntityDataMsg(entityName, entityId, tbMsg))
  310 + .setDownlinkMsg(constructEntityDataProtoMsg(entityName, entityId, tbMsg))
320 311 .build());
321 312 }
322 313 }
323 314
324   - private void processEntityCRUDMessage(EdgeQueueEntry entry, UpdateMsgType msgType) throws java.io.IOException {
325   - log.trace("Executing processEntityCRUDMessage, entry [{}], msgType [{}]", entry, msgType);
326   - switch (entry.getEntityType()) {
  315 + private void processEntityCRUDMessage(EdgeEvent edgeEvent, UpdateMsgType msgType) throws java.io.IOException {
  316 + log.trace("Executing processEntityCRUDMessage, edgeEvent [{}], msgType [{}]", edgeEvent, msgType);
  317 + switch (edgeEvent.getEdgeEventType()) {
327 318 case EDGE:
328 319 Edge edge = objectMapper.readValue(entry.getData(), Edge.class);
329 320 onEdgeUpdated(msgType, edge);
... ... @@ -476,33 +467,30 @@ public final class EdgeGrpcSession implements Closeable {
476 467 .build());
477 468 }
478 469
479   - private UpdateMsgType getResponseMsgType(String msgType) {
480   - if (msgType.equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) ||
481   - msgType.equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
482   - msgType.equals(DataConstants.ATTRIBUTES_UPDATED) ||
483   - msgType.equals(DataConstants.ATTRIBUTES_DELETED)) {
484   - return UpdateMsgType.RULE_CHAIN_CUSTOM_MESSAGE;
485   - } else {
486   - switch (msgType) {
487   - case DataConstants.ENTITY_UPDATED:
488   - return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE;
489   - case DataConstants.ENTITY_CREATED:
490   - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
491   - return ENTITY_CREATED_RPC_MESSAGE;
492   - case DataConstants.ENTITY_DELETED:
493   - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
494   - return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE;
495   - case DataConstants.ALARM_ACK:
496   - return UpdateMsgType.ALARM_ACK_RPC_MESSAGE;
497   - case DataConstants.ALARM_CLEAR:
498   - return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE;
499   - default:
500   - throw new RuntimeException("Unsupported msgType [" + msgType + "]");
501   - }
  470 + private UpdateMsgType getResponseMsgType(ActionType actionType) {
  471 + switch (actionType) {
  472 + case ADDED:
  473 + return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE;
  474 + case UPDATED:
  475 + case ASSIGNED_TO_EDGE:
  476 + return ENTITY_CREATED_RPC_MESSAGE;
  477 + case DELETED:
  478 + case UNASSIGNED_FROM_EDGE:
  479 + return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE;
  480 + case ALARM_ACK:
  481 + return UpdateMsgType.ALARM_ACK_RPC_MESSAGE;
  482 + case ALARM_CLEAR:
  483 + return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE;
  484 + case ATTRIBUTES_UPDATED:
  485 + case ATTRIBUTES_DELETED:
  486 + case TIMESERIES_DELETED:
  487 + return null;
  488 + default:
  489 + throw new RuntimeException("Unsupported actionType [" + actionType + "]");
502 490 }
503 491 }
504 492
505   - private DownlinkMsg constructDownlinkEntityDataMsg(String entityName, EntityId entityId, TbMsg tbMsg) {
  493 + private DownlinkMsg constructEntityDataProtoMsg(String entityName, EntityId entityId, TbMsg tbMsg) {
506 494 EntityDataProto entityData = EntityDataProto.newBuilder()
507 495 .setEntityName(entityName)
508 496 .setTbMsg(ByteString.copyFrom(TbMsg.toByteArray(tbMsg)))
... ...
... ... @@ -239,7 +239,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
239 239 schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.6.0", SCHEMA_UPDATE_SQL);
240 240 loadSql(schemaUpdateFile, conn);
241 241 try {
242   - conn.createStatement().execute("ALTER TABLE rule_chain ADD type varchar(255) DEFAULT 'SYSTEM'"); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
  242 + conn.createStatement().execute("ALTER TABLE rule_chain ADD type varchar(255) DEFAULT 'CORE'"); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
243 243 } catch (Exception e) {}
244 244 log.info("Schema updated.");
245 245 }
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.edge;
  17 +
  18 +import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.EntityType;
  20 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  21 +import org.thingsboard.server.common.data.edge.EdgeEventType;
  22 +import org.thingsboard.server.common.data.id.EdgeId;
  23 +import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.common.data.page.TimePageData;
  25 +import org.thingsboard.server.common.data.page.TimePageLink;
  26 +
  27 +public interface EdgeEventService {
  28 +
  29 + EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType);
  30 +
  31 + ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent);
  32 +
  33 + TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
  34 +
  35 +}
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ...
... ... @@ -65,7 +65,4 @@ public class DataConstants {
65 65 public static final String DEFAULT_SECRET_KEY = "";
66 66 public static final String SECRET_KEY_FIELD_NAME = "secretKey";
67 67 public static final String DURATION_MS_FIELD_NAME = "durationMs";
68   -
69   - public static final String EDGE_QUEUE_EVENT_TYPE = "EDGE_QUEUE";
70   -
71 68 }
... ...
... ... @@ -24,6 +24,7 @@ public enum ActionType {
24 24 UPDATED(false), // log entity
25 25 ATTRIBUTES_UPDATED(false), // log attributes/values
26 26 ATTRIBUTES_DELETED(false), // log attributes
  27 + TIMESERIES_UPDATED(false), // log timeseries
27 28 TIMESERIES_DELETED(false), // log timeseries
28 29 RPC_CALL(false), // log method and params
29 30 CREDENTIALS_UPDATED(false), // log new credentials
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.edge;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import lombok.Data;
  20 +import org.thingsboard.server.common.data.BaseData;
  21 +import org.thingsboard.server.common.data.id.EdgeEventId;
  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;
  25 +
  26 +import java.util.UUID;
  27 +
  28 +@Data
  29 +public class EdgeEvent extends BaseData<EdgeEventId> {
  30 +
  31 + private TenantId tenantId;
  32 + private EdgeId edgeId;
  33 + private String edgeEventAction;
  34 + private UUID entityId;
  35 + private EdgeEventType edgeEventType;
  36 + private transient JsonNode entityBody;
  37 +
  38 + public EdgeEvent() {
  39 + super();
  40 + }
  41 +
  42 + public EdgeEvent(EdgeEventId id) {
  43 + super(id);
  44 + }
  45 +
  46 + public EdgeEvent(EdgeEvent event) {
  47 + super(event);
  48 + }
  49 +
  50 +}
... ...
common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntityType.java
... ... @@ -15,6 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.common.data.edge;
17 17
18   -public enum EdgeQueueEntityType {
  18 +public enum EdgeEventType {
19 19 DASHBOARD, ASSET, DEVICE, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA, EDGE, USER, CUSTOMER, RELATION
20 20 }
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonCreator;
  19 +import com.fasterxml.jackson.annotation.JsonProperty;
  20 +
  21 +import java.util.UUID;
  22 +
  23 +public class EdgeEventId extends UUIDBased {
  24 +
  25 + private static final long serialVersionUID = 1L;
  26 +
  27 + @JsonCreator
  28 + public EdgeEventId(@JsonProperty("id") UUID id) {
  29 + super(id);
  30 + }
  31 +
  32 + public static EdgeEventId fromString(String edgeEventId) {
  33 + return new EdgeEventId(UUID.fromString(edgeEventId));
  34 + }
  35 +}
... ...
... ... @@ -16,5 +16,5 @@
16 16 package org.thingsboard.server.common.data.rule;
17 17
18 18 public enum RuleChainType {
19   - SYSTEM, EDGE
  19 + CORE, EDGE
20 20 }
... ...
... ... @@ -42,6 +42,10 @@
42 42 </dependency>
43 43 <dependency>
44 44 <groupId>org.thingsboard.common</groupId>
  45 + <artifactId>queue</artifactId>
  46 + </dependency>
  47 + <dependency>
  48 + <groupId>org.thingsboard.common</groupId>
45 49 <artifactId>message</artifactId>
46 50 </dependency>
47 51 <dependency>
... ...
... ... @@ -19,6 +19,8 @@ option java_package = "org.thingsboard.server.gen.edge";
19 19 option java_multiple_files = true;
20 20 option java_outer_classname = "EdgeProtos";
21 21
  22 +import "queue.proto";
  23 +
22 24 package edge;
23 25
24 26 // Interface exported by the ThingsBoard Edge Transport.
... ... @@ -94,15 +96,16 @@ enum UpdateMsgType {
94 96 ENTITY_DELETED_RPC_MESSAGE = 2;
95 97 ALARM_ACK_RPC_MESSAGE = 3;
96 98 ALARM_CLEAR_RPC_MESSAGE = 4;
97   - RULE_CHAIN_CUSTOM_MESSAGE = 5;
98   - DEVICE_CONFLICT_RPC_MESSAGE = 6;
  99 + DEVICE_CONFLICT_RPC_MESSAGE = 5;
99 100 }
100 101
101 102 message EntityDataProto {
102 103 string entityName = 1;
103 104 int64 entityIdMSB = 2;
104 105 int64 entityIdLSB = 3;
105   - bytes tbMsg = 4;
  106 + transport.PostTelemetryMsg postTelemetryMsg = 4;
  107 + transport.PostAttributeMsg postAttributesMsg = 5;
  108 + // transport.ToDeviceRpcRequestMsg ???
106 109 }
107 110
108 111 message RuleChainUpdateMsg {
... ...
... ... @@ -356,6 +356,14 @@ message FromDeviceRPCResponseProto {
356 356 message EdgeNotificationMsgProto {
357 357 int64 tenantIdMSB = 1;
358 358 int64 tenantIdLSB = 2;
  359 + string edgeEventType = 3;
  360 + string edgeEventAction = 4;
  361 + int64 entityIdMSB = 5;
  362 + int64 entityIdLSB = 6;
  363 + string entityType = 7;
  364 + string entityBody = 8;
  365 + PostTelemetryMsg postTelemetryMsg = 9;
  366 + PostAttributeMsg postAttributesMsg = 10;
359 367 }
360 368
361 369 /**
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.edge;
  17 +
  18 +import com.google.common.util.concurrent.ListenableFuture;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.apache.commons.lang3.StringUtils;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.stereotype.Service;
  23 +import org.thingsboard.server.common.data.EntityType;
  24 +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;
  27 +import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.page.TimePageData;
  29 +import org.thingsboard.server.common.data.page.TimePageLink;
  30 +import org.thingsboard.server.dao.exception.DataValidationException;
  31 +import org.thingsboard.server.dao.service.DataValidator;
  32 +
  33 +import java.util.List;
  34 +
  35 +@Service
  36 +@Slf4j
  37 +public class BaseEdgeEventService implements EdgeEventService {
  38 +
  39 + @Autowired
  40 + public EdgeEventDao edgeEventDao;
  41 +
  42 + @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 + default:
  56 + log.warn("Failed to push notification to edge service. Unsupported entity type [{}]", entityType);
  57 + return null;
  58 + }
  59 + }
  60 +
  61 + @Override
  62 + public ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent) {
  63 + edgeEventValidator.validate(edgeEvent, EdgeEvent::getTenantId);
  64 + return edgeEventDao.saveAsync(edgeEvent);
  65 + }
  66 +
  67 + @Override
  68 + public TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
  69 + List<EdgeEvent> events = edgeEventDao.findEdgeEvents(tenantId.getId(), edgeId, pageLink);
  70 + return new TimePageData<>(events, pageLink);
  71 + }
  72 +
  73 + private DataValidator<EdgeEvent> edgeEventValidator =
  74 + new DataValidator<EdgeEvent>() {
  75 + @Override
  76 + protected void validateDataImpl(TenantId tenantId, EdgeEvent edgeEvent) {
  77 + if (edgeEvent.getEdgeId() == null) {
  78 + throw new DataValidationException("Edge id should be specified!");
  79 + }
  80 + if (StringUtils.isEmpty(edgeEvent.getEdgeEventAction())) {
  81 + throw new DataValidationException("Edge Event action should be specified!");
  82 + }
  83 + }
  84 + };
  85 +}
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.edge;
  17 +
  18 +import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  20 +import org.thingsboard.server.common.data.id.EdgeId;
  21 +import org.thingsboard.server.common.data.page.TimePageLink;
  22 +import org.thingsboard.server.dao.Dao;
  23 +
  24 +import java.util.List;
  25 +import java.util.UUID;
  26 +
  27 +/**
  28 + * The Interface EdgeEventDao.
  29 + */
  30 +public interface EdgeEventDao extends Dao<EdgeEvent> {
  31 +
  32 + /**
  33 + * Save or update edge event object async
  34 + *
  35 + * @param edgeEvent the event object
  36 + * @return saved edge event object future
  37 + */
  38 + ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent);
  39 +
  40 +
  41 + /**
  42 + * Find edge events by tenantId, edgeId and pageLink.
  43 + *
  44 + * @param tenantId the tenantId
  45 + * @param edgeId the edgeId
  46 + * @param pageLink the pageLink
  47 + * @return the event list
  48 + */
  49 + List<EdgeEvent> findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink);
  50 +
  51 +}
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ...
... ... @@ -372,6 +372,16 @@ public class ModelConstants {
372 372 public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key";
373 373 public static final String EDGE_SECRET_PROPERTY = "secret";
374 374
  375 + /**
  376 + * Cassandra edge queue constants.
  377 + */
  378 + public static final String EDGE_EVENT_COLUMN_FAMILY_NAME = "edge_event";
  379 + public static final String EDGE_EVENT_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
  380 + public static final String EDGE_EVENT_EDGE_ID_PROPERTY = "edge_id";
  381 + public static final String EDGE_EVENT_TYPE_PROPERTY = "edge_event_type";
  382 + public static final String EDGE_EVENT_ACTION_PROPERTY = "edge_event_action";
  383 + public static final String EDGE_EVENT_ENTITY_ID_PROPERTY = "entity_id";
  384 + public static final String EDGE_EVENT_ENTITY_BODY_PROPERTY = "entity_body";
375 385
376 386 /**
377 387 * Cassandra attributes and timeseries constants.
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.nosql;
  17 +
  18 +import com.datastax.driver.core.utils.UUIDs;
  19 +import com.datastax.driver.mapping.annotations.ClusteringColumn;
  20 +import com.datastax.driver.mapping.annotations.Column;
  21 +import com.datastax.driver.mapping.annotations.PartitionKey;
  22 +import com.datastax.driver.mapping.annotations.Table;
  23 +import com.fasterxml.jackson.databind.JsonNode;
  24 +import lombok.Data;
  25 +import lombok.NoArgsConstructor;
  26 +import org.thingsboard.server.common.data.EntityType;
  27 +import org.thingsboard.server.common.data.Event;
  28 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  29 +import org.thingsboard.server.common.data.edge.EdgeEventType;
  30 +import org.thingsboard.server.common.data.id.EdgeEventId;
  31 +import org.thingsboard.server.common.data.id.EdgeId;
  32 +import org.thingsboard.server.common.data.id.EntityIdFactory;
  33 +import org.thingsboard.server.common.data.id.EventId;
  34 +import org.thingsboard.server.common.data.id.TenantId;
  35 +import org.thingsboard.server.dao.model.BaseEntity;
  36 +import org.thingsboard.server.dao.model.type.EdgeEventTypeCodec;
  37 +import org.thingsboard.server.dao.model.type.EntityTypeCodec;
  38 +import org.thingsboard.server.dao.model.type.JsonCodec;
  39 +
  40 +import java.util.UUID;
  41 +
  42 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY;
  43 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME;
  44 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY;
  45 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_BODY_PROPERTY;
  46 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY;
  47 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY;
  48 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY;
  49 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_BODY_PROPERTY;
  50 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_COLUMN_FAMILY_NAME;
  51 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_ID_PROPERTY;
  52 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_TYPE_PROPERTY;
  53 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_TENANT_ID_PROPERTY;
  54 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_TYPE_PROPERTY;
  55 +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_UID_PROPERTY;
  56 +import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
  57 +
  58 +@Data
  59 +@NoArgsConstructor
  60 +@Table(name = EDGE_EVENT_COLUMN_FAMILY_NAME)
  61 +public class EdgeEventEntity implements BaseEntity<EdgeEvent> {
  62 +
  63 + @Column(name = ID_PROPERTY)
  64 + private UUID id;
  65 +
  66 + @PartitionKey()
  67 + @Column(name = EDGE_EVENT_TENANT_ID_PROPERTY)
  68 + private UUID tenantId;
  69 +
  70 + @PartitionKey(value = 1)
  71 + @Column(name = EDGE_EVENT_EDGE_ID_PROPERTY)
  72 + private UUID edgeId;
  73 +
  74 + @PartitionKey(value = 2)
  75 + @Column(name = EDGE_EVENT_TYPE_PROPERTY, codec = EdgeEventTypeCodec.class)
  76 + private EdgeEventType edgeEventType;
  77 +
  78 + @PartitionKey(value = 3)
  79 + @Column(name = EDGE_EVENT_ENTITY_ID_PROPERTY)
  80 + private UUID entityId;
  81 +
  82 + @ClusteringColumn()
  83 + @Column(name = EDGE_EVENT_ACTION_PROPERTY)
  84 + private String edgeEventAction;
  85 +
  86 + // TODO
  87 + @ClusteringColumn(value = 1)
  88 + @Column(name = EVENT_UID_PROPERTY)
  89 + private String eventUid;
  90 +
  91 + @Column(name = EDGE_EVENT_ENTITY_BODY_PROPERTY, codec = JsonCodec.class)
  92 + private JsonNode entityBody;
  93 +
  94 + public EdgeEventEntity(EdgeEvent edgeEvent) {
  95 + if (edgeEvent.getId() != null) {
  96 + this.id = edgeEvent.getId().getId();
  97 + }
  98 + if (edgeEvent.getTenantId() != null) {
  99 + this.tenantId = edgeEvent.getTenantId().getId();
  100 + }
  101 + if (edgeEvent.getEdgeId() != null) {
  102 + this.edgeId = edgeEvent.getEdgeId().getId();
  103 + }
  104 +// if (event.getEntityId() != null) {
  105 +// this.entityType = event.getEntityId().getEntityType();
  106 +// this.entityId = event.getEntityId().getId();
  107 +// }
  108 +// this.edgeEventType = edgeEvent.getEdgeEventType();
  109 +// this.edgeEventAction = edgeEvent.getEdgeEventAction();
  110 +// this.entityBody = edgeEvent.getEntityBody();
  111 + }
  112 +
  113 + @Override
  114 + public UUID getUuid() {
  115 + return id;
  116 + }
  117 +
  118 + @Override
  119 + public void setUuid(UUID id) {
  120 + this.id = id;
  121 + }
  122 +
  123 + @Override
  124 + public EdgeEvent toData() {
  125 + EdgeEvent edgeEvent = new EdgeEvent(new EdgeEventId(id));
  126 +// edgeEvent.setCreatedTime(UUIDs.unixTimestamp(id));
  127 +// edgeEvent.setTenantId(new TenantId(tenantId));
  128 +// edgeEvent.setEdgeId(new EdgeId(edgeId));
  129 +// edgeEvent.setEntityId(entityId);
  130 +// event.setBody(body);
  131 +// event.setType(eventType);
  132 +// event.setUid(eventUid);
  133 + return edgeEvent;
  134 + }
  135 +}
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import com.datastax.driver.core.utils.UUIDs;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import lombok.Data;
  21 +import lombok.EqualsAndHashCode;
  22 +import lombok.NoArgsConstructor;
  23 +import org.hibernate.annotations.Type;
  24 +import org.hibernate.annotations.TypeDef;
  25 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  26 +import org.thingsboard.server.common.data.edge.EdgeEventType;
  27 +import org.thingsboard.server.common.data.id.EdgeEventId;
  28 +import org.thingsboard.server.common.data.id.EdgeId;
  29 +import org.thingsboard.server.common.data.id.TenantId;
  30 +import org.thingsboard.server.dao.model.BaseEntity;
  31 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  32 +import org.thingsboard.server.dao.util.mapping.JsonStringType;
  33 +
  34 +import javax.persistence.Column;
  35 +import javax.persistence.Entity;
  36 +import javax.persistence.EnumType;
  37 +import javax.persistence.Enumerated;
  38 +import javax.persistence.Table;
  39 +import java.util.UUID;
  40 +
  41 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY;
  42 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME;
  43 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY;
  44 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_BODY_PROPERTY;
  45 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY;
  46 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY;
  47 +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY;
  48 +import static org.thingsboard.server.dao.model.ModelConstants.EPOCH_DIFF;
  49 +import static org.thingsboard.server.dao.model.ModelConstants.TS_COLUMN;
  50 +
  51 +@Data
  52 +@EqualsAndHashCode(callSuper = true)
  53 +@Entity
  54 +@TypeDef(name = "json", typeClass = JsonStringType.class)
  55 +@Table(name = EDGE_EVENT_COLUMN_FAMILY_NAME)
  56 +@NoArgsConstructor
  57 +public class EdgeEventEntity extends BaseSqlEntity<EdgeEvent> implements BaseEntity<EdgeEvent> {
  58 +
  59 + @Column(name = EDGE_EVENT_TENANT_ID_PROPERTY)
  60 + private String tenantId;
  61 +
  62 + @Column(name = EDGE_EVENT_EDGE_ID_PROPERTY)
  63 + private String edgeId;
  64 +
  65 + @Column(name = EDGE_EVENT_ENTITY_ID_PROPERTY)
  66 + private String entityId;
  67 +
  68 + @Enumerated(EnumType.STRING)
  69 + @Column(name = EDGE_EVENT_TYPE_PROPERTY)
  70 + private EdgeEventType edgeEventType;
  71 +
  72 + @Column(name = EDGE_EVENT_ACTION_PROPERTY)
  73 + private String edgeEventAction;
  74 +
  75 + @Type(type = "json")
  76 + @Column(name = EDGE_EVENT_ENTITY_BODY_PROPERTY)
  77 + private JsonNode entityBody;
  78 +
  79 + @Column(name = TS_COLUMN)
  80 + private long ts;
  81 +
  82 + public EdgeEventEntity(EdgeEvent edgeEvent) {
  83 + if (edgeEvent.getId() != null) {
  84 + this.setUuid(edgeEvent.getId().getId());
  85 + this.ts = getTs(edgeEvent.getId().getId());
  86 + } else {
  87 + this.ts = System.currentTimeMillis();
  88 + }
  89 + if (edgeEvent.getTenantId() != null) {
  90 + this.tenantId = toString(edgeEvent.getTenantId().getId());
  91 + }
  92 + if (edgeEvent.getEdgeId() != null) {
  93 + this.edgeId = toString(edgeEvent.getEdgeId().getId());
  94 + }
  95 + if (edgeEvent.getEntityId() != null) {
  96 + this.entityId = toString(edgeEvent.getEntityId());
  97 + }
  98 + this.edgeEventType = edgeEvent.getEdgeEventType();
  99 + this.edgeEventAction = edgeEvent.getEdgeEventAction();
  100 + this.entityBody = edgeEvent.getEntityBody();
  101 + }
  102 +
  103 + @Override
  104 + public EdgeEvent toData() {
  105 + EdgeEvent edgeEvent = new EdgeEvent(new EdgeEventId(this.getUuid()));
  106 + edgeEvent.setCreatedTime(UUIDs.unixTimestamp(this.getUuid()));
  107 + edgeEvent.setTenantId(new TenantId(toUUID(tenantId)));
  108 + edgeEvent.setEdgeId(new EdgeId(toUUID(edgeId)));
  109 + if (entityId != null) {
  110 + edgeEvent.setEntityId(toUUID(entityId));
  111 + }
  112 + edgeEvent.setEdgeEventType(edgeEventType);
  113 + edgeEvent.setEdgeEventAction(edgeEventAction);
  114 + edgeEvent.setEntityBody(entityBody);
  115 + return edgeEvent;
  116 + }
  117 +
  118 + private static long getTs(UUID uuid) {
  119 + return (uuid.timestamp() - EPOCH_DIFF) / 10000;
  120 + }
  121 +}
... ...
dao/src/main/java/org/thingsboard/server/dao/model/type/EdgeEventTypeCodec.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/PushToEdgeNodeCallback.java
... ... @@ -13,29 +13,15 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.rule.engine.edge;
  16 +package org.thingsboard.server.dao.model.type;
17 17
18   -import com.google.common.util.concurrent.FutureCallback;
19   -import lombok.Data;
20   -import org.thingsboard.rule.engine.api.TbContext;
21   -import org.thingsboard.server.common.msg.TbMsg;
  18 +import com.datastax.driver.extras.codecs.enums.EnumNameCodec;
  19 +import org.thingsboard.server.common.data.edge.EdgeEventType;
22 20
23   -import javax.annotation.Nullable;
  21 +public class EdgeEventTypeCodec extends EnumNameCodec<EdgeEventType> {
24 22
25   -import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
26   -
27   -@Data
28   -class PushToEdgeNodeCallback implements FutureCallback<Void> {
29   - private final TbContext ctx;
30   - private final TbMsg msg;
31   -
32   - @Override
33   - public void onSuccess(@Nullable Void result) {
34   - ctx.tellNext(msg, SUCCESS);
  23 + public EdgeEventTypeCodec() {
  24 + super(EdgeEventType.class);
35 25 }
36 26
37   - @Override
38   - public void onFailure(Throwable t) {
39   - ctx.tellFailure(msg, t);
40   - }
41 27 }
... ...
... ... @@ -289,7 +289,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
289 289
290 290 @Override
291 291 public RuleChain getRootTenantRuleChain(TenantId tenantId) {
292   - return getRootRuleChainByType(tenantId, RuleChainType.SYSTEM);
  292 + return getRootRuleChainByType(tenantId, RuleChainType.CORE);
293 293 }
294 294
295 295 private RuleChain getRootRuleChainByType(TenantId tenantId, RuleChainType type) {
... ... @@ -566,7 +566,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
566 566 throw new DataValidationException("Rule chain name should be specified!");
567 567 }
568 568 if (ruleChain.getType() == null) {
569   - ruleChain.setType(RuleChainType.SYSTEM);
  569 + ruleChain.setType(RuleChainType.CORE);
570 570 }
571 571 if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) {
572 572 throw new DataValidationException("Rule chain should be assigned to tenant!");
... ... @@ -575,7 +575,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
575 575 if (tenant == null) {
576 576 throw new DataValidationException("Rule chain is referencing to non-existent tenant!");
577 577 }
578   - if (ruleChain.isRoot() && RuleChainType.SYSTEM.equals(ruleChain.getType())) {
  578 + if (ruleChain.isRoot() && RuleChainType.CORE.equals(ruleChain.getType())) {
579 579 RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
580 580 if (rootRuleChain != null && !rootRuleChain.getId().equals(ruleChain.getId())) {
581 581 throw new DataValidationException("Another root rule chain is present in scope of current tenant!");
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.edge;
  17 +
  18 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.thingsboard.server.dao.model.sql.EdgeEventEntity;
  21 +import org.thingsboard.server.dao.util.SqlDao;
  22 +
  23 +@SqlDao
  24 +public interface EdgeEventRepository extends CrudRepository<EdgeEventEntity, String>, JpaSpecificationExecutor<EdgeEventEntity> {
  25 +
  26 +}
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.edge;
  17 +
  18 +import com.datastax.driver.core.utils.UUIDs;
  19 +import com.google.common.util.concurrent.ListenableFuture;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.data.domain.PageRequest;
  23 +import org.springframework.data.domain.Pageable;
  24 +import org.springframework.data.domain.Sort;
  25 +import org.springframework.data.jpa.domain.Specification;
  26 +import org.springframework.data.repository.CrudRepository;
  27 +import org.springframework.stereotype.Component;
  28 +import org.thingsboard.server.common.data.UUIDConverter;
  29 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  30 +import org.thingsboard.server.common.data.id.EdgeEventId;
  31 +import org.thingsboard.server.common.data.id.EdgeId;
  32 +import org.thingsboard.server.common.data.page.TimePageLink;
  33 +import org.thingsboard.server.dao.DaoUtil;
  34 +import org.thingsboard.server.dao.edge.EdgeEventDao;
  35 +import org.thingsboard.server.dao.model.sql.EdgeEventEntity;
  36 +import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao;
  37 +import org.thingsboard.server.dao.util.SqlDao;
  38 +
  39 +import javax.persistence.criteria.Predicate;
  40 +import java.util.ArrayList;
  41 +import java.util.List;
  42 +import java.util.Optional;
  43 +import java.util.UUID;
  44 +
  45 +import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
  46 +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
  47 +
  48 +@Slf4j
  49 +@Component
  50 +@SqlDao
  51 +public class JpaBaseEdgeEventDao extends JpaAbstractSearchTimeDao<EdgeEventEntity, EdgeEvent> implements EdgeEventDao {
  52 +
  53 + private final UUID systemTenantId = NULL_UUID;
  54 +
  55 + @Autowired
  56 + private EdgeEventRepository edgeEventRepository;
  57 +
  58 + @Override
  59 + protected Class<EdgeEventEntity> getEntityClass() {
  60 + return EdgeEventEntity.class;
  61 + }
  62 +
  63 + @Override
  64 + protected CrudRepository<EdgeEventEntity, String> getCrudRepository() {
  65 + return edgeEventRepository;
  66 + }
  67 +
  68 + @Override
  69 + public ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent) {
  70 + log.debug("Save edge event [{}] ", edgeEvent);
  71 + if (edgeEvent.getId() == null) {
  72 + edgeEvent.setId(new EdgeEventId(UUIDs.timeBased()));
  73 + }
  74 + return service.submit(() -> save(new EdgeEventEntity(edgeEvent)).orElse(null));
  75 + }
  76 +
  77 + @Override
  78 + public List<EdgeEvent> findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink) {
  79 + Specification<EdgeEventEntity> timeSearchSpec = JpaAbstractSearchTimeDao.getTimeSearchPageSpec(pageLink, "id");
  80 + Specification<EdgeEventEntity> fieldsSpec = getEntityFieldsSpec(tenantId, edgeId);
  81 + Sort.Direction sortDirection = pageLink.isAscOrder() ? Sort.Direction.ASC : Sort.Direction.DESC;
  82 + Pageable pageable = PageRequest.of(0, pageLink.getLimit(), sortDirection, ID_PROPERTY);
  83 + return DaoUtil.convertDataList(edgeEventRepository.findAll(Specification.where(timeSearchSpec).and(fieldsSpec), pageable).getContent());
  84 + }
  85 +
  86 + public Optional<EdgeEvent> save(EdgeEventEntity entity) {
  87 + log.debug("Save edge event [{}] ", entity);
  88 + if (entity.getTenantId() == null) {
  89 + log.trace("Save system edge event with predefined id {}", systemTenantId);
  90 + entity.setTenantId(UUIDConverter.fromTimeUUID(systemTenantId));
  91 + }
  92 + if (entity.getUuid() == null) {
  93 + entity.setUuid(UUIDs.timeBased());
  94 + }
  95 + return Optional.of(DaoUtil.getData(edgeEventRepository.save(entity)));
  96 + }
  97 +
  98 + private Specification<EdgeEventEntity> getEntityFieldsSpec(UUID tenantId, EdgeId edgeId) {
  99 + return (root, criteriaQuery, criteriaBuilder) -> {
  100 + List<Predicate> predicates = new ArrayList<>();
  101 + if (tenantId != null) {
  102 + Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), UUIDConverter.fromTimeUUID(tenantId));
  103 + predicates.add(tenantIdPredicate);
  104 + }
  105 + if (edgeId != null) {
  106 + Predicate entityIdPredicate = criteriaBuilder.equal(root.get("edgeId"), UUIDConverter.fromTimeUUID(edgeId.getId()));
  107 + predicates.add(entityIdPredicate);
  108 + }
  109 + return criteriaBuilder.and(predicates.toArray(new Predicate[]{}));
  110 + };
  111 + }
  112 +}
... ...
... ... @@ -270,3 +270,14 @@ CREATE TABLE IF NOT EXISTS edge (
270 270 CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name),
271 271 CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key)
272 272 );
  273 +
  274 +CREATE TABLE IF NOT EXISTS edge_event (
  275 + id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY,
  276 + edge_id varchar(31),
  277 + edge_event_type varchar(255),
  278 + entity_id varchar(31),
  279 + edge_event_action varchar(255),
  280 + entity_body varchar(10000000),
  281 + tenant_id varchar(31),
  282 + ts bigint NOT NULL
  283 +);
\ No newline at end of file
... ...
... ... @@ -271,6 +271,18 @@ CREATE TABLE IF NOT EXISTS edge (
271 271 CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key)
272 272 );
273 273
  274 +CREATE TABLE IF NOT EXISTS edge_event (
  275 + id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY,
  276 + edge_id varchar(31),
  277 + edge_event_type varchar(255),
  278 + entity_id varchar(31),
  279 + edge_event_action varchar(255),
  280 + entity_body varchar(10000000),
  281 + tenant_id varchar(31),
  282 + ts bigint NOT NULL
  283 +);
  284 +
  285 +
274 286 CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint)
275 287 LANGUAGE plpgsql AS
276 288 $$
... ...
... ... @@ -45,6 +45,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
45 45 import org.thingsboard.server.dao.dashboard.DashboardService;
46 46 import org.thingsboard.server.dao.device.DeviceCredentialsService;
47 47 import org.thingsboard.server.dao.device.DeviceService;
  48 +import org.thingsboard.server.dao.edge.EdgeEventService;
48 49 import org.thingsboard.server.dao.edge.EdgeService;
49 50 import org.thingsboard.server.dao.entityview.EntityViewService;
50 51 import org.thingsboard.server.dao.event.EventService;
... ... @@ -126,6 +127,9 @@ public abstract class AbstractServiceTest {
126 127 protected EdgeService edgeService;
127 128
128 129 @Autowired
  130 + protected EdgeEventService edgeEventService;
  131 +
  132 + @Autowired
129 133 private ComponentDescriptorService componentDescriptorService;
130 134
131 135 class IdComparator<D extends BaseData<? extends UUIDBased>> implements Comparator<D> {
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service;
  17 +
  18 +import com.datastax.driver.core.utils.UUIDs;
  19 +import org.junit.Assert;
  20 +import org.junit.Test;
  21 +import org.thingsboard.server.common.data.DataConstants;
  22 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  23 +import org.thingsboard.server.common.data.edge.EdgeEventType;
  24 +import org.thingsboard.server.common.data.id.DeviceId;
  25 +import org.thingsboard.server.common.data.id.EdgeEventId;
  26 +import org.thingsboard.server.common.data.id.EdgeId;
  27 +import org.thingsboard.server.common.data.id.EntityId;
  28 +import org.thingsboard.server.common.data.id.TenantId;
  29 +import org.thingsboard.server.common.data.page.TimePageData;
  30 +import org.thingsboard.server.common.data.page.TimePageLink;
  31 +
  32 +import java.io.IOException;
  33 +import java.time.LocalDateTime;
  34 +import java.time.Month;
  35 +import java.time.ZoneOffset;
  36 +
  37 +public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest {
  38 +
  39 + @Test
  40 + public void saveEdgeEvent() throws Exception {
  41 + EdgeId edgeId = new EdgeId(UUIDs.timeBased());
  42 + DeviceId deviceId = new DeviceId(UUIDs.timeBased());
  43 + EdgeEvent edgeEvent = generateEdgeEvent(null, edgeId, deviceId, DataConstants.ENTITY_CREATED);
  44 + EdgeEvent saved = edgeEventService.saveAsync(edgeEvent).get();
  45 + Assert.assertEquals(saved.getTenantId(), edgeEvent.getTenantId());
  46 + Assert.assertEquals(saved.getEdgeId(), edgeEvent.getEdgeId());
  47 + Assert.assertEquals(saved.getEntityId(), edgeEvent.getEntityId());
  48 + Assert.assertEquals(saved.getEdgeEventType(), edgeEvent.getEdgeEventType());
  49 + Assert.assertEquals(saved.getEdgeEventAction(), edgeEvent.getEdgeEventAction());
  50 + Assert.assertEquals(saved.getEntityBody(), edgeEvent.getEntityBody());
  51 + }
  52 +
  53 + protected EdgeEvent generateEdgeEvent(TenantId tenantId, EdgeId edgeId, EntityId entityId, String edgeEventAction) throws IOException {
  54 + if (tenantId == null) {
  55 + tenantId = new TenantId(UUIDs.timeBased());
  56 + }
  57 + EdgeEvent edgeEvent = new EdgeEvent();
  58 + edgeEvent.setTenantId(tenantId);
  59 + edgeEvent.setEdgeId(edgeId);
  60 + edgeEvent.setEntityId(entityId.getId());
  61 + edgeEvent.setEdgeEventType(EdgeEventType.DEVICE);
  62 + edgeEvent.setEdgeEventAction(edgeEventAction);
  63 + edgeEvent.setEntityBody(readFromResource("TestJsonData.json"));
  64 + return edgeEvent;
  65 + }
  66 +
  67 +
  68 + @Test
  69 + public void findEdgeEventsByTimeDescOrder() throws Exception {
  70 + long timeBeforeStartTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 11, 30).toEpochSecond(ZoneOffset.UTC);
  71 + long startTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 12, 0).toEpochSecond(ZoneOffset.UTC);
  72 + long eventTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 12, 30).toEpochSecond(ZoneOffset.UTC);
  73 + long endTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 13, 0).toEpochSecond(ZoneOffset.UTC);
  74 + long timeAfterEndTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 13, 30).toEpochSecond(ZoneOffset.UTC);
  75 +
  76 + EdgeId edgeId = new EdgeId(UUIDs.timeBased());
  77 + DeviceId deviceId = new DeviceId(UUIDs.timeBased());
  78 + TenantId tenantId = new TenantId(UUIDs.timeBased());
  79 + saveEdgeEventWithProvidedTime(timeBeforeStartTime, edgeId, deviceId, tenantId);
  80 + EdgeEvent savedEdgeEvent = saveEdgeEventWithProvidedTime(eventTime, edgeId, deviceId, tenantId);
  81 + EdgeEvent savedEdgeEvent2 = saveEdgeEventWithProvidedTime(eventTime + 1, edgeId, deviceId, tenantId);
  82 + EdgeEvent savedEdgeEvent3 = saveEdgeEventWithProvidedTime(eventTime + 2, edgeId, deviceId, tenantId);
  83 + saveEdgeEventWithProvidedTime(timeAfterEndTime, edgeId, deviceId, tenantId);
  84 +
  85 + TimePageData<EdgeEvent> edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, new TimePageLink(2, startTime, endTime, false));
  86 +
  87 + Assert.assertNotNull(edgeEvents.getData());
  88 + Assert.assertTrue(edgeEvents.getData().size() == 2);
  89 + Assert.assertTrue(edgeEvents.getData().get(0).getUuidId().equals(savedEdgeEvent3.getUuidId()));
  90 + Assert.assertTrue(edgeEvents.getData().get(1).getUuidId().equals(savedEdgeEvent2.getUuidId()));
  91 + Assert.assertTrue(edgeEvents.hasNext());
  92 + Assert.assertNotNull(edgeEvents.getNextPageLink());
  93 +
  94 + edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, edgeEvents.getNextPageLink());
  95 +
  96 + Assert.assertNotNull(edgeEvents.getData());
  97 + Assert.assertTrue(edgeEvents.getData().size() == 1);
  98 + Assert.assertTrue(edgeEvents.getData().get(0).getUuidId().equals(savedEdgeEvent.getUuidId()));
  99 + Assert.assertFalse(edgeEvents.hasNext());
  100 + Assert.assertNull(edgeEvents.getNextPageLink());
  101 + }
  102 +
  103 + private EdgeEvent saveEdgeEventWithProvidedTime(long time, EdgeId edgeId, EntityId entityId, TenantId tenantId) throws Exception {
  104 + EdgeEvent edgeEvent = generateEdgeEvent(tenantId, edgeId, entityId, DataConstants.ENTITY_CREATED);
  105 + edgeEvent.setId(new EdgeEventId(UUIDs.startOf(time)));
  106 + return edgeEventService.saveAsync(edgeEvent).get();
  107 + }
  108 +}
\ No newline at end of file
... ...
dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java renamed from dao/src/test/java/org/thingsboard/server/dao/service/EdgeServiceImplTest.java
... ... @@ -37,7 +37,7 @@ import java.util.List;
37 37
38 38 import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
39 39
40   -public abstract class EdgeServiceImplTest extends AbstractServiceTest {
  40 +public abstract class BaseEdgeServiceTest extends AbstractServiceTest {
41 41
42 42 private IdComparator<Edge> idComparator = new IdComparator<>();
43 43
... ...
... ... @@ -145,7 +145,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
145 145 TextPageLink pageLink = new TextPageLink(16);
146 146 TextPageData<RuleChain> pageData = null;
147 147 do {
148   - pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink);
  148 + pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
149 149 loadedRuleChains.addAll(pageData.getData());
150 150 if (pageData.hasNext()) {
151 151 pageLink = pageData.getNextPageLink();
... ... @@ -160,7 +160,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
160 160 ruleChainService.deleteRuleChainsByTenantId(tenantId);
161 161
162 162 pageLink = new TextPageLink(31);
163   - pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink);
  163 + pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
164 164 Assert.assertFalse(pageData.hasNext());
165 165 Assert.assertTrue(pageData.getData().isEmpty());
166 166
... ... @@ -196,7 +196,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
196 196 TextPageLink pageLink = new TextPageLink(19, name1);
197 197 TextPageData<RuleChain> pageData = null;
198 198 do {
199   - pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink);
  199 + pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
200 200 loadedRuleChainsName1.addAll(pageData.getData());
201 201 if (pageData.hasNext()) {
202 202 pageLink = pageData.getNextPageLink();
... ... @@ -211,7 +211,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
211 211 List<RuleChain> loadedRuleChainsName2 = new ArrayList<>();
212 212 pageLink = new TextPageLink(4, name2);
213 213 do {
214   - pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink);
  214 + pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
215 215 loadedRuleChainsName2.addAll(pageData.getData());
216 216 if (pageData.hasNext()) {
217 217 pageLink = pageData.getNextPageLink();
... ... @@ -228,7 +228,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
228 228 }
229 229
230 230 pageLink = new TextPageLink(4, name1);
231   - pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink);
  231 + pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
232 232 Assert.assertFalse(pageData.hasNext());
233 233 Assert.assertEquals(0, pageData.getData().size());
234 234
... ... @@ -237,7 +237,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
237 237 }
238 238
239 239 pageLink = new TextPageLink(4, name2);
240   - pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink);
  240 + pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
241 241 Assert.assertFalse(pageData.hasNext());
242 242 Assert.assertEquals(0, pageData.getData().size());
243 243 }
... ...
dao/src/test/java/org/thingsboard/server/dao/service/nosql/EdgeEventServiceNoSqlTest.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntry.java
... ... @@ -13,13 +13,11 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.edge;
  16 +package org.thingsboard.server.dao.service.nosql;
17 17
18   -import lombok.Data;
  18 +import org.thingsboard.server.dao.service.BaseEdgeEventServiceTest;
  19 +import org.thingsboard.server.dao.service.DaoNoSqlTest;
19 20
20   -@Data
21   -public class EdgeQueueEntry {
22   - private String type;
23   - private EdgeQueueEntityType entityType;
24   - private String data;
  21 +@DaoNoSqlTest
  22 +public class EdgeEventServiceNoSqlTest extends BaseEdgeEventServiceTest {
25 23 }
... ...
... ... @@ -15,9 +15,9 @@
15 15 */
16 16 package org.thingsboard.server.dao.service.nosql;
17 17
18   -import org.thingsboard.server.dao.service.EdgeServiceImplTest;
  18 +import org.thingsboard.server.dao.service.BaseEdgeServiceTest;
19 19 import org.thingsboard.server.dao.service.DaoNoSqlTest;
20 20
21 21 @DaoNoSqlTest
22   -public class EdgeServiceNoSqlTest extends EdgeServiceImplTest {
  22 +public class EdgeServiceNoSqlTest extends BaseEdgeServiceTest {
23 23 }
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service.sql;
  17 +
  18 +import org.thingsboard.server.dao.service.BaseEdgeEventServiceTest;
  19 +import org.thingsboard.server.dao.service.DaoSqlTest;
  20 +
  21 +@DaoSqlTest
  22 +public class EdgeEventServiceSqlTest extends BaseEdgeEventServiceTest {
  23 +}
... ...
... ... @@ -15,9 +15,9 @@
15 15 */
16 16 package org.thingsboard.server.dao.service.sql;
17 17
18   -import org.thingsboard.server.dao.service.EdgeServiceImplTest;
  18 +import org.thingsboard.server.dao.service.BaseEdgeServiceTest;
19 19 import org.thingsboard.server.dao.service.DaoSqlTest;
20 20
21 21 @DaoSqlTest
22   -public class EdgeServiceSqlTest extends EdgeServiceImplTest {
  22 +public class EdgeServiceSqlTest extends BaseEdgeServiceTest {
23 23 }
... ...
... ... @@ -20,4 +20,5 @@ DROP TABLE IF EXISTS widgets_bundle;
20 20 DROP TABLE IF EXISTS rule_node;
21 21 DROP TABLE IF EXISTS rule_chain;
22 22 DROP TABLE IF EXISTS entity_view;
23   -DROP TABLE IF EXISTS edge;
\ No newline at end of file
  23 +DROP TABLE IF EXISTS edge;
  24 +DROP TABLE IF EXISTS edge_event;
\ No newline at end of file
... ...
... ... @@ -58,6 +58,6 @@ public @interface RuleNode {
58 58
59 59 boolean customRelations() default false;
60 60
61   - RuleChainType[] ruleChainTypes() default RuleChainType.SYSTEM;
  61 + RuleChainType[] ruleChainTypes() default RuleChainType.CORE;
62 62
63 63 }
... ...
... ... @@ -35,6 +35,7 @@ import org.thingsboard.server.dao.cassandra.CassandraCluster;
35 35 import org.thingsboard.server.dao.customer.CustomerService;
36 36 import org.thingsboard.server.dao.dashboard.DashboardService;
37 37 import org.thingsboard.server.dao.device.DeviceService;
  38 +import org.thingsboard.server.dao.edge.EdgeEventService;
38 39 import org.thingsboard.server.dao.edge.EdgeService;
39 40 import org.thingsboard.server.dao.entityview.EntityViewService;
40 41 import org.thingsboard.server.dao.nosql.CassandraStatementTask;
... ... @@ -190,6 +191,8 @@ public interface TbContext {
190 191
191 192 EdgeService getEdgeService();
192 193
  194 + EdgeEventService getEdgeEventService();
  195 +
193 196 ListeningExecutor getJsExecutor();
194 197
195 198 ListeningExecutor getMailExecutor();
... ...
... ... @@ -38,7 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg;
38 38 uiResources = {"static/rulenode/rulenode-core-config.js"},
39 39 configDirective = "tbActionNodeAssignToCustomerConfig",
40 40 icon = "add_circle",
41   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  41 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
42 42 )
43 43 public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode<TbAssignToCustomerNodeConfiguration> {
44 44
... ...
... ... @@ -46,7 +46,7 @@ import org.thingsboard.server.common.msg.TbMsg;
46 46 uiResources = {"static/rulenode/rulenode-core-config.js"},
47 47 configDirective = "tbActionNodeClearAlarmConfig",
48 48 icon = "notifications_off",
49   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  49 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
50 50 )
51 51 public class TbClearAlarmNode extends TbAbstractAlarmNode<TbClearAlarmNodeConfiguration> {
52 52
... ...
... ... @@ -58,7 +58,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
58 58 uiResources = {"static/rulenode/rulenode-core-config.js"},
59 59 configDirective = "tbNodeEmptyConfig",
60 60 icon = "content_copy",
61   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  61 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
62 62 )
63 63 public class TbCopyAttributesToEntityViewNode implements TbNode {
64 64
... ...
... ... @@ -52,7 +52,7 @@ import java.util.List;
52 52 uiResources = {"static/rulenode/rulenode-core-config.js"},
53 53 configDirective = "tbActionNodeCreateAlarmConfig",
54 54 icon = "notifications_active",
55   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  55 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
56 56 )
57 57 public class TbCreateAlarmNode extends TbAbstractAlarmNode<TbCreateAlarmNodeConfiguration> {
58 58
... ...
... ... @@ -55,7 +55,7 @@ import java.util.List;
55 55 uiResources = {"static/rulenode/rulenode-core-config.js"},
56 56 configDirective = "tbActionNodeCreateRelationConfig",
57 57 icon = "add_circle",
58   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  58 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
59 59 )
60 60 public class TbCreateRelationNode extends TbAbstractRelationActionNode<TbCreateRelationNodeConfiguration> {
61 61
... ...
... ... @@ -45,7 +45,7 @@ import java.util.List;
45 45 uiResources = {"static/rulenode/rulenode-core-config.js"},
46 46 configDirective = "tbActionNodeDeleteRelationConfig",
47 47 icon = "remove_circle",
48   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  48 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
49 49 )
50 50 public class TbDeleteRelationNode extends TbAbstractRelationActionNode<TbDeleteRelationNodeConfiguration> {
51 51
... ...
... ... @@ -38,7 +38,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
38 38 uiResources = {"static/rulenode/rulenode-core-config.js"},
39 39 configDirective = "tbActionNodeLogConfig",
40 40 icon = "menu",
41   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  41 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
42 42 )
43 43
44 44 public class TbLogNode implements TbNode {
... ...
... ... @@ -44,7 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
44 44 icon = "functions",
45 45 uiResources = {"static/rulenode/rulenode-core-config.js"},
46 46 configDirective = "tbActionNodeMsgCountConfig",
47   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  47 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
48 48 )
49 49 public class TbMsgCountNode implements TbNode {
50 50
... ...
... ... @@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.TbMsg;
35 35 uiResources = {"static/rulenode/rulenode-core-config.js"},
36 36 configDirective = "tbActionNodeUnAssignToCustomerConfig",
37 37 icon = "remove_circle",
38   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  38 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
39 39 )
40 40 public class TbUnassignFromCustomerNode extends TbAbstractCustomerActionNode<TbUnassignFromCustomerNodeConfiguration> {
41 41
... ...
... ... @@ -47,7 +47,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
47 47 uiResources = {"static/rulenode/rulenode-core-config.js"},
48 48 configDirective = "tbActionNodeSnsConfig",
49 49 iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+",
50   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  50 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
51 51 )
52 52 public class TbSnsNode implements TbNode {
53 53
... ...
... ... @@ -52,7 +52,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
52 52 uiResources = {"static/rulenode/rulenode-core-config.js"},
53 53 configDirective = "tbActionNodeSqsConfig",
54 54 iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+",
55   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  55 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
56 56 )
57 57 public class TbSqsNode implements TbNode {
58 58
... ...
... ... @@ -45,7 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
45 45 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
46 46 configDirective = "tbActionNodeGeneratorConfig",
47 47 icon = "repeat",
48   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  48 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
49 49 )
50 50
51 51 public class TbMsgGeneratorNode implements TbNode {
... ...
... ... @@ -46,7 +46,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
46 46 icon = "pause",
47 47 uiResources = {"static/rulenode/rulenode-core-config.js"},
48 48 configDirective = "tbActionNodeMsgDelayConfig",
49   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  49 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
50 50 )
51 51
52 52 public class TbMsgDelayNode implements TbNode {
... ...
... ... @@ -15,6 +15,10 @@
15 15 */
16 16 package org.thingsboard.rule.engine.edge;
17 17
  18 +import com.fasterxml.jackson.databind.ObjectMapper;
  19 +import com.google.common.util.concurrent.FutureCallback;
  20 +import com.google.common.util.concurrent.Futures;
  21 +import com.google.common.util.concurrent.ListenableFuture;
18 22 import lombok.extern.slf4j.Slf4j;
19 23 import org.thingsboard.rule.engine.api.EmptyNodeConfiguration;
20 24 import org.thingsboard.rule.engine.api.RuleNode;
... ... @@ -23,10 +27,25 @@ import org.thingsboard.rule.engine.api.TbNode;
23 27 import org.thingsboard.rule.engine.api.TbNodeConfiguration;
24 28 import org.thingsboard.rule.engine.api.TbNodeException;
25 29 import org.thingsboard.rule.engine.api.util.TbNodeUtils;
  30 +import org.thingsboard.server.common.data.DataConstants;
  31 +import org.thingsboard.server.common.data.EntityType;
  32 +import org.thingsboard.server.common.data.audit.ActionType;
  33 +import org.thingsboard.server.common.data.edge.EdgeEvent;
  34 +import org.thingsboard.server.common.data.edge.EdgeEventType;
  35 +import org.thingsboard.server.common.data.id.EdgeId;
  36 +import org.thingsboard.server.common.data.id.EntityId;
  37 +import org.thingsboard.server.common.data.id.TenantId;
26 38 import org.thingsboard.server.common.data.plugin.ComponentType;
  39 +import org.thingsboard.server.common.data.relation.EntityRelation;
  40 +import org.thingsboard.server.common.data.relation.RelationTypeGroup;
27 41 import org.thingsboard.server.common.msg.TbMsg;
28 42 import org.thingsboard.server.common.msg.session.SessionMsgType;
29 43
  44 +import javax.annotation.Nullable;
  45 +import java.util.List;
  46 +
  47 +import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
  48 +
30 49 @Slf4j
31 50 @RuleNode(
32 51 type = ComponentType.ACTION,
... ... @@ -40,13 +59,10 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
40 59 )
41 60 public class TbMsgPushToEdgeNode implements TbNode {
42 61
43   - private static final String CLOUD_MSG_SOURCE = "cloud";
44   - private static final String EDGE_MSG_SOURCE = "edge";
45   - private static final String MSG_SOURCE_KEY = "source";
46   - private static final String TS_METADATA_KEY = "ts";
47   -
48 62 private EmptyNodeConfiguration config;
49 63
  64 + private static final ObjectMapper json = new ObjectMapper();
  65 +
50 66 @Override
51 67 public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
52 68 this.config = TbNodeUtils.convert(configuration, EmptyNodeConfiguration.class);
... ... @@ -54,14 +70,71 @@ public class TbMsgPushToEdgeNode implements TbNode {
54 70
55 71 @Override
56 72 public void onMsg(TbContext ctx, TbMsg msg) {
57   - if (EDGE_MSG_SOURCE.equalsIgnoreCase(msg.getMetaData().getValue(MSG_SOURCE_KEY))) {
58   - return;
59   - }
60   - if (msg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name())) {
61   - msg.getMetaData().putValue(TS_METADATA_KEY, Long.toString(System.currentTimeMillis()));
  73 + if (EntityType.DEVICE.equals(msg.getOriginator().getEntityType()) ||
  74 + EntityType.DEVICE.equals(msg.getOriginator().getEntityType()) ||
  75 + EntityType.DEVICE.equals(msg.getOriginator().getEntityType()) ||
  76 + EntityType.DEVICE.equals(msg.getOriginator().getEntityType())) {
  77 + if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msg.getType()) ||
  78 + SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msg.getType()) ||
  79 + DataConstants.ATTRIBUTES_UPDATED.equals(msg.getType()) ||
  80 + DataConstants.ATTRIBUTES_DELETED.equals(msg.getType())) {
  81 + ListenableFuture<EdgeId> getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator());
  82 + Futures.transform(getEdgeIdFuture, edgeId -> {
  83 + EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType());
  84 + if (edgeEventTypeByEntityType == null) {
  85 + log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType());
  86 + ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '"+ msg.getOriginator().getEntityType() + "'"));
  87 + }
  88 + ActionType actionType;
  89 + if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msg.getType())) {
  90 + actionType = ActionType.TIMESERIES_UPDATED;
  91 + } else if (SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msg.getType()) ||
  92 + DataConstants.ATTRIBUTES_UPDATED.equals(msg.getType())) {
  93 + actionType = ActionType.ATTRIBUTES_UPDATED;
  94 + } else {
  95 + actionType = ActionType.ATTRIBUTES_DELETED;
  96 + }
  97 + EdgeEvent edgeEvent = new EdgeEvent();
  98 + edgeEvent.setTenantId(ctx.getTenantId());
  99 + edgeEvent.setEdgeId(edgeId);
  100 + edgeEvent.setEdgeEventAction(actionType.name());
  101 + edgeEvent.setEntityId(msg.getOriginator().getId());
  102 + edgeEvent.setEdgeEventType(edgeEventTypeByEntityType);
  103 + edgeEvent.setEntityBody(json.valueToTree(msg.getData()));
  104 + ListenableFuture<EdgeEvent> saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent);
  105 + Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
  106 + @Override
  107 + public void onSuccess(@Nullable EdgeEvent event) {
  108 + ctx.tellNext(msg, SUCCESS);
  109 + }
  110 +
  111 + @Override
  112 + public void onFailure(Throwable th) {
  113 + log.error("Could not save edge event", th);
  114 + ctx.tellFailure(msg, th);
  115 + }
  116 + }, ctx.getDbCallbackExecutor());
  117 + return null;
  118 + }, ctx.getDbCallbackExecutor());
  119 + } else {
  120 + log.debug("Unsupported msg type {}", msg.getType());
  121 + ctx.tellFailure(msg, new RuntimeException("Unsupported msg type '" + msg.getType() + "'"));
  122 + }
  123 + } else {
  124 + log.debug("Unsupported originator type {}", msg.getOriginator().getEntityType());
  125 + ctx.tellFailure(msg, new RuntimeException("Unsupported originator type '" + msg.getOriginator().getEntityType() + "'"));
62 126 }
63   - msg.getMetaData().putValue(MSG_SOURCE_KEY, CLOUD_MSG_SOURCE);
64   - ctx.getEdgeService().pushEventToEdge(ctx.getTenantId(), msg, new PushToEdgeNodeCallback(ctx, msg));
  127 + }
  128 +
  129 + private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) {
  130 + ListenableFuture<List<EntityRelation>> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
  131 + return Futures.transform(future, relations -> {
  132 + if (relations != null && relations.size() > 0) {
  133 + return new EdgeId(relations.get(0).getFrom().getId());
  134 + } else {
  135 + return null;
  136 + }
  137 + }, ctx.getDbCallbackExecutor());
65 138 }
66 139
67 140 @Override
... ...
... ... @@ -41,7 +41,7 @@ import java.util.Map;
41 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 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 43 configDirective = "tbFilterNodeCheckMessageConfig",
44   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  44 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
45 45 )
46 46 public class TbCheckMessageNode implements TbNode {
47 47
... ...
... ... @@ -53,7 +53,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
53 53 nodeDetails = "If at least one relation exists - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
54 54 uiResources = {"static/rulenode/rulenode-core-config.js"},
55 55 configDirective = "tbFilterNodeCheckRelationConfig",
56   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  56 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
57 57 )
58 58 public class TbCheckRelationNode implements TbNode {
59 59
... ...
... ... @@ -38,7 +38,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
38 38 "Message type can be accessed via <code>msgType</code> property.",
39 39 uiResources = {"static/rulenode/rulenode-core-config.js"},
40 40 configDirective = "tbFilterNodeScriptConfig",
41   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  41 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
42 42 )
43 43
44 44 public class TbJsFilterNode implements TbNode {
... ...
... ... @@ -41,7 +41,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
41 41 "Message type can be accessed via <code>msgType</code> property.",
42 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 43 configDirective = "tbFilterNodeSwitchConfig",
44   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  44 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
45 45 )
46 46 public class TbJsSwitchNode implements TbNode {
47 47
... ...
... ... @@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.TbMsg;
35 35 nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
36 36 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
37 37 configDirective = "tbFilterNodeMessageTypeConfig",
38   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  38 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
39 39 )
40 40 public class TbMsgTypeFilterNode implements TbNode {
41 41
... ...
... ... @@ -36,7 +36,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
36 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 37 uiResources = {"static/rulenode/rulenode-core-config.js"},
38 38 configDirective = "tbNodeEmptyConfig",
39   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  39 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
40 40 )
41 41 public class TbMsgTypeSwitchNode implements TbNode {
42 42
... ...
... ... @@ -33,7 +33,7 @@ import org.thingsboard.server.common.msg.TbMsg;
33 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 34 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
35 35 configDirective = "tbFilterNodeOriginatorTypeConfig",
36   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  36 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
37 37 )
38 38 public class TbOriginatorTypeFilterNode implements TbNode {
39 39
... ...
... ... @@ -33,7 +33,7 @@ import org.thingsboard.server.common.msg.TbMsg;
33 33 nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).",
34 34 uiResources = {"static/rulenode/rulenode-core-config.js"},
35 35 configDirective = "tbNodeEmptyConfig",
36   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  36 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
37 37 )
38 38 public class TbOriginatorTypeSwitchNode implements TbNode {
39 39
... ...
... ... @@ -51,7 +51,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
51 51 uiResources = {"static/rulenode/rulenode-core-config.js"},
52 52 configDirective = "tbActionNodePubSubConfig",
53 53 iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=",
54   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  54 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
55 55 )
56 56 public class TbPubSubNode implements TbNode {
57 57
... ...
... ... @@ -53,7 +53,7 @@ import java.util.concurrent.TimeoutException;
53 53 nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters",
54 54 uiResources = {"static/rulenode/rulenode-core-config.js"},
55 55 configDirective = "tbActionNodeGpsGeofencingConfig",
56   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  56 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
57 57 )
58 58 public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> {
59 59
... ...
... ... @@ -54,7 +54,7 @@ import java.util.List;
54 54 nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.",
55 55 uiResources = {"static/rulenode/rulenode-core-config.js"},
56 56 configDirective = "tbFilterNodeGpsGeofencingConfig",
57   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  57 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
58 58 )
59 59 public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode<TbGpsGeofencingFilterNodeConfiguration> {
60 60
... ...
... ... @@ -53,7 +53,7 @@ import java.util.Properties;
53 53 uiResources = {"static/rulenode/rulenode-core-config.js"},
54 54 configDirective = "tbActionNodeKafkaConfig",
55 55 iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==",
56   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  56 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
57 57 )
58 58 public class TbKafkaNode implements TbNode {
59 59
... ...
... ... @@ -42,7 +42,7 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE;
42 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 43 configDirective = "tbTransformationNodeToEmailConfig",
44 44 icon = "email",
45   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  45 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
46 46 )
47 47 public class TbMsgToEmailNode implements TbNode {
48 48
... ...
... ... @@ -48,7 +48,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
48 48 uiResources = {"static/rulenode/rulenode-core-config.js"},
49 49 configDirective = "tbActionNodeSendEmailConfig",
50 50 icon = "send",
51   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  51 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
52 52 )
53 53 public class TbSendEmailNode implements TbNode {
54 54
... ...
... ... @@ -42,7 +42,7 @@ import org.thingsboard.server.common.msg.TbMsg;
42 42 "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ",
43 43 uiResources = {"static/rulenode/rulenode-core-config.js"},
44 44 configDirective = "tbEnrichmentNodeOriginatorAttributesConfig",
45   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  45 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
46 46 )
47 47 public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> {
48 48
... ...
... ... @@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
35 35 "<code>metadata.temperature</code>.",
36 36 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
37 37 configDirective = "tbEnrichmentNodeCustomerAttributesConfig",
38   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  38 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
39 39 )
40 40 public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> {
41 41
... ...
... ... @@ -44,7 +44,7 @@ import org.thingsboard.server.common.msg.TbMsg;
44 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 45 uiResources = {"static/rulenode/rulenode-core-config.js"},
46 46 configDirective = "tbEnrichmentNodeEntityDetailsConfig",
47   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  47 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
48 48 )
49 49 public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration> {
50 50
... ...
... ... @@ -40,7 +40,7 @@ import org.thingsboard.server.common.msg.TbMsg;
40 40 "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ",
41 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 42 configDirective = "tbEnrichmentNodeDeviceAttributesConfig",
43   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  43 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
44 44 )
45 45 public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> {
46 46
... ...
... ... @@ -45,7 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
45 45 nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.",
46 46 uiResources = {"static/rulenode/rulenode-core-config.js"},
47 47 configDirective = "tbEnrichmentNodeOriginatorFieldsConfig",
48   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  48 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
49 49 )
50 50 public class TbGetOriginatorFieldsNode implements TbNode {
51 51
... ...
... ... @@ -37,7 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
37 37 "<code>metadata.temperature</code>.",
38 38 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
39 39 configDirective = "tbEnrichmentNodeRelatedAttributesConfig",
40   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  40 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
41 41 )
42 42
43 43 public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {
... ...
... ... @@ -68,7 +68,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE;
68 68 "<b>Note</b>: The maximum size of the fetched array is 1000 records.\n ",
69 69 uiResources = {"static/rulenode/rulenode-core-config.js"},
70 70 configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase",
71   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  71 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
72 72 )
73 73 public class TbGetTelemetryNode implements TbNode {
74 74
... ...
... ... @@ -37,7 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
37 37 "<code>metadata.temperature</code>.",
38 38 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
39 39 configDirective = "tbEnrichmentNodeTenantAttributesConfig",
40   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  40 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
41 41 )
42 42 public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> {
43 43
... ...
... ... @@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg;
39 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 40 uiResources = {"static/rulenode/rulenode-core-config.js"},
41 41 configDirective = "tbEnrichmentNodeEntityDetailsConfig",
42   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  42 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
43 43 )
44 44 public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration> {
45 45
... ...
... ... @@ -51,7 +51,7 @@ import java.util.concurrent.TimeoutException;
51 51 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
52 52 configDirective = "tbActionNodeMqttConfig",
53 53 icon = "call_split",
54   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  54 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
55 55 )
56 56 public class TbMqttNode implements TbNode {
57 57
... ...
... ... @@ -41,7 +41,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
41 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 42 configDirective = "tbActionNodeRabbitMqConfig",
43 43 iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=",
44   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  44 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
45 45 )
46 46 public class TbRabbitMqNode implements TbNode {
47 47
... ...
... ... @@ -41,7 +41,7 @@ import org.thingsboard.server.common.msg.TbMsg;
41 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 42 configDirective = "tbActionNodeRestApiCallConfig",
43 43 iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+",
44   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  44 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
45 45 )
46 46 public class TbRestApiCallNode implements TbNode {
47 47
... ...
... ... @@ -41,7 +41,7 @@ import java.util.UUID;
41 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 42 configDirective = "tbActionNodeRpcReplyConfig",
43 43 icon = "call_merge",
44   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  44 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
45 45 )
46 46 public class TbSendRPCReplyNode implements TbNode {
47 47
... ...
... ... @@ -52,7 +52,7 @@ import java.util.concurrent.TimeUnit;
52 52 uiResources = {"static/rulenode/rulenode-core-config.js"},
53 53 configDirective = "tbActionNodeRpcRequestConfig",
54 54 icon = "call_made",
55   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  55 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
56 56 )
57 57 public class TbSendRPCRequestNode implements TbNode {
58 58
... ...
... ... @@ -46,7 +46,7 @@ import java.util.Set;
46 46 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
47 47 configDirective = "tbActionNodeAttributesConfig",
48 48 icon = "file_upload",
49   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  49 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
50 50 )
51 51 public class TbMsgAttributesNode implements TbNode {
52 52
... ...
... ... @@ -47,7 +47,7 @@ import java.util.Map;
47 47 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
48 48 configDirective = "tbActionNodeTimeseriesConfig",
49 49 icon = "file_upload",
50   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  50 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
51 51 )
52 52 public class TbMsgTimeseriesNode implements TbNode {
53 53
... ...
... ... @@ -40,7 +40,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
40 40 "Size of the queue per originator and timeout values are configurable on a system level",
41 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 42 configDirective = "tbNodeEmptyConfig",
43   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  43 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
44 44 )
45 45 @Deprecated
46 46 public class TbSynchronizationBeginNode implements TbNode {
... ...
... ... @@ -40,7 +40,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
40 40 nodeDetails = "",
41 41 uiResources = {"static/rulenode/rulenode-core-config.js"},
42 42 configDirective = ("tbNodeEmptyConfig"),
43   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  43 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
44 44 )
45 45 @Deprecated
46 46 public class TbSynchronizationEndNode implements TbNode {
... ...
... ... @@ -48,7 +48,7 @@ import java.util.HashSet;
48 48 uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
49 49 configDirective = "tbTransformationNodeChangeOriginatorConfig",
50 50 icon = "find_replace",
51   - ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE}
  51 + ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
52 52 )
53 53 public class TbChangeOriginatorNode extends TbAbstractTransformNode {
54 54
... ...