Browse Source

Refactoring notification engine

pull/2436/head
Volodymyr Babak 6 years ago
parent
commit
cd2908fb59
  1. 6
      application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
  2. 6
      application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
  3. 32
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java
  4. 4
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java
  5. 2
      application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
  6. 4
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  7. 9
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  8. 60
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  9. 8
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  10. 12
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  11. 7
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  12. 9
      application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java
  13. 10
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  14. 32
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
  15. 4
      application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java
  16. 183
      application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java
  17. 18
      application/src/main/java/org/thingsboard/server/service/edge/EdgeNotificationService.java
  18. 100
      application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
  19. 2
      application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
  20. 35
      common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java
  21. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java
  22. 3
      common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
  23. 1
      common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java
  24. 50
      common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java
  25. 2
      common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java
  26. 35
      common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeEventId.java
  27. 2
      common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainType.java
  28. 4
      common/edge-api/pom.xml
  29. 9
      common/edge-api/src/main/proto/edge.proto
  30. 8
      common/queue/src/main/proto/queue.proto
  31. 85
      dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java
  32. 51
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeEventDao.java
  33. 2
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java
  34. 10
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  35. 135
      dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEventEntity.java
  36. 121
      dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java
  37. 27
      dao/src/main/java/org/thingsboard/server/dao/model/type/EdgeEventTypeCodec.java
  38. 6
      dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
  39. 26
      dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeEventRepository.java
  40. 112
      dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java
  41. 11
      dao/src/main/resources/sql/schema-entities-hsql.sql
  42. 12
      dao/src/main/resources/sql/schema-entities.sql
  43. 4
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  44. 108
      dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java
  45. 2
      dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java
  46. 12
      dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java
  47. 23
      dao/src/test/java/org/thingsboard/server/dao/service/nosql/EdgeEventServiceNoSqlTest.java
  48. 4
      dao/src/test/java/org/thingsboard/server/dao/service/nosql/EdgeServiceNoSqlTest.java
  49. 12
      dao/src/test/java/org/thingsboard/server/dao/service/sql/EdgeEventServiceSqlTest.java
  50. 4
      dao/src/test/java/org/thingsboard/server/dao/service/sql/EdgeServiceSqlTest.java
  51. 3
      dao/src/test/resources/sql/hsql/drop-all-tables.sql
  52. 2
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java
  53. 3
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
  54. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java
  55. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java
  56. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java
  57. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java
  58. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java
  59. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java
  60. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java
  61. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java
  62. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java
  63. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java
  64. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java
  65. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java
  66. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java
  67. 41
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/PushToEdgeNodeCallback.java
  68. 97
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java
  69. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java
  70. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java
  71. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
  72. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
  73. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
  74. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java
  75. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java
  76. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java
  77. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java
  78. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java
  79. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java
  80. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java
  81. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java
  82. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java
  83. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
  84. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
  85. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java
  86. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java
  87. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java
  88. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
  89. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java
  90. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
  91. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java
  92. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java
  93. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java
  94. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java
  95. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java
  96. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java
  97. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java
  98. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java
  99. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java
  100. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java

6
application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java

@ -58,6 +58,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.ClaimDevicesService; import org.thingsboard.server.dao.device.ClaimDevicesService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.event.EventService;
@ -258,6 +259,11 @@ public class ActorSystemContext {
@Getter @Getter
private EdgeService edgeService; private EdgeService edgeService;
@Lazy
@Autowired
@Getter
private EdgeEventService edgeEventService;
@Value("${actors.session.max_concurrent_sessions_per_device:1}") @Value("${actors.session.max_concurrent_sessions_per_device:1}")
@Getter @Getter
private long maxConcurrentSessionsPerDevice; private long maxConcurrentSessionsPerDevice;

6
application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java

@ -51,6 +51,7 @@ import org.thingsboard.server.dao.cassandra.CassandraCluster;
import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.nosql.CassandraStatementTask; import org.thingsboard.server.dao.nosql.CassandraStatementTask;
@ -406,6 +407,11 @@ class DefaultTbContext implements TbContext {
return mainCtx.getEdgeService(); return mainCtx.getEdgeService();
} }
@Override
public EdgeEventService getEdgeEventService() {
return mainCtx.getEdgeEventService();
}
@Override @Override
public EventLoopGroup getSharedEventLoop() { public EventLoopGroup getSharedEventLoop() {
return mainCtx.getSharedEventLoopGroupService().getSharedEventLoopGroup(); return mainCtx.getSharedEventLoopGroupService().getSharedEventLoopGroup();

32
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java

@ -18,14 +18,11 @@ package org.thingsboard.server.actors.ruleChain;
import akka.actor.ActorContext; import akka.actor.ActorContext;
import akka.actor.ActorRef; import akka.actor.ActorRef;
import akka.actor.Props; import akka.actor.Props;
import com.google.common.util.concurrent.FutureCallback;
import com.sun.istack.Nullable;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.api.TbRelationTypes; import org.thingsboard.rule.engine.api.TbRelationTypes;
import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.actors.service.DefaultActorService; import org.thingsboard.server.actors.service.DefaultActorService;
import org.thingsboard.server.actors.shared.ComponentMsgProcessor; import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
@ -102,7 +99,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
if (!started) { if (!started) {
RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
if (ruleChain != null) { if (ruleChain != null) {
if (ruleChain.getType().equals(RuleChainType.SYSTEM)) { if (ruleChain.getType().equals(RuleChainType.CORE)) {
List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId); List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
log.trace("[{}][{}] Starting rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); log.trace("[{}][{}] Starting rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
// Creating and starting the actors; // Creating and starting the actors;
@ -124,7 +121,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
public void onUpdate(ActorContext context) { public void onUpdate(ActorContext context) {
RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
if (ruleChain != null) { if (ruleChain != null) {
if (ruleChain.getType().equals(RuleChainType.SYSTEM)) { if (ruleChain.getType().equals(RuleChainType.CORE)) {
ruleChainName = ruleChain.getName(); ruleChainName = ruleChain.getName();
List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId); List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
@ -224,7 +221,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
if (targetCtx != null) { if (targetCtx != null) {
log.trace("[{}][{}] Pushing message to target rule node", entityId, targetId); log.trace("[{}][{}] Pushing message to target rule node", entityId, targetId);
pushMsgToNode(targetCtx, msg, ""); pushMsgToNode(targetCtx, msg, "");
pushUpdatesToEdges(msg);
} else { } else {
log.trace("[{}][{}] Rule node does not exist. Probably old message", entityId, targetId); log.trace("[{}][{}] Rule node does not exist. Probably old message", entityId, targetId);
msg.getCallback().onSuccess(); msg.getCallback().onSuccess();
@ -354,30 +350,6 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
} }
} }
private void pushUpdatesToEdges(TbMsg msg) {
switch (msg.getType()) {
case DataConstants.ENTITY_CREATED:
case DataConstants.ENTITY_UPDATED:
case DataConstants.ENTITY_DELETED:
case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
case DataConstants.ALARM_ACK:
case DataConstants.ALARM_CLEAR:
edgeService.pushEventToEdge(tenantId, msg, new FutureCallback<Void>() {
@Override
public void onSuccess(@Nullable Void aVoid) {
log.debug("Event saved successfully!");
}
@Override
public void onFailure(Throwable t) {
log.debug("Failure during event save", t);
}
});
}
}
@Override @Override
protected RuleNodeException getInactiveException() { protected RuleNodeException getInactiveException() {
RuleNode firstRuleNode = firstNode != null ? firstNode.getSelf() : null; RuleNode firstRuleNode = firstNode != null ? firstNode.getSelf() : null;

4
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java

@ -56,7 +56,7 @@ public abstract class RuleChainManagerActor extends ContextAwareActor {
} }
protected void initRuleChains() { protected void initRuleChains() {
for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, link), ContextAwareActor.ENTITY_PACK_LIMIT)) { for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, link), ContextAwareActor.ENTITY_PACK_LIMIT)) {
RuleChainId ruleChainId = ruleChain.getId(); RuleChainId ruleChainId = ruleChain.getId();
log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId()); log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId());
//TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa. //TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa.
@ -67,7 +67,7 @@ public abstract class RuleChainManagerActor extends ContextAwareActor {
} }
protected void visit(RuleChain entity, ActorRef actorRef) { protected void visit(RuleChain entity, ActorRef actorRef) {
if (entity != null && entity.isRoot() && entity.getType().equals(RuleChainType.SYSTEM)) { if (entity != null && entity.isRoot() && entity.getType().equals(RuleChainType.CORE)) {
rootChain = entity; rootChain = entity;
rootChainActor = actorRef; rootChainActor = actorRef;
} }

2
application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java

@ -206,7 +206,7 @@ public class TenantActor extends RuleChainManagerActor {
if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) { if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) {
RuleChain ruleChain = systemContext.getRuleChainService(). RuleChain ruleChain = systemContext.getRuleChainService().
findRuleChainById(tenantId, new RuleChainId(msg.getEntityId().getId())); findRuleChainById(tenantId, new RuleChainId(msg.getEntityId().getId()));
if (ruleChain != null && ruleChain.getType().equals(RuleChainType.SYSTEM)) { if (ruleChain != null && ruleChain.getType().equals(RuleChainType.CORE)) {
visit(ruleChain, target); visit(ruleChain, target);
} }
} }

4
application/src/main/java/org/thingsboard/server/controller/AlarmController.java

@ -125,6 +125,8 @@ public class AlarmController extends BaseController {
alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, ackTs).get(); alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, ackTs).get();
alarm.setAckTs(ackTs); alarm.setAckTs(ackTs);
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null); logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null);
sendNotificationMsgToEdgeService(getTenantId(), alarmId, ActionType.ALARM_ACK);
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
} }
@ -142,6 +144,8 @@ public class AlarmController extends BaseController {
alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, clearTs).get(); alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, clearTs).get();
alarm.setClearTs(clearTs); alarm.setClearTs(clearTs);
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null); logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null);
sendNotificationMsgToEdgeService(getTenantId(), alarmId, ActionType.ALARM_CLEAR);
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
} }

9
application/src/main/java/org/thingsboard/server/controller/AssetController.java

@ -27,12 +27,14 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.AssetSearchQuery; import org.thingsboard.server.common.data.asset.AssetSearchQuery;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
@ -86,6 +88,8 @@ public class AssetController extends BaseController {
Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
sendNotificationMsgToEdgeService(savedAsset.getTenantId(), savedAsset.getId(), EdgeEventType.ASSET, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
logEntityAction(savedAsset.getId(), savedAsset, logEntityAction(savedAsset.getId(), savedAsset,
savedAsset.getCustomerId(), savedAsset.getCustomerId(),
asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
@ -112,6 +116,7 @@ public class AssetController extends BaseController {
asset.getCustomerId(), asset.getCustomerId(),
ActionType.DELETED, null, strAssetId); ActionType.DELETED, null, strAssetId);
sendNotificationMsgToEdgeService(getTenantId(), assetId, EdgeEventType.ASSET, ActionType.DELETED);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), logEntityAction(emptyId(EntityType.ASSET),
null, null,
@ -354,6 +359,8 @@ public class AssetController extends BaseController {
savedAsset.getCustomerId(), savedAsset.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strAssetId, strEdgeId, edge.getName()); ActionType.ASSIGNED_TO_EDGE, null, strAssetId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(), EdgeEventType.ASSET, ActionType.ASSIGNED_TO_EDGE);
return savedAsset; return savedAsset;
} catch (Exception e) { } catch (Exception e) {
@ -385,6 +392,8 @@ public class AssetController extends BaseController {
asset.getCustomerId(), asset.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strAssetId, edge.getId().toString(), edge.getName()); ActionType.UNASSIGNED_FROM_EDGE, null, strAssetId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(), EdgeEventType.ASSET, ActionType.UNASSIGNED_FROM_EDGE);
return savedAsset; return savedAsset;
} catch (Exception e) { } catch (Exception e) {

60
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.Asset;
@ -66,6 +67,7 @@ import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
@ -83,6 +85,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.ClaimDevicesService; import org.thingsboard.server.dao.device.ClaimDevicesService;
import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
@ -95,10 +98,12 @@ import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.component.ComponentDiscoveryService; import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.queue.TbClusterService;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.AccessControlService; import org.thingsboard.server.service.security.permission.AccessControlService;
@ -108,6 +113,7 @@ import org.thingsboard.server.service.state.DeviceStateService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.management.relation.Relation;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -200,6 +206,12 @@ public abstract class BaseController {
@Autowired @Autowired
protected EdgeService edgeService; protected EdgeService edgeService;
@Autowired
protected EdgeNotificationService edgeNotificationService;
@Autowired
protected EdgeEventService edgeEventService;
@Value("${server.log_controller_error_stack_trace}") @Value("${server.log_controller_error_stack_trace}")
@Getter @Getter
private boolean logControllerErrorStackTrace; private boolean logControllerErrorStackTrace;
@ -559,7 +571,6 @@ public abstract class BaseController {
} }
if (e == null) { if (e == null) {
pushEntityActionToRuleEngine(entityId, entity, user, customerId, actionType, additionalInfo); pushEntityActionToRuleEngine(entityId, entity, user, customerId, actionType, additionalInfo);
// TODO: voba - refactor to push events to edge queue directly, instead of the rule engine flow
} }
auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo); auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo);
} }
@ -600,16 +611,6 @@ public abstract class BaseController {
case ALARM_CLEAR: case ALARM_CLEAR:
msgType = DataConstants.ALARM_CLEAR; msgType = DataConstants.ALARM_CLEAR;
break; break;
case ASSIGNED_TO_EDGE:
msgType = DataConstants.ENTITY_ASSIGNED_TO_EDGE;
break;
case UNASSIGNED_FROM_EDGE:
msgType = DataConstants.ENTITY_UNASSIGNED_FROM_EDGE;
break;
case CREDENTIALS_UPDATED:
//TODO: voba - this is not efficient way to do this. Refactor on later stages
msgType = DataConstants.ENTITY_UPDATED;
break;
} }
if (!StringUtils.isEmpty(msgType)) { if (!StringUtils.isEmpty(msgType)) {
try { try {
@ -698,5 +699,42 @@ public abstract class BaseController {
return result; return result;
} }
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) {
try {
sendNotificationMsgToEdgeService(tenantId, null, json.writeValueAsString(relation), EdgeEventType.RELATION, edgeEventAction);
} catch (Exception e) {
log.warn("Failed to push relation to core: {}", relation, e);
}
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) {
EdgeEventType edgeEventType = edgeEventService.getEdgeEventTypeByEntityType(entityId.getEntityType());
if (edgeEventType != null) {
sendNotificationMsgToEdgeService(tenantId, entityId, null, edgeEventType, edgeEventAction);
}
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, EdgeEventType edgeEventType, ActionType edgeEventAction) {
sendNotificationMsgToEdgeService(tenantId, entityId, null, edgeEventType, edgeEventAction);
}
private void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, String entityBody, EdgeEventType edgeEventType, ActionType edgeEventAction) {
TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder();
builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits());
builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits());
builder.setEdgeEventType(edgeEventType.name());
builder.setEdgeEventAction(edgeEventAction.name());
if (entityId != null) {
builder.setEntityIdMSB(entityId.getId().getMostSignificantBits());
builder.setEntityIdLSB(entityId.getId().getLeastSignificantBits());
builder.setEntityType(entityId.getEntityType().name());
}
if (entityBody != null) {
builder.setEntityBody(entityBody);
}
TransportProtos.EdgeNotificationMsgProto msg = builder.build();
tbClusterService.pushMsgToCore(tenantId, entityId != null ? entityId : tenantId,
TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null);
}
} }

8
application/src/main/java/org/thingsboard/server/controller/DashboardController.java

@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.ShortCustomerInfo;
import org.thingsboard.server.common.data.ShortEdgeInfo; import org.thingsboard.server.common.data.ShortEdgeInfo;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.DashboardId;
@ -116,6 +117,9 @@ public class DashboardController extends BaseController {
null, null,
dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(),
EdgeEventType.DASHBOARD, savedDashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedDashboard; return savedDashboard;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), dashboard, logEntityAction(emptyId(EntityType.DASHBOARD), dashboard,
@ -139,6 +143,7 @@ public class DashboardController extends BaseController {
null, null,
ActionType.DELETED, null, strDashboardId); ActionType.DELETED, null, strDashboardId);
sendNotificationMsgToEdgeService(getTenantId(), dashboardId, EdgeEventType.DASHBOARD, ActionType.DELETED);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), logEntityAction(emptyId(EntityType.DASHBOARD),
@ -495,6 +500,7 @@ public class DashboardController extends BaseController {
null, null,
ActionType.ASSIGNED_TO_EDGE, null, strDashboardId, strEdgeId, edge.getName()); ActionType.ASSIGNED_TO_EDGE, null, strDashboardId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedDashboard.getId(), EdgeEventType.DASHBOARD, ActionType.ASSIGNED_TO_EDGE);
return savedDashboard; return savedDashboard;
} catch (Exception e) { } catch (Exception e) {
@ -526,6 +532,8 @@ public class DashboardController extends BaseController {
null, null,
ActionType.UNASSIGNED_FROM_EDGE, null, strDashboardId, edge.getId().toString(), edge.getName()); ActionType.UNASSIGNED_FROM_EDGE, null, strDashboardId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedDashboard.getId(), EdgeEventType.DASHBOARD, ActionType.UNASSIGNED_FROM_EDGE);
return savedDashboard; return savedDashboard;
} catch (Exception e) { } catch (Exception e) {

12
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.device.DeviceSearchQuery; import org.thingsboard.server.common.data.device.DeviceSearchQuery;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
@ -57,6 +58,7 @@ import org.thingsboard.server.dao.device.claim.ClaimResponse;
import org.thingsboard.server.dao.device.claim.ClaimResult; import org.thingsboard.server.dao.device.claim.ClaimResult;
import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
@ -106,6 +108,8 @@ public class DeviceController extends BaseController {
tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(), tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(),
savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null); savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null);
sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(), EdgeEventType.DEVICE, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
logEntityAction(savedDevice.getId(), savedDevice, logEntityAction(savedDevice.getId(), savedDevice,
savedDevice.getCustomerId(), savedDevice.getCustomerId(),
device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
@ -137,6 +141,8 @@ public class DeviceController extends BaseController {
device.getCustomerId(), device.getCustomerId(),
ActionType.DELETED, null, strDeviceId); ActionType.DELETED, null, strDeviceId);
sendNotificationMsgToEdgeService(getTenantId(), deviceId, EdgeEventType.DEVICE, ActionType.DELETED);
deviceStateService.onDeviceDeleted(device); deviceStateService.onDeviceDeleted(device);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), logEntityAction(emptyId(EntityType.DEVICE),
@ -260,6 +266,8 @@ public class DeviceController extends BaseController {
tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null); tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null);
sendNotificationMsgToEdgeService(getTenantId(), device.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED);
logEntityAction(device.getId(), device, logEntityAction(device.getId(), device,
device.getCustomerId(), device.getCustomerId(),
ActionType.CREDENTIALS_UPDATED, null, deviceCredentials); ActionType.CREDENTIALS_UPDATED, null, deviceCredentials);
@ -509,6 +517,8 @@ public class DeviceController extends BaseController {
savedDevice.getCustomerId(), savedDevice.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strDeviceId, strEdgeId, edge.getName()); ActionType.ASSIGNED_TO_EDGE, null, strDeviceId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedDevice.getId(), EdgeEventType.DEVICE, ActionType.ASSIGNED_TO_EDGE);
return savedDevice; return savedDevice;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null, logEntityAction(emptyId(EntityType.DEVICE), null,
@ -538,6 +548,8 @@ public class DeviceController extends BaseController {
device.getCustomerId(), device.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strDeviceId, edge.getId().toString(), edge.getName()); ActionType.UNASSIGNED_FROM_EDGE, null, strDeviceId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedDevice.getId(), EdgeEventType.DEVICE, ActionType.UNASSIGNED_FROM_EDGE);
return savedDevice; return savedDevice;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null, logEntityAction(emptyId(EntityType.DEVICE), null,

7
application/src/main/java/org/thingsboard/server/controller/EdgeController.java

@ -97,7 +97,7 @@ public class EdgeController extends BaseController {
if (created) { if (created) {
ruleChainService.assignRuleChainToEdge(tenantId, defaultRootEdgeRuleChain.getId(), savedEdge.getId()); ruleChainService.assignRuleChainToEdge(tenantId, defaultRootEdgeRuleChain.getId(), savedEdge.getId());
edgeService.setEdgeRootRuleChain(tenantId, savedEdge, defaultRootEdgeRuleChain.getId()); edgeNotificationService.setEdgeRootRuleChain(tenantId, savedEdge, defaultRootEdgeRuleChain.getId());
edgeService.assignDefaultRuleChainsToEdge(tenantId, savedEdge.getId()); edgeService.assignDefaultRuleChainsToEdge(tenantId, savedEdge.getId());
} }
@ -257,8 +257,7 @@ public class EdgeController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
public Edge getTenantEdge( public Edge getTenantEdge(@RequestParam String edgeName) throws ThingsboardException {
@RequestParam String edgeName) throws ThingsboardException {
try { try {
TenantId tenantId = getCurrentUser().getTenantId(); TenantId tenantId = getCurrentUser().getTenantId();
return checkNotNull(edgeService.findEdgeByTenantIdAndName(tenantId, edgeName)); return checkNotNull(edgeService.findEdgeByTenantIdAndName(tenantId, edgeName));
@ -283,7 +282,7 @@ public class EdgeController extends BaseController {
accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.WRITE, accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.WRITE,
edge.getId(), edge); edge.getId(), edge);
Edge updatedEdge = edgeService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId); Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId);
logEntityAction(updatedEdge.getId(), updatedEdge, null, ActionType.UPDATED, null); logEntityAction(updatedEdge.getId(), updatedEdge, null, ActionType.UPDATED, null);

9
application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java

@ -24,7 +24,9 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
@ -63,10 +65,13 @@ public class EntityRelationController extends BaseController {
relation.setTypeGroup(RelationTypeGroup.COMMON); relation.setTypeGroup(RelationTypeGroup.COMMON);
} }
relationService.saveRelation(getTenantId(), relation); relationService.saveRelation(getTenantId(), relation);
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(), logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, null, relation); ActionType.RELATION_ADD_OR_UPDATE, null, relation);
logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(), logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, null, relation); ActionType.RELATION_ADD_OR_UPDATE, null, relation);
sendNotificationMsgToEdgeService(getTenantId(), relation, ActionType.RELATION_ADD_OR_UPDATE);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(), logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, e, relation); ActionType.RELATION_ADD_OR_UPDATE, e, relation);
@ -104,6 +109,8 @@ public class EntityRelationController extends BaseController {
ActionType.RELATION_DELETED, null, relation); ActionType.RELATION_DELETED, null, relation);
logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(), logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_DELETED, null, relation); ActionType.RELATION_DELETED, null, relation);
sendNotificationMsgToEdgeService(getTenantId(), relation, ActionType.RELATION_DELETED);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(), logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_DELETED, e, relation); ActionType.RELATION_DELETED, e, relation);
@ -125,6 +132,8 @@ public class EntityRelationController extends BaseController {
try { try {
relationService.deleteEntityRelations(getTenantId(), entityId); relationService.deleteEntityRelations(getTenantId(), entityId);
logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, null); logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, null);
sendNotificationMsgToEdgeService(getTenantId(), entityId, ActionType.RELATIONS_DELETED);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, e); logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, e);
throw handleException(e); throw handleException(e);

10
application/src/main/java/org/thingsboard/server/controller/EntityViewController.java

@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
@ -116,6 +117,8 @@ public class EntityViewController extends BaseController {
logEntityAction(savedEntityView.getId(), savedEntityView, null, logEntityAction(savedEntityView.getId(), savedEntityView, null,
entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), EdgeEventType.ENTITY_VIEW, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedEntityView; return savedEntityView;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null,
@ -185,6 +188,8 @@ public class EntityViewController extends BaseController {
entityViewService.deleteEntityView(getTenantId(), entityViewId); entityViewService.deleteEntityView(getTenantId(), entityViewId);
logEntityAction(entityViewId, entityView, entityView.getCustomerId(), logEntityAction(entityViewId, entityView, entityView.getCustomerId(),
ActionType.DELETED, null, strEntityViewId); ActionType.DELETED, null, strEntityViewId);
sendNotificationMsgToEdgeService(getTenantId(), entityViewId, EdgeEventType.ENTITY_VIEW, ActionType.DELETED);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW), logEntityAction(emptyId(EntityType.ENTITY_VIEW),
null, null,
@ -389,6 +394,9 @@ public class EntityViewController extends BaseController {
logEntityAction(entityViewId, savedEntityView, logEntityAction(entityViewId, savedEntityView,
savedEntityView.getCustomerId(), savedEntityView.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strEntityViewId, strEdgeId, edge.getName()); ActionType.ASSIGNED_TO_EDGE, null, strEntityViewId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), EdgeEventType.ENTITY_VIEW, ActionType.ASSIGNED_TO_EDGE);
return savedEntityView; return savedEntityView;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
@ -417,6 +425,8 @@ public class EntityViewController extends BaseController {
entityView.getCustomerId(), entityView.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strEntityViewId, edge.getId().toString(), edge.getName()); ActionType.UNASSIGNED_FROM_EDGE, null, strEntityViewId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(), EdgeEventType.ENTITY_VIEW, ActionType.UNASSIGNED_FROM_EDGE);
return savedEntityView; return savedEntityView;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,

32
application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

@ -41,6 +41,7 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
@ -134,7 +135,7 @@ public class RuleChainController extends BaseController {
RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
if (RuleChainType.SYSTEM.equals(savedRuleChain.getType())) { if (RuleChainType.CORE.equals(savedRuleChain.getType())) {
tbClusterService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(), tbClusterService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(),
created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
} }
@ -143,6 +144,12 @@ public class RuleChainController extends BaseController {
null, null,
created ? ActionType.ADDED : ActionType.UPDATED, null); created ? ActionType.ADDED : ActionType.UPDATED, null);
if (RuleChainType.EDGE.equals(savedRuleChain.getType())) {
sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(),
savedRuleChain.getId(), EdgeEventType.RULE_CHAIN,
savedRuleChain.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
}
return savedRuleChain; return savedRuleChain;
} catch (Exception e) { } catch (Exception e) {
@ -209,7 +216,7 @@ public class RuleChainController extends BaseController {
RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE); RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE);
RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData)); RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData));
if (RuleChainType.SYSTEM.equals(ruleChain.getType())) { if (RuleChainType.CORE.equals(ruleChain.getType())) {
tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED); tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);
} }
@ -217,6 +224,12 @@ public class RuleChainController extends BaseController {
null, null,
ActionType.UPDATED, null, ruleChainMetaData); ActionType.UPDATED, null, ruleChainMetaData);
if (RuleChainType.EDGE.equals(ruleChain.getType())) {
sendNotificationMsgToEdgeService(ruleChain.getTenantId(),
ruleChain.getId(), EdgeEventType.RULE_CHAIN,
ActionType.UPDATED);
}
return savedRuleChainMetaData; return savedRuleChainMetaData;
} catch (Exception e) { } catch (Exception e) {
@ -243,7 +256,7 @@ public class RuleChainController extends BaseController {
RuleChainType type = RuleChainType.valueOf(typeStr); RuleChainType type = RuleChainType.valueOf(typeStr);
return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink)); return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink));
} else { } else {
return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink)); return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink));
} }
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
@ -267,7 +280,7 @@ public class RuleChainController extends BaseController {
referencingRuleChainIds.remove(ruleChain.getId()); referencingRuleChainIds.remove(ruleChain.getId());
if (RuleChainType.SYSTEM.equals(ruleChain.getType())) { if (RuleChainType.CORE.equals(ruleChain.getType())) {
referencingRuleChainIds.forEach(referencingRuleChainId -> referencingRuleChainIds.forEach(referencingRuleChainId ->
tbClusterService.onEntityStateChange(ruleChain.getTenantId(), referencingRuleChainId, ComponentLifecycleEvent.UPDATED)); tbClusterService.onEntityStateChange(ruleChain.getTenantId(), referencingRuleChainId, ComponentLifecycleEvent.UPDATED));
@ -278,6 +291,12 @@ public class RuleChainController extends BaseController {
null, null,
ActionType.DELETED, null, strRuleChainId); ActionType.DELETED, null, strRuleChainId);
if (RuleChainType.EDGE.equals(ruleChain.getType())) {
sendNotificationMsgToEdgeService(ruleChain.getTenantId(),
ruleChain.getId(), EdgeEventType.RULE_CHAIN,
ActionType.DELETED);
}
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.RULE_CHAIN), logEntityAction(emptyId(EntityType.RULE_CHAIN),
null, null,
@ -407,6 +426,8 @@ public class RuleChainController extends BaseController {
null, null,
ActionType.ASSIGNED_TO_EDGE, null, strRuleChainId, strEdgeId, edge.getName()); ActionType.ASSIGNED_TO_EDGE, null, strRuleChainId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedRuleChain.getId(),
EdgeEventType.RULE_CHAIN, ActionType.ASSIGNED_TO_EDGE);
return savedRuleChain; return savedRuleChain;
} catch (Exception e) { } catch (Exception e) {
@ -438,6 +459,9 @@ public class RuleChainController extends BaseController {
null, null,
ActionType.UNASSIGNED_FROM_EDGE, null, strRuleChainId, edge.getId().toString(), edge.getName()); ActionType.UNASSIGNED_FROM_EDGE, null, strRuleChainId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), savedRuleChain.getId(),
EdgeEventType.RULE_CHAIN, ActionType.UNASSIGNED_FROM_EDGE);
return savedRuleChain; return savedRuleChain;
} catch (Exception e) { } catch (Exception e) {

4
application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java

@ -116,7 +116,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
} }
private void putComponentIntoMaps(ComponentType type, RuleNode ruleNodeAnnotation, ComponentDescriptor component) { private void putComponentIntoMaps(ComponentType type, RuleNode ruleNodeAnnotation, ComponentDescriptor component) {
if (ruleChainTypeContainsArray(RuleChainType.SYSTEM, ruleNodeAnnotation.ruleChainTypes())) { if (ruleChainTypeContainsArray(RuleChainType.CORE, ruleNodeAnnotation.ruleChainTypes())) {
systemComponentsMap.computeIfAbsent(type, k -> new ArrayList<>()).add(component); systemComponentsMap.computeIfAbsent(type, k -> new ArrayList<>()).add(component);
} }
if (ruleChainTypeContainsArray(RuleChainType.EDGE, ruleNodeAnnotation.ruleChainTypes())) { if (ruleChainTypeContainsArray(RuleChainType.EDGE, ruleNodeAnnotation.ruleChainTypes())) {
@ -225,7 +225,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
@Override @Override
public List<ComponentDescriptor> getComponents(Set<ComponentType> types, RuleChainType ruleChainType) { public List<ComponentDescriptor> getComponents(Set<ComponentType> types, RuleChainType ruleChainType) {
if (RuleChainType.SYSTEM.equals(ruleChainType)) { if (RuleChainType.CORE.equals(ruleChainType)) {
return getComponents(types, systemComponentsMap); return getComponents(types, systemComponentsMap);
} else if (RuleChainType.EDGE.equals(ruleChainType)) { } else if (RuleChainType.EDGE.equals(ruleChainType)) {
return getComponents(types, edgeComponentsMap); return getComponents(types, edgeComponentsMap);

183
application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.edge; package org.thingsboard.server.service.edge;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -17,9 +32,10 @@ import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeQueueEntityType; import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeQueueEntry; import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
@ -36,6 +52,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.event.EventService;
@ -79,7 +96,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
private RelationService relationService; private RelationService relationService;
@Autowired @Autowired
private EventService eventService; private EdgeEventService edgeEventService;
private ExecutorService tsCallBackExecutor; private ExecutorService tsCallBackExecutor;
@ -96,8 +113,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
} }
@Override @Override
public TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) { public TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
return eventService.findEvents(tenantId, edgeId, DataConstants.EDGE_QUEUE_EVENT_TYPE, pageLink); return edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink);
} }
@Override @Override
@ -105,7 +122,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
edge.setRootRuleChainId(ruleChainId); edge.setRootRuleChainId(ruleChainId);
Edge savedEdge = edgeService.saveEdge(edge); Edge savedEdge = edgeService.saveEdge(edge);
RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId); RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId);
saveEventToEdgeQueue(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, DataConstants.ENTITY_UPDATED, mapper.writeValueAsString(ruleChain), new FutureCallback<Void>() { saveEventToEdgeQueue(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, DataConstants.ENTITY_UPDATED, mapper.writeValueAsString(ruleChain), new FutureCallback<Void>() {
@Override @Override
public void onSuccess(@Nullable Void aVoid) { public void onSuccess(@Nullable Void aVoid) {
log.debug("Event saved successfully!"); log.debug("Event saved successfully!");
@ -119,28 +136,28 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
return savedEdge; return savedEdge;
} }
private void saveEventToEdgeQueue(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, String type, String data, FutureCallback<Void> callback) throws IOException { private void saveEventToEdgeQueue(TenantId tenantId, EdgeId edgeId, EdgeEventType entityType, String type, String data, FutureCallback<Void> callback) throws IOException {
log.debug("Pushing single event to edge queue. tenantId [{}], edgeId [{}], entityType [{}], type[{}], data [{}]", tenantId, edgeId, entityType, type, data); log.debug("Pushing single event to edge queue. tenantId [{}], edgeId [{}], entityType [{}], type[{}], data [{}]", tenantId, edgeId, entityType, type, data);
EdgeQueueEntry queueEntry = new EdgeQueueEntry(); // EdgeEQueueEntry queueEntry = new EdgeQueueEntry();
queueEntry.setEntityType(entityType); // queueEntry.setEntityType(entityType);
queueEntry.setType(type); // queueEntry.setType(type);
queueEntry.setData(data); // queueEntry.setData(data);
Event event = new Event(); EdgeEvent edgeEvent = new EdgeEvent();
event.setEntityId(edgeId); edgeEvent.setEdgeId(edgeId);
event.setTenantId(tenantId); edgeEvent.setTenantId(tenantId);
event.setType(DataConstants.EDGE_QUEUE_EVENT_TYPE); // event.setType(DataConstants.EDGE_QUEUE_EVENT_TYPE);
event.setBody(mapper.valueToTree(queueEntry)); // event.setBody(mapper.valueToTree(queueEntry));
ListenableFuture<Event> saveFuture = eventService.saveAsync(event); ListenableFuture<EdgeEvent> saveFuture = edgeEventService.saveAsync(edgeEvent);
addMainCallback(saveFuture, callback); addMainCallback(saveFuture, callback);
} }
private void addMainCallback(ListenableFuture<Event> saveFuture, final FutureCallback<Void> callback) { private void addMainCallback(ListenableFuture<EdgeEvent> saveFuture, final FutureCallback<Void> callback) {
Futures.addCallback(saveFuture, new FutureCallback<Event>() { Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
@Override @Override
public void onSuccess(@Nullable Event result) { public void onSuccess(@Nullable EdgeEvent result) {
callback.onSuccess(null); callback.onSuccess(null);
} }
@ -153,52 +170,52 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
@Override @Override
public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) { public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) {
if (tbMsg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) || // if (tbMsg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) ||
tbMsg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) || // tbMsg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
tbMsg.getType().equals(DataConstants.ATTRIBUTES_UPDATED) || // tbMsg.getType().equals(DataConstants.ATTRIBUTES_UPDATED) ||
tbMsg.getType().equals(DataConstants.ATTRIBUTES_DELETED)) { // tbMsg.getType().equals(DataConstants.ATTRIBUTES_DELETED)) {
processCustomTbMsg(tenantId, tbMsg, callback); // processCustomTbMsg(tenantId, tbMsg, callback);
} else { // } else {
try { // try {
switch (tbMsg.getOriginator().getEntityType()) { // switch (tbMsg.getOriginator().getEntityType()) {
case EDGE: // case EDGE:
processEdge(tenantId, tbMsg, callback); // processEdge(tenantId, tbMsg, callback);
break; // break;
case ASSET: // case ASSET:
processAsset(tenantId, tbMsg, callback); // processAsset(tenantId, tbMsg, callback);
break; // break;
case DEVICE: // case DEVICE:
processDevice(tenantId, tbMsg, callback); // processDevice(tenantId, tbMsg, callback);
break; // break;
case DASHBOARD: // case DASHBOARD:
processDashboard(tenantId, tbMsg, callback); // processDashboard(tenantId, tbMsg, callback);
break; // break;
case RULE_CHAIN: // case RULE_CHAIN:
processRuleChain(tenantId, tbMsg, callback); // processRuleChain(tenantId, tbMsg, callback);
break; // break;
case ENTITY_VIEW: // case ENTITY_VIEW:
processEntityView(tenantId, tbMsg, callback); // processEntityView(tenantId, tbMsg, callback);
break; // break;
case ALARM: // case ALARM:
processAlarm(tenantId, tbMsg, callback); // processAlarm(tenantId, tbMsg, callback);
break; // break;
default: // default:
log.debug("Entity type [{}] is not designed to be pushed to edge", tbMsg.getOriginator().getEntityType()); // log.debug("Entity type [{}] is not designed to be pushed to edge", tbMsg.getOriginator().getEntityType());
} // }
} catch (IOException e) { // } catch (IOException e) {
log.error("Can't push to edge updates, entity type [{}], data [{}]", tbMsg.getOriginator().getEntityType(), tbMsg.getData(), e); // log.error("Can't push to edge updates, entity type [{}], data [{}]", tbMsg.getOriginator().getEntityType(), tbMsg.getData(), e);
} // }
} // }
} }
private void processCustomTbMsg(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) { private void processCustomTbMsg(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) {
ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, tbMsg.getOriginator()); ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, tbMsg.getOriginator());
Futures.transform(edgeIdFuture, edgeId -> { Futures.transform(edgeIdFuture, edgeId -> {
EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(tbMsg.getOriginator().getEntityType()); EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(tbMsg.getOriginator().getEntityType());
if (edgeId != null && edgeQueueEntityType != null) { if (edgeId != null && edgeEventType != null) {
try { try {
saveEventToEdgeQueue(tenantId, edgeId, edgeQueueEntityType, tbMsg.getType(), Base64.encodeBase64String(TbMsg.toByteArray(tbMsg)), callback); saveEventToEdgeQueue(tenantId, edgeId, edgeEventType, tbMsg.getType(), Base64.encodeBase64String(TbMsg.toByteArray(tbMsg)), callback);
} catch (IOException e) { } catch (IOException e) {
log.error("Error while saving custom tbMsg into Edge Queue", e); log.error("Error while saving custom tbMsg into Edge Queue", e);
} }
@ -211,13 +228,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
switch (tbMsg.getType()) { switch (tbMsg.getType()) {
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DEVICE, callback); processAssignedEntity(tenantId, tbMsg, EdgeEventType.DEVICE, callback);
break; break;
case DataConstants.ENTITY_DELETED: case DataConstants.ENTITY_DELETED:
case DataConstants.ENTITY_CREATED: case DataConstants.ENTITY_CREATED:
case DataConstants.ENTITY_UPDATED: case DataConstants.ENTITY_UPDATED:
Device device = mapper.readValue(tbMsg.getData(), Device.class); Device device = mapper.readValue(tbMsg.getData(), Device.class);
pushEventToEdge(tenantId, device.getId(), EdgeQueueEntityType.DEVICE, tbMsg, callback); pushEventToEdge(tenantId, device.getId(), EdgeEventType.DEVICE, tbMsg, callback);
break; break;
default: default:
log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg); log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
@ -240,13 +257,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
switch (tbMsg.getType()) { switch (tbMsg.getType()) {
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ASSET, callback); processAssignedEntity(tenantId, tbMsg, EdgeEventType.ASSET, callback);
break; break;
case DataConstants.ENTITY_DELETED: case DataConstants.ENTITY_DELETED:
case DataConstants.ENTITY_CREATED: case DataConstants.ENTITY_CREATED:
case DataConstants.ENTITY_UPDATED: case DataConstants.ENTITY_UPDATED:
Asset asset = mapper.readValue(tbMsg.getData(), Asset.class); Asset asset = mapper.readValue(tbMsg.getData(), Asset.class);
pushEventToEdge(tenantId, asset.getId(), EdgeQueueEntityType.ASSET, tbMsg, callback); pushEventToEdge(tenantId, asset.getId(), EdgeEventType.ASSET, tbMsg, callback);
break; break;
default: default:
log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg); log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
@ -257,13 +274,13 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
switch (tbMsg.getType()) { switch (tbMsg.getType()) {
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ENTITY_VIEW, callback); processAssignedEntity(tenantId, tbMsg, EdgeEventType.ENTITY_VIEW, callback);
break; break;
case DataConstants.ENTITY_DELETED: case DataConstants.ENTITY_DELETED:
case DataConstants.ENTITY_CREATED: case DataConstants.ENTITY_CREATED:
case DataConstants.ENTITY_UPDATED: case DataConstants.ENTITY_UPDATED:
EntityView entityView = mapper.readValue(tbMsg.getData(), EntityView.class); EntityView entityView = mapper.readValue(tbMsg.getData(), EntityView.class);
pushEventToEdge(tenantId, entityView.getId(), EdgeQueueEntityType.ENTITY_VIEW, tbMsg, callback); pushEventToEdge(tenantId, entityView.getId(), EdgeEventType.ENTITY_VIEW, tbMsg, callback);
break; break;
default: default:
log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg); log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
@ -278,9 +295,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
case DataConstants.ALARM_ACK: case DataConstants.ALARM_ACK:
case DataConstants.ALARM_CLEAR: case DataConstants.ALARM_CLEAR:
Alarm alarm = mapper.readValue(tbMsg.getData(), Alarm.class); Alarm alarm = mapper.readValue(tbMsg.getData(), Alarm.class);
EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType()); EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType());
if (edgeQueueEntityType != null) { if (edgeEventType != null) {
pushEventToEdge(tenantId, alarm.getOriginator(), EdgeQueueEntityType.ALARM, tbMsg, callback); pushEventToEdge(tenantId, alarm.getOriginator(), EdgeEventType.ALARM, tbMsg, callback);
} }
break; break;
default: default:
@ -292,7 +309,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
switch (tbMsg.getType()) { switch (tbMsg.getType()) {
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DASHBOARD, callback); processAssignedEntity(tenantId, tbMsg, EdgeEventType.DASHBOARD, callback);
break; break;
case DataConstants.ENTITY_DELETED: case DataConstants.ENTITY_DELETED:
case DataConstants.ENTITY_CREATED: case DataConstants.ENTITY_CREATED:
@ -303,7 +320,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) { if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {
try { try {
for (Edge edge : edges.getData()) { for (Edge edge : edges.getData()) {
pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.DASHBOARD, tbMsg, callback); pushEventToEdge(tenantId, edge.getId(), EdgeEventType.DASHBOARD, tbMsg, callback);
} }
} catch (IOException e) { } catch (IOException e) {
log.error("Can't push event to edge", e); log.error("Can't push event to edge", e);
@ -321,7 +338,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
switch (tbMsg.getType()) { switch (tbMsg.getType()) {
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.RULE_CHAIN, callback); processAssignedEntity(tenantId, tbMsg, EdgeEventType.RULE_CHAIN, callback);
break; break;
case DataConstants.ENTITY_DELETED: case DataConstants.ENTITY_DELETED:
case DataConstants.ENTITY_CREATED: case DataConstants.ENTITY_CREATED:
@ -333,7 +350,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) { if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {
try { try {
for (Edge edge : edges.getData()) { for (Edge edge : edges.getData()) {
pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, tbMsg, callback); pushEventToEdge(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, tbMsg, callback);
} }
} catch (IOException e) { } catch (IOException e) {
log.error("Can't push event to edge", e); log.error("Can't push event to edge", e);
@ -349,7 +366,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
} }
private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeQueueEntityType entityType, FutureCallback<Void> callback) throws IOException { private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeEventType entityType, FutureCallback<Void> callback) throws IOException {
EdgeId edgeId; EdgeId edgeId;
switch (tbMsg.getType()) { switch (tbMsg.getType()) {
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
@ -364,13 +381,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
} }
} }
private void pushEventToEdge(TenantId tenantId, EntityId originatorId, EdgeEventType edgeEventType, TbMsg tbMsg, FutureCallback<Void> callback) {
private void pushEventToEdge(TenantId tenantId, EntityId originatorId, EdgeQueueEntityType edgeQueueEntityType, TbMsg tbMsg, FutureCallback<Void> callback) {
ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, originatorId); ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, originatorId);
Futures.transform(edgeIdFuture, edgeId -> { Futures.transform(edgeIdFuture, edgeId -> {
if (edgeId != null) { if (edgeId != null) {
try { try {
pushEventToEdge(tenantId, edgeId, edgeQueueEntityType, tbMsg, callback); pushEventToEdge(tenantId, edgeId, edgeEventType, tbMsg, callback);
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to push event to edge, edgeId [{}], tbMsg [{}]", edgeId, tbMsg, e); log.error("Failed to push event to edge, edgeId [{}], tbMsg [{}]", edgeId, tbMsg, e);
} }
@ -380,7 +396,6 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
MoreExecutors.directExecutor()); MoreExecutors.directExecutor());
} }
private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TenantId tenantId, EntityId originatorId) { private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TenantId tenantId, EntityId originatorId) {
List<EntityRelation> originatorEdgeRelations = relationService.findByToAndType(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); List<EntityRelation> originatorEdgeRelations = relationService.findByToAndType(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) { if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) {
@ -391,12 +406,12 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
} }
private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException { private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, EdgeEventType entityType, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
log.debug("Pushing event(s) to edge queue. tenantId [{}], edgeId [{}], entityType [{}], tbMsg [{}]", tenantId, edgeId, entityType, tbMsg); log.debug("Pushing event(s) to edge queue. tenantId [{}], edgeId [{}], entityType [{}], tbMsg [{}]", tenantId, edgeId, entityType, tbMsg);
saveEventToEdgeQueue(tenantId, edgeId, entityType, tbMsg.getType(), tbMsg.getData(), callback); saveEventToEdgeQueue(tenantId, edgeId, entityType, tbMsg.getType(), tbMsg.getData(), callback);
if (entityType.equals(EdgeQueueEntityType.RULE_CHAIN)) { if (entityType.equals(EdgeEventType.RULE_CHAIN)) {
pushRuleChainMetadataToEdge(tenantId, edgeId, tbMsg, callback); pushRuleChainMetadataToEdge(tenantId, edgeId, tbMsg, callback);
} }
} }
@ -408,7 +423,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
case DataConstants.ENTITY_UPDATED: case DataConstants.ENTITY_UPDATED:
RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId()); RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId());
saveEventToEdgeQueue(tenantId, edgeId, EdgeQueueEntityType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData), callback); saveEventToEdgeQueue(tenantId, edgeId, EdgeEventType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData), callback);
break; break;
default: default:
log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg); log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
@ -416,14 +431,14 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
} }
private EdgeQueueEntityType getEdgeQueueTypeByEntityType(EntityType entityType) { private EdgeEventType getEdgeQueueTypeByEntityType(EntityType entityType) {
switch (entityType) { switch (entityType) {
case DEVICE: case DEVICE:
return EdgeQueueEntityType.DEVICE; return EdgeEventType.DEVICE;
case ASSET: case ASSET:
return EdgeQueueEntityType.ASSET; return EdgeEventType.ASSET;
case ENTITY_VIEW: case ENTITY_VIEW:
return EdgeQueueEntityType.ENTITY_VIEW; return EdgeEventType.ENTITY_VIEW;
default: default:
log.info("Unsupported entity type: [{}]", entityType); log.info("Unsupported entity type: [{}]", entityType);
return null; return null;

18
application/src/main/java/org/thingsboard/server/service/edge/EdgeNotificationService.java

@ -1,7 +1,23 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.edge; package org.thingsboard.server.service.edge;
import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -14,7 +30,7 @@ import java.io.IOException;
public interface EdgeNotificationService { public interface EdgeNotificationService {
TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException; Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException;

100
application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java

@ -33,14 +33,14 @@ import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeQueueEntry; import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
@ -63,7 +63,6 @@ import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.queue.TbMsgCallback; import org.thingsboard.server.common.msg.queue.TbMsgCallback;
import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.gen.edge.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.AlarmUpdateMsg;
import org.thingsboard.server.gen.edge.ConnectRequestMsg; import org.thingsboard.server.gen.edge.ConnectRequestMsg;
import org.thingsboard.server.gen.edge.ConnectResponseCode; import org.thingsboard.server.gen.edge.ConnectResponseCode;
@ -169,36 +168,28 @@ public final class EdgeGrpcSession implements Closeable {
void processHandleMessages() throws ExecutionException, InterruptedException { void processHandleMessages() throws ExecutionException, InterruptedException {
Long queueStartTs = getQueueStartTs().get(); Long queueStartTs = getQueueStartTs().get();
TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true); TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), queueStartTs, null, true);
TimePageData<Event> pageData; TimePageData<EdgeEvent> pageData;
UUID ifOffset = null; UUID ifOffset = null;
do { do {
pageData = ctx.getEdgeNotificationService().findQueueEvents(edge.getTenantId(), edge.getId(), pageLink); pageData = ctx.getEdgeNotificationService().findEdgeEvents(edge.getTenantId(), edge.getId(), pageLink);
if (isConnected() && !pageData.getData().isEmpty()) { if (isConnected() && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size());
for (Event event : pageData.getData()) { for (EdgeEvent edgeEvent : pageData.getData()) {
log.trace("[{}] Processing event [{}]", this.sessionId, event); log.trace("[{}] Processing edge event [{}]", this.sessionId, edgeEvent);
try { try {
EdgeQueueEntry entry = objectMapper.treeToValue(event.getBody(), EdgeQueueEntry.class); UpdateMsgType msgType = getResponseMsgType(ActionType.valueOf(edgeEvent.getEdgeEventAction()));
UpdateMsgType msgType = getResponseMsgType(entry.getType()); if (msgType == null) {
switch (msgType) { processTelemetryMessage(edgeEvent);
case ENTITY_DELETED_RPC_MESSAGE: } else {
case ENTITY_UPDATED_RPC_MESSAGE: processEntityCRUDMessage(edgeEvent, msgType);
case ENTITY_CREATED_RPC_MESSAGE:
case ALARM_ACK_RPC_MESSAGE:
case ALARM_CLEAR_RPC_MESSAGE:
processEntityCRUDMessage(entry, msgType);
break;
case RULE_CHAIN_CUSTOM_MESSAGE:
processCustomDownlinkMessage(entry);
break;
} }
if (ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) { if (ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) {
pushEntityAttributesToEdge(entry); pushEntityAttributesToEdge(edgeEvent);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Exception during processing records from queue", e); log.error("Exception during processing records from queue", e);
} }
ifOffset = event.getUuidId(); ifOffset = edgeEvent.getUuidId();
} }
} }
if (isConnected() && pageData.hasNext()) { if (isConnected() && pageData.hasNext()) {
@ -222,10 +213,10 @@ public final class EdgeGrpcSession implements Closeable {
} }
} }
private void pushEntityAttributesToEdge(EdgeQueueEntry entry) throws IOException { private void pushEntityAttributesToEdge(EdgeEvent edgeEvent) throws IOException {
EntityId entityId = null; EntityId entityId = null;
String entityName = null; String entityName = null;
switch (entry.getEntityType()) { switch (edgeEvent.getEdgeEventType()) {
case EDGE: case EDGE:
Edge edge = objectMapper.readValue(entry.getData(), Edge.class); Edge edge = objectMapper.readValue(entry.getData(), Edge.class);
entityId = edge.getId(); entityId = edge.getId();
@ -277,7 +268,7 @@ public final class EdgeGrpcSession implements Closeable {
, objectMapper.writeValueAsString(entityNode)); , objectMapper.writeValueAsString(entityNode));
log.debug("Sending donwlink entity data msg, entityName [{}], tbMsg [{}]", finalEntityName, tbMsg); log.debug("Sending donwlink entity data msg, entityName [{}], tbMsg [{}]", finalEntityName, tbMsg);
outputStream.onNext(ResponseMsg.newBuilder() outputStream.onNext(ResponseMsg.newBuilder()
.setDownlinkMsg(constructDownlinkEntityDataMsg(finalEntityName, finalEntityId, tbMsg)) .setDownlinkMsg(constructEntityDataProtoMsg(finalEntityName, finalEntityId, tbMsg))
.build()); .build());
} catch (Exception e) { } catch (Exception e) {
log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e);
@ -290,12 +281,12 @@ public final class EdgeGrpcSession implements Closeable {
} }
} }
private void processCustomDownlinkMessage(EdgeQueueEntry entry) throws IOException { private void processTelemetryMessage(EdgeEvent edgeEvent) throws IOException {
log.trace("Executing processCustomDownlinkMessage, entry [{}]", entry); log.trace("Executing processTelemetryMessage, edgeEvent [{}]", edgeEvent);
TbMsg tbMsg = TbMsg.fromBytes(Base64.decodeBase64(entry.getData()), TbMsgCallback.EMPTY); TbMsg tbMsg = TbMsg.fromBytes(Base64.decodeBase64(entry.getData()), TbMsgCallback.EMPTY);
String entityName = null; String entityName = null;
EntityId entityId = null; EntityId entityId = null;
switch (entry.getEntityType()) { switch (edgeEvent.getEdgeEventType()) {
case DEVICE: case DEVICE:
Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), new DeviceId(tbMsg.getOriginator().getId())); Device device = ctx.getDeviceService().findDeviceById(edge.getTenantId(), new DeviceId(tbMsg.getOriginator().getId()));
entityName = device.getName(); entityName = device.getName();
@ -316,14 +307,14 @@ public final class EdgeGrpcSession implements Closeable {
if (entityName != null && entityId != null) { if (entityName != null && entityId != null) {
log.debug("Sending downlink entity data msg, entityName [{}], tbMsg [{}]", entityName, tbMsg); log.debug("Sending downlink entity data msg, entityName [{}], tbMsg [{}]", entityName, tbMsg);
outputStream.onNext(ResponseMsg.newBuilder() outputStream.onNext(ResponseMsg.newBuilder()
.setDownlinkMsg(constructDownlinkEntityDataMsg(entityName, entityId, tbMsg)) .setDownlinkMsg(constructEntityDataProtoMsg(entityName, entityId, tbMsg))
.build()); .build());
} }
} }
private void processEntityCRUDMessage(EdgeQueueEntry entry, UpdateMsgType msgType) throws java.io.IOException { private void processEntityCRUDMessage(EdgeEvent edgeEvent, UpdateMsgType msgType) throws java.io.IOException {
log.trace("Executing processEntityCRUDMessage, entry [{}], msgType [{}]", entry, msgType); log.trace("Executing processEntityCRUDMessage, edgeEvent [{}], msgType [{}]", edgeEvent, msgType);
switch (entry.getEntityType()) { switch (edgeEvent.getEdgeEventType()) {
case EDGE: case EDGE:
Edge edge = objectMapper.readValue(entry.getData(), Edge.class); Edge edge = objectMapper.readValue(entry.getData(), Edge.class);
onEdgeUpdated(msgType, edge); onEdgeUpdated(msgType, edge);
@ -476,33 +467,30 @@ public final class EdgeGrpcSession implements Closeable {
.build()); .build());
} }
private UpdateMsgType getResponseMsgType(String msgType) { private UpdateMsgType getResponseMsgType(ActionType actionType) {
if (msgType.equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) || switch (actionType) {
msgType.equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) || case ADDED:
msgType.equals(DataConstants.ATTRIBUTES_UPDATED) || return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE;
msgType.equals(DataConstants.ATTRIBUTES_DELETED)) { case UPDATED:
return UpdateMsgType.RULE_CHAIN_CUSTOM_MESSAGE; case ASSIGNED_TO_EDGE:
} else { return ENTITY_CREATED_RPC_MESSAGE;
switch (msgType) { case DELETED:
case DataConstants.ENTITY_UPDATED: case UNASSIGNED_FROM_EDGE:
return UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE; return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE;
case DataConstants.ENTITY_CREATED: case ALARM_ACK:
case DataConstants.ENTITY_ASSIGNED_TO_EDGE: return UpdateMsgType.ALARM_ACK_RPC_MESSAGE;
return ENTITY_CREATED_RPC_MESSAGE; case ALARM_CLEAR:
case DataConstants.ENTITY_DELETED: return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE;
case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE: case ATTRIBUTES_UPDATED:
return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; case ATTRIBUTES_DELETED:
case DataConstants.ALARM_ACK: case TIMESERIES_DELETED:
return UpdateMsgType.ALARM_ACK_RPC_MESSAGE; return null;
case DataConstants.ALARM_CLEAR: default:
return UpdateMsgType.ALARM_CLEAR_RPC_MESSAGE; throw new RuntimeException("Unsupported actionType [" + actionType + "]");
default:
throw new RuntimeException("Unsupported msgType [" + msgType + "]");
}
} }
} }
private DownlinkMsg constructDownlinkEntityDataMsg(String entityName, EntityId entityId, TbMsg tbMsg) { private DownlinkMsg constructEntityDataProtoMsg(String entityName, EntityId entityId, TbMsg tbMsg) {
EntityDataProto entityData = EntityDataProto.newBuilder() EntityDataProto entityData = EntityDataProto.newBuilder()
.setEntityName(entityName) .setEntityName(entityName)
.setTbMsg(ByteString.copyFrom(TbMsg.toByteArray(tbMsg))) .setTbMsg(ByteString.copyFrom(TbMsg.toByteArray(tbMsg)))

2
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java

@ -239,7 +239,7 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.6.0", SCHEMA_UPDATE_SQL); schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.6.0", SCHEMA_UPDATE_SQL);
loadSql(schemaUpdateFile, conn); loadSql(schemaUpdateFile, conn);
try { try {
conn.createStatement().execute("ALTER TABLE rule_chain ADD type varchar(255) DEFAULT 'SYSTEM'"); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script conn.createStatement().execute("ALTER TABLE rule_chain ADD type varchar(255) DEFAULT 'CORE'"); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
} catch (Exception e) {} } catch (Exception e) {}
log.info("Schema updated."); log.info("Schema updated.");
} }

35
common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeEventService.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
public interface EdgeEventService {
EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType);
ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent);
TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
}

2
common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,

3
common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java

@ -65,7 +65,4 @@ public class DataConstants {
public static final String DEFAULT_SECRET_KEY = ""; public static final String DEFAULT_SECRET_KEY = "";
public static final String SECRET_KEY_FIELD_NAME = "secretKey"; public static final String SECRET_KEY_FIELD_NAME = "secretKey";
public static final String DURATION_MS_FIELD_NAME = "durationMs"; public static final String DURATION_MS_FIELD_NAME = "durationMs";
public static final String EDGE_QUEUE_EVENT_TYPE = "EDGE_QUEUE";
} }

1
common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java

@ -24,6 +24,7 @@ public enum ActionType {
UPDATED(false), // log entity UPDATED(false), // log entity
ATTRIBUTES_UPDATED(false), // log attributes/values ATTRIBUTES_UPDATED(false), // log attributes/values
ATTRIBUTES_DELETED(false), // log attributes ATTRIBUTES_DELETED(false), // log attributes
TIMESERIES_UPDATED(false), // log timeseries
TIMESERIES_DELETED(false), // log timeseries TIMESERIES_DELETED(false), // log timeseries
RPC_CALL(false), // log method and params RPC_CALL(false), // log method and params
CREDENTIALS_UPDATED(false), // log new credentials CREDENTIALS_UPDATED(false), // log new credentials

50
common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEvent.java

@ -0,0 +1,50 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.edge;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.id.EdgeEventId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.UUID;
@Data
public class EdgeEvent extends BaseData<EdgeEventId> {
private TenantId tenantId;
private EdgeId edgeId;
private String edgeEventAction;
private UUID entityId;
private EdgeEventType edgeEventType;
private transient JsonNode entityBody;
public EdgeEvent() {
super();
}
public EdgeEvent(EdgeEventId id) {
super(id);
}
public EdgeEvent(EdgeEvent event) {
super(event);
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntityType.java → common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java

@ -15,6 +15,6 @@
*/ */
package org.thingsboard.server.common.data.edge; package org.thingsboard.server.common.data.edge;
public enum EdgeQueueEntityType { public enum EdgeEventType {
DASHBOARD, ASSET, DEVICE, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA, EDGE, USER, CUSTOMER, RELATION DASHBOARD, ASSET, DEVICE, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA, EDGE, USER, CUSTOMER, RELATION
} }

35
common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeEventId.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.UUID;
public class EdgeEventId extends UUIDBased {
private static final long serialVersionUID = 1L;
@JsonCreator
public EdgeEventId(@JsonProperty("id") UUID id) {
super(id);
}
public static EdgeEventId fromString(String edgeEventId) {
return new EdgeEventId(UUID.fromString(edgeEventId));
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainType.java

@ -16,5 +16,5 @@
package org.thingsboard.server.common.data.rule; package org.thingsboard.server.common.data.rule;
public enum RuleChainType { public enum RuleChainType {
SYSTEM, EDGE CORE, EDGE
} }

4
common/edge-api/pom.xml

@ -40,6 +40,10 @@
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<artifactId>data</artifactId> <artifactId>data</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.thingsboard.common</groupId>
<artifactId>queue</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<artifactId>message</artifactId> <artifactId>message</artifactId>

9
common/edge-api/src/main/proto/edge.proto

@ -19,6 +19,8 @@ option java_package = "org.thingsboard.server.gen.edge";
option java_multiple_files = true; option java_multiple_files = true;
option java_outer_classname = "EdgeProtos"; option java_outer_classname = "EdgeProtos";
import "queue.proto";
package edge; package edge;
// Interface exported by the ThingsBoard Edge Transport. // Interface exported by the ThingsBoard Edge Transport.
@ -94,15 +96,16 @@ enum UpdateMsgType {
ENTITY_DELETED_RPC_MESSAGE = 2; ENTITY_DELETED_RPC_MESSAGE = 2;
ALARM_ACK_RPC_MESSAGE = 3; ALARM_ACK_RPC_MESSAGE = 3;
ALARM_CLEAR_RPC_MESSAGE = 4; ALARM_CLEAR_RPC_MESSAGE = 4;
RULE_CHAIN_CUSTOM_MESSAGE = 5; DEVICE_CONFLICT_RPC_MESSAGE = 5;
DEVICE_CONFLICT_RPC_MESSAGE = 6;
} }
message EntityDataProto { message EntityDataProto {
string entityName = 1; string entityName = 1;
int64 entityIdMSB = 2; int64 entityIdMSB = 2;
int64 entityIdLSB = 3; int64 entityIdLSB = 3;
bytes tbMsg = 4; transport.PostTelemetryMsg postTelemetryMsg = 4;
transport.PostAttributeMsg postAttributesMsg = 5;
// transport.ToDeviceRpcRequestMsg ???
} }
message RuleChainUpdateMsg { message RuleChainUpdateMsg {

8
common/queue/src/main/proto/queue.proto

@ -356,6 +356,14 @@ message FromDeviceRPCResponseProto {
message EdgeNotificationMsgProto { message EdgeNotificationMsgProto {
int64 tenantIdMSB = 1; int64 tenantIdMSB = 1;
int64 tenantIdLSB = 2; int64 tenantIdLSB = 2;
string edgeEventType = 3;
string edgeEventAction = 4;
int64 entityIdMSB = 5;
int64 entityIdLSB = 6;
string entityType = 7;
string entityBody = 8;
PostTelemetryMsg postTelemetryMsg = 9;
PostAttributeMsg postAttributesMsg = 10;
} }
/** /**

85
dao/src/main/java/org/thingsboard/server/dao/edge/BaseEdgeEventService.java

@ -0,0 +1,85 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import java.util.List;
@Service
@Slf4j
public class BaseEdgeEventService implements EdgeEventService {
@Autowired
public EdgeEventDao edgeEventDao;
@Override
public EdgeEventType getEdgeEventTypeByEntityType(EntityType entityType) {
switch (entityType) {
case DEVICE:
return EdgeEventType.DEVICE;
case ASSET:
return EdgeEventType.ASSET;
case ENTITY_VIEW:
return EdgeEventType.ENTITY_VIEW;
case DASHBOARD:
return EdgeEventType.DASHBOARD;
case USER:
return EdgeEventType.USER;
default:
log.warn("Failed to push notification to edge service. Unsupported entity type [{}]", entityType);
return null;
}
}
@Override
public ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent) {
edgeEventValidator.validate(edgeEvent, EdgeEvent::getTenantId);
return edgeEventDao.saveAsync(edgeEvent);
}
@Override
public TimePageData<EdgeEvent> findEdgeEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
List<EdgeEvent> events = edgeEventDao.findEdgeEvents(tenantId.getId(), edgeId, pageLink);
return new TimePageData<>(events, pageLink);
}
private DataValidator<EdgeEvent> edgeEventValidator =
new DataValidator<EdgeEvent>() {
@Override
protected void validateDataImpl(TenantId tenantId, EdgeEvent edgeEvent) {
if (edgeEvent.getEdgeId() == null) {
throw new DataValidationException("Edge id should be specified!");
}
if (StringUtils.isEmpty(edgeEvent.getEdgeEventAction())) {
throw new DataValidationException("Edge Event action should be specified!");
}
}
};
}

51
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeEventDao.java

@ -0,0 +1,51 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.Dao;
import java.util.List;
import java.util.UUID;
/**
* The Interface EdgeEventDao.
*/
public interface EdgeEventDao extends Dao<EdgeEvent> {
/**
* Save or update edge event object async
*
* @param edgeEvent the event object
* @return saved edge event object future
*/
ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent);
/**
* Find edge events by tenantId, edgeId and pageLink.
*
* @param tenantId the tenantId
* @param edgeId the edgeId
* @param pageLink the pageLink
* @return the event list
*/
List<EdgeEvent> findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink);
}

2
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,

10
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -372,6 +372,16 @@ public class ModelConstants {
public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key"; public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key";
public static final String EDGE_SECRET_PROPERTY = "secret"; public static final String EDGE_SECRET_PROPERTY = "secret";
/**
* Cassandra edge queue constants.
*/
public static final String EDGE_EVENT_COLUMN_FAMILY_NAME = "edge_event";
public static final String EDGE_EVENT_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
public static final String EDGE_EVENT_EDGE_ID_PROPERTY = "edge_id";
public static final String EDGE_EVENT_TYPE_PROPERTY = "edge_event_type";
public static final String EDGE_EVENT_ACTION_PROPERTY = "edge_event_action";
public static final String EDGE_EVENT_ENTITY_ID_PROPERTY = "entity_id";
public static final String EDGE_EVENT_ENTITY_BODY_PROPERTY = "entity_body";
/** /**
* Cassandra attributes and timeseries constants. * Cassandra attributes and timeseries constants.

135
dao/src/main/java/org/thingsboard/server/dao/model/nosql/EdgeEventEntity.java

@ -0,0 +1,135 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model.nosql;
import com.datastax.driver.core.utils.UUIDs;
import com.datastax.driver.mapping.annotations.ClusteringColumn;
import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeEventId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.EventId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseEntity;
import org.thingsboard.server.dao.model.type.EdgeEventTypeCodec;
import org.thingsboard.server.dao.model.type.EntityTypeCodec;
import org.thingsboard.server.dao.model.type.JsonCodec;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_BODY_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_BODY_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_COLUMN_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_UID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
@Data
@NoArgsConstructor
@Table(name = EDGE_EVENT_COLUMN_FAMILY_NAME)
public class EdgeEventEntity implements BaseEntity<EdgeEvent> {
@Column(name = ID_PROPERTY)
private UUID id;
@PartitionKey()
@Column(name = EDGE_EVENT_TENANT_ID_PROPERTY)
private UUID tenantId;
@PartitionKey(value = 1)
@Column(name = EDGE_EVENT_EDGE_ID_PROPERTY)
private UUID edgeId;
@PartitionKey(value = 2)
@Column(name = EDGE_EVENT_TYPE_PROPERTY, codec = EdgeEventTypeCodec.class)
private EdgeEventType edgeEventType;
@PartitionKey(value = 3)
@Column(name = EDGE_EVENT_ENTITY_ID_PROPERTY)
private UUID entityId;
@ClusteringColumn()
@Column(name = EDGE_EVENT_ACTION_PROPERTY)
private String edgeEventAction;
// TODO
@ClusteringColumn(value = 1)
@Column(name = EVENT_UID_PROPERTY)
private String eventUid;
@Column(name = EDGE_EVENT_ENTITY_BODY_PROPERTY, codec = JsonCodec.class)
private JsonNode entityBody;
public EdgeEventEntity(EdgeEvent edgeEvent) {
if (edgeEvent.getId() != null) {
this.id = edgeEvent.getId().getId();
}
if (edgeEvent.getTenantId() != null) {
this.tenantId = edgeEvent.getTenantId().getId();
}
if (edgeEvent.getEdgeId() != null) {
this.edgeId = edgeEvent.getEdgeId().getId();
}
// if (event.getEntityId() != null) {
// this.entityType = event.getEntityId().getEntityType();
// this.entityId = event.getEntityId().getId();
// }
// this.edgeEventType = edgeEvent.getEdgeEventType();
// this.edgeEventAction = edgeEvent.getEdgeEventAction();
// this.entityBody = edgeEvent.getEntityBody();
}
@Override
public UUID getUuid() {
return id;
}
@Override
public void setUuid(UUID id) {
this.id = id;
}
@Override
public EdgeEvent toData() {
EdgeEvent edgeEvent = new EdgeEvent(new EdgeEventId(id));
// edgeEvent.setCreatedTime(UUIDs.unixTimestamp(id));
// edgeEvent.setTenantId(new TenantId(tenantId));
// edgeEvent.setEdgeId(new EdgeId(edgeId));
// edgeEvent.setEntityId(entityId);
// event.setBody(body);
// event.setType(eventType);
// event.setUid(eventUid);
return edgeEvent;
}
}

121
dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java

@ -0,0 +1,121 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model.sql;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeEventId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseEntity;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Table;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_COLUMN_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_BODY_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EPOCH_DIFF;
import static org.thingsboard.server.dao.model.ModelConstants.TS_COLUMN;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = EDGE_EVENT_COLUMN_FAMILY_NAME)
@NoArgsConstructor
public class EdgeEventEntity extends BaseSqlEntity<EdgeEvent> implements BaseEntity<EdgeEvent> {
@Column(name = EDGE_EVENT_TENANT_ID_PROPERTY)
private String tenantId;
@Column(name = EDGE_EVENT_EDGE_ID_PROPERTY)
private String edgeId;
@Column(name = EDGE_EVENT_ENTITY_ID_PROPERTY)
private String entityId;
@Enumerated(EnumType.STRING)
@Column(name = EDGE_EVENT_TYPE_PROPERTY)
private EdgeEventType edgeEventType;
@Column(name = EDGE_EVENT_ACTION_PROPERTY)
private String edgeEventAction;
@Type(type = "json")
@Column(name = EDGE_EVENT_ENTITY_BODY_PROPERTY)
private JsonNode entityBody;
@Column(name = TS_COLUMN)
private long ts;
public EdgeEventEntity(EdgeEvent edgeEvent) {
if (edgeEvent.getId() != null) {
this.setUuid(edgeEvent.getId().getId());
this.ts = getTs(edgeEvent.getId().getId());
} else {
this.ts = System.currentTimeMillis();
}
if (edgeEvent.getTenantId() != null) {
this.tenantId = toString(edgeEvent.getTenantId().getId());
}
if (edgeEvent.getEdgeId() != null) {
this.edgeId = toString(edgeEvent.getEdgeId().getId());
}
if (edgeEvent.getEntityId() != null) {
this.entityId = toString(edgeEvent.getEntityId());
}
this.edgeEventType = edgeEvent.getEdgeEventType();
this.edgeEventAction = edgeEvent.getEdgeEventAction();
this.entityBody = edgeEvent.getEntityBody();
}
@Override
public EdgeEvent toData() {
EdgeEvent edgeEvent = new EdgeEvent(new EdgeEventId(this.getUuid()));
edgeEvent.setCreatedTime(UUIDs.unixTimestamp(this.getUuid()));
edgeEvent.setTenantId(new TenantId(toUUID(tenantId)));
edgeEvent.setEdgeId(new EdgeId(toUUID(edgeId)));
if (entityId != null) {
edgeEvent.setEntityId(toUUID(entityId));
}
edgeEvent.setEdgeEventType(edgeEventType);
edgeEvent.setEdgeEventAction(edgeEventAction);
edgeEvent.setEntityBody(entityBody);
return edgeEvent;
}
private static long getTs(UUID uuid) {
return (uuid.timestamp() - EPOCH_DIFF) / 10000;
}
}

27
dao/src/main/java/org/thingsboard/server/dao/model/type/EdgeEventTypeCodec.java

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model.type;
import com.datastax.driver.extras.codecs.enums.EnumNameCodec;
import org.thingsboard.server.common.data.edge.EdgeEventType;
public class EdgeEventTypeCodec extends EnumNameCodec<EdgeEventType> {
public EdgeEventTypeCodec() {
super(EdgeEventType.class);
}
}

6
dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

@ -289,7 +289,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
@Override @Override
public RuleChain getRootTenantRuleChain(TenantId tenantId) { public RuleChain getRootTenantRuleChain(TenantId tenantId) {
return getRootRuleChainByType(tenantId, RuleChainType.SYSTEM); return getRootRuleChainByType(tenantId, RuleChainType.CORE);
} }
private RuleChain getRootRuleChainByType(TenantId tenantId, RuleChainType type) { private RuleChain getRootRuleChainByType(TenantId tenantId, RuleChainType type) {
@ -566,7 +566,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
throw new DataValidationException("Rule chain name should be specified!"); throw new DataValidationException("Rule chain name should be specified!");
} }
if (ruleChain.getType() == null) { if (ruleChain.getType() == null) {
ruleChain.setType(RuleChainType.SYSTEM); ruleChain.setType(RuleChainType.CORE);
} }
if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) { if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) {
throw new DataValidationException("Rule chain should be assigned to tenant!"); throw new DataValidationException("Rule chain should be assigned to tenant!");
@ -575,7 +575,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
if (tenant == null) { if (tenant == null) {
throw new DataValidationException("Rule chain is referencing to non-existent tenant!"); throw new DataValidationException("Rule chain is referencing to non-existent tenant!");
} }
if (ruleChain.isRoot() && RuleChainType.SYSTEM.equals(ruleChain.getType())) { if (ruleChain.isRoot() && RuleChainType.CORE.equals(ruleChain.getType())) {
RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId()); RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
if (rootRuleChain != null && !rootRuleChain.getId().equals(ruleChain.getId())) { if (rootRuleChain != null && !rootRuleChain.getId().equals(ruleChain.getId())) {
throw new DataValidationException("Another root rule chain is present in scope of current tenant!"); throw new DataValidationException("Another root rule chain is present in scope of current tenant!");

26
dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeEventRepository.java

@ -0,0 +1,26 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.edge;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.thingsboard.server.dao.model.sql.EdgeEventEntity;
import org.thingsboard.server.dao.util.SqlDao;
@SqlDao
public interface EdgeEventRepository extends CrudRepository<EdgeEventEntity, String>, JpaSpecificationExecutor<EdgeEventEntity> {
}

112
dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java

@ -0,0 +1,112 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.edge;
import com.datastax.driver.core.utils.UUIDs;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.UUIDConverter;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.EdgeEventId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.edge.EdgeEventDao;
import org.thingsboard.server.dao.model.sql.EdgeEventEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao;
import org.thingsboard.server.dao.util.SqlDao;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
@Slf4j
@Component
@SqlDao
public class JpaBaseEdgeEventDao extends JpaAbstractSearchTimeDao<EdgeEventEntity, EdgeEvent> implements EdgeEventDao {
private final UUID systemTenantId = NULL_UUID;
@Autowired
private EdgeEventRepository edgeEventRepository;
@Override
protected Class<EdgeEventEntity> getEntityClass() {
return EdgeEventEntity.class;
}
@Override
protected CrudRepository<EdgeEventEntity, String> getCrudRepository() {
return edgeEventRepository;
}
@Override
public ListenableFuture<EdgeEvent> saveAsync(EdgeEvent edgeEvent) {
log.debug("Save edge event [{}] ", edgeEvent);
if (edgeEvent.getId() == null) {
edgeEvent.setId(new EdgeEventId(UUIDs.timeBased()));
}
return service.submit(() -> save(new EdgeEventEntity(edgeEvent)).orElse(null));
}
@Override
public List<EdgeEvent> findEdgeEvents(UUID tenantId, EdgeId edgeId, TimePageLink pageLink) {
Specification<EdgeEventEntity> timeSearchSpec = JpaAbstractSearchTimeDao.getTimeSearchPageSpec(pageLink, "id");
Specification<EdgeEventEntity> fieldsSpec = getEntityFieldsSpec(tenantId, edgeId);
Sort.Direction sortDirection = pageLink.isAscOrder() ? Sort.Direction.ASC : Sort.Direction.DESC;
Pageable pageable = PageRequest.of(0, pageLink.getLimit(), sortDirection, ID_PROPERTY);
return DaoUtil.convertDataList(edgeEventRepository.findAll(Specification.where(timeSearchSpec).and(fieldsSpec), pageable).getContent());
}
public Optional<EdgeEvent> save(EdgeEventEntity entity) {
log.debug("Save edge event [{}] ", entity);
if (entity.getTenantId() == null) {
log.trace("Save system edge event with predefined id {}", systemTenantId);
entity.setTenantId(UUIDConverter.fromTimeUUID(systemTenantId));
}
if (entity.getUuid() == null) {
entity.setUuid(UUIDs.timeBased());
}
return Optional.of(DaoUtil.getData(edgeEventRepository.save(entity)));
}
private Specification<EdgeEventEntity> getEntityFieldsSpec(UUID tenantId, EdgeId edgeId) {
return (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if (tenantId != null) {
Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), UUIDConverter.fromTimeUUID(tenantId));
predicates.add(tenantIdPredicate);
}
if (edgeId != null) {
Predicate entityIdPredicate = criteriaBuilder.equal(root.get("edgeId"), UUIDConverter.fromTimeUUID(edgeId.getId()));
predicates.add(entityIdPredicate);
}
return criteriaBuilder.and(predicates.toArray(new Predicate[]{}));
};
}
}

11
dao/src/main/resources/sql/schema-entities-hsql.sql

@ -270,3 +270,14 @@ CREATE TABLE IF NOT EXISTS edge (
CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name), CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name),
CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key) CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key)
); );
CREATE TABLE IF NOT EXISTS edge_event (
id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY,
edge_id varchar(31),
edge_event_type varchar(255),
entity_id varchar(31),
edge_event_action varchar(255),
entity_body varchar(10000000),
tenant_id varchar(31),
ts bigint NOT NULL
);

12
dao/src/main/resources/sql/schema-entities.sql

@ -271,6 +271,18 @@ CREATE TABLE IF NOT EXISTS edge (
CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key) CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key)
); );
CREATE TABLE IF NOT EXISTS edge_event (
id varchar(31) NOT NULL CONSTRAINT edge_event_pkey PRIMARY KEY,
edge_id varchar(31),
edge_event_type varchar(255),
entity_id varchar(31),
edge_event_action varchar(255),
entity_body varchar(10000000),
tenant_id varchar(31),
ts bigint NOT NULL
);
CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint)
LANGUAGE plpgsql AS LANGUAGE plpgsql AS
$$ $$

4
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -45,6 +45,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceCredentialsService; import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.event.EventService;
@ -125,6 +126,9 @@ public abstract class AbstractServiceTest {
@Autowired @Autowired
protected EdgeService edgeService; protected EdgeService edgeService;
@Autowired
protected EdgeEventService edgeEventService;
@Autowired @Autowired
private ComponentDescriptorService componentDescriptorService; private ComponentDescriptorService componentDescriptorService;

108
dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeEventServiceTest.java

@ -0,0 +1,108 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.service;
import com.datastax.driver.core.utils.UUIDs;
import org.junit.Assert;
import org.junit.Test;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeEventId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
public abstract class BaseEdgeEventServiceTest extends AbstractServiceTest {
@Test
public void saveEdgeEvent() throws Exception {
EdgeId edgeId = new EdgeId(UUIDs.timeBased());
DeviceId deviceId = new DeviceId(UUIDs.timeBased());
EdgeEvent edgeEvent = generateEdgeEvent(null, edgeId, deviceId, DataConstants.ENTITY_CREATED);
EdgeEvent saved = edgeEventService.saveAsync(edgeEvent).get();
Assert.assertEquals(saved.getTenantId(), edgeEvent.getTenantId());
Assert.assertEquals(saved.getEdgeId(), edgeEvent.getEdgeId());
Assert.assertEquals(saved.getEntityId(), edgeEvent.getEntityId());
Assert.assertEquals(saved.getEdgeEventType(), edgeEvent.getEdgeEventType());
Assert.assertEquals(saved.getEdgeEventAction(), edgeEvent.getEdgeEventAction());
Assert.assertEquals(saved.getEntityBody(), edgeEvent.getEntityBody());
}
protected EdgeEvent generateEdgeEvent(TenantId tenantId, EdgeId edgeId, EntityId entityId, String edgeEventAction) throws IOException {
if (tenantId == null) {
tenantId = new TenantId(UUIDs.timeBased());
}
EdgeEvent edgeEvent = new EdgeEvent();
edgeEvent.setTenantId(tenantId);
edgeEvent.setEdgeId(edgeId);
edgeEvent.setEntityId(entityId.getId());
edgeEvent.setEdgeEventType(EdgeEventType.DEVICE);
edgeEvent.setEdgeEventAction(edgeEventAction);
edgeEvent.setEntityBody(readFromResource("TestJsonData.json"));
return edgeEvent;
}
@Test
public void findEdgeEventsByTimeDescOrder() throws Exception {
long timeBeforeStartTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 11, 30).toEpochSecond(ZoneOffset.UTC);
long startTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 12, 0).toEpochSecond(ZoneOffset.UTC);
long eventTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 12, 30).toEpochSecond(ZoneOffset.UTC);
long endTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 13, 0).toEpochSecond(ZoneOffset.UTC);
long timeAfterEndTime = LocalDateTime.of(2020, Month.NOVEMBER, 1, 13, 30).toEpochSecond(ZoneOffset.UTC);
EdgeId edgeId = new EdgeId(UUIDs.timeBased());
DeviceId deviceId = new DeviceId(UUIDs.timeBased());
TenantId tenantId = new TenantId(UUIDs.timeBased());
saveEdgeEventWithProvidedTime(timeBeforeStartTime, edgeId, deviceId, tenantId);
EdgeEvent savedEdgeEvent = saveEdgeEventWithProvidedTime(eventTime, edgeId, deviceId, tenantId);
EdgeEvent savedEdgeEvent2 = saveEdgeEventWithProvidedTime(eventTime + 1, edgeId, deviceId, tenantId);
EdgeEvent savedEdgeEvent3 = saveEdgeEventWithProvidedTime(eventTime + 2, edgeId, deviceId, tenantId);
saveEdgeEventWithProvidedTime(timeAfterEndTime, edgeId, deviceId, tenantId);
TimePageData<EdgeEvent> edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, new TimePageLink(2, startTime, endTime, false));
Assert.assertNotNull(edgeEvents.getData());
Assert.assertTrue(edgeEvents.getData().size() == 2);
Assert.assertTrue(edgeEvents.getData().get(0).getUuidId().equals(savedEdgeEvent3.getUuidId()));
Assert.assertTrue(edgeEvents.getData().get(1).getUuidId().equals(savedEdgeEvent2.getUuidId()));
Assert.assertTrue(edgeEvents.hasNext());
Assert.assertNotNull(edgeEvents.getNextPageLink());
edgeEvents = edgeEventService.findEdgeEvents(tenantId, edgeId, edgeEvents.getNextPageLink());
Assert.assertNotNull(edgeEvents.getData());
Assert.assertTrue(edgeEvents.getData().size() == 1);
Assert.assertTrue(edgeEvents.getData().get(0).getUuidId().equals(savedEdgeEvent.getUuidId()));
Assert.assertFalse(edgeEvents.hasNext());
Assert.assertNull(edgeEvents.getNextPageLink());
}
private EdgeEvent saveEdgeEventWithProvidedTime(long time, EdgeId edgeId, EntityId entityId, TenantId tenantId) throws Exception {
EdgeEvent edgeEvent = generateEdgeEvent(tenantId, edgeId, entityId, DataConstants.ENTITY_CREATED);
edgeEvent.setId(new EdgeEventId(UUIDs.startOf(time)));
return edgeEventService.saveAsync(edgeEvent).get();
}
}

2
dao/src/test/java/org/thingsboard/server/dao/service/EdgeServiceImplTest.java → dao/src/test/java/org/thingsboard/server/dao/service/BaseEdgeServiceTest.java

@ -37,7 +37,7 @@ import java.util.List;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
public abstract class EdgeServiceImplTest extends AbstractServiceTest { public abstract class BaseEdgeServiceTest extends AbstractServiceTest {
private IdComparator<Edge> idComparator = new IdComparator<>(); private IdComparator<Edge> idComparator = new IdComparator<>();

12
dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java

@ -145,7 +145,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
TextPageLink pageLink = new TextPageLink(16); TextPageLink pageLink = new TextPageLink(16);
TextPageData<RuleChain> pageData = null; TextPageData<RuleChain> pageData = null;
do { do {
pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink); pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
loadedRuleChains.addAll(pageData.getData()); loadedRuleChains.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink(); pageLink = pageData.getNextPageLink();
@ -160,7 +160,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
ruleChainService.deleteRuleChainsByTenantId(tenantId); ruleChainService.deleteRuleChainsByTenantId(tenantId);
pageLink = new TextPageLink(31); pageLink = new TextPageLink(31);
pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink); pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty()); Assert.assertTrue(pageData.getData().isEmpty());
@ -196,7 +196,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
TextPageLink pageLink = new TextPageLink(19, name1); TextPageLink pageLink = new TextPageLink(19, name1);
TextPageData<RuleChain> pageData = null; TextPageData<RuleChain> pageData = null;
do { do {
pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink); pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
loadedRuleChainsName1.addAll(pageData.getData()); loadedRuleChainsName1.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink(); pageLink = pageData.getNextPageLink();
@ -211,7 +211,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
List<RuleChain> loadedRuleChainsName2 = new ArrayList<>(); List<RuleChain> loadedRuleChainsName2 = new ArrayList<>();
pageLink = new TextPageLink(4, name2); pageLink = new TextPageLink(4, name2);
do { do {
pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink); pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
loadedRuleChainsName2.addAll(pageData.getData()); loadedRuleChainsName2.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageData.getNextPageLink(); pageLink = pageData.getNextPageLink();
@ -228,7 +228,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
} }
pageLink = new TextPageLink(4, name1); pageLink = new TextPageLink(4, name1);
pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink); pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(0, pageData.getData().size()); Assert.assertEquals(0, pageData.getData().size());
@ -237,7 +237,7 @@ public abstract class BaseRuleChainServiceTest extends AbstractServiceTest {
} }
pageLink = new TextPageLink(4, name2); pageLink = new TextPageLink(4, name2);
pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.SYSTEM, pageLink); pageData = ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink);
Assert.assertFalse(pageData.hasNext()); Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(0, pageData.getData().size()); Assert.assertEquals(0, pageData.getData().size());
} }

23
dao/src/test/java/org/thingsboard/server/dao/service/nosql/EdgeEventServiceNoSqlTest.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.service.nosql;
import org.thingsboard.server.dao.service.BaseEdgeEventServiceTest;
import org.thingsboard.server.dao.service.DaoNoSqlTest;
@DaoNoSqlTest
public class EdgeEventServiceNoSqlTest extends BaseEdgeEventServiceTest {
}

4
dao/src/test/java/org/thingsboard/server/dao/service/nosql/EdgeServiceNoSqlTest.java

@ -15,9 +15,9 @@
*/ */
package org.thingsboard.server.dao.service.nosql; package org.thingsboard.server.dao.service.nosql;
import org.thingsboard.server.dao.service.EdgeServiceImplTest; import org.thingsboard.server.dao.service.BaseEdgeServiceTest;
import org.thingsboard.server.dao.service.DaoNoSqlTest; import org.thingsboard.server.dao.service.DaoNoSqlTest;
@DaoNoSqlTest @DaoNoSqlTest
public class EdgeServiceNoSqlTest extends EdgeServiceImplTest { public class EdgeServiceNoSqlTest extends BaseEdgeServiceTest {
} }

12
common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeQueueEntry.java → dao/src/test/java/org/thingsboard/server/dao/service/sql/EdgeEventServiceSqlTest.java

@ -13,13 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.common.data.edge; package org.thingsboard.server.dao.service.sql;
import lombok.Data; import org.thingsboard.server.dao.service.BaseEdgeEventServiceTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
@Data @DaoSqlTest
public class EdgeQueueEntry { public class EdgeEventServiceSqlTest extends BaseEdgeEventServiceTest {
private String type;
private EdgeQueueEntityType entityType;
private String data;
} }

4
dao/src/test/java/org/thingsboard/server/dao/service/sql/EdgeServiceSqlTest.java

@ -15,9 +15,9 @@
*/ */
package org.thingsboard.server.dao.service.sql; package org.thingsboard.server.dao.service.sql;
import org.thingsboard.server.dao.service.EdgeServiceImplTest; import org.thingsboard.server.dao.service.BaseEdgeServiceTest;
import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.service.DaoSqlTest;
@DaoSqlTest @DaoSqlTest
public class EdgeServiceSqlTest extends EdgeServiceImplTest { public class EdgeServiceSqlTest extends BaseEdgeServiceTest {
} }

3
dao/src/test/resources/sql/hsql/drop-all-tables.sql

@ -20,4 +20,5 @@ DROP TABLE IF EXISTS widgets_bundle;
DROP TABLE IF EXISTS rule_node; DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain; DROP TABLE IF EXISTS rule_chain;
DROP TABLE IF EXISTS entity_view; DROP TABLE IF EXISTS entity_view;
DROP TABLE IF EXISTS edge; DROP TABLE IF EXISTS edge;
DROP TABLE IF EXISTS edge_event;

2
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleNode.java

@ -58,6 +58,6 @@ public @interface RuleNode {
boolean customRelations() default false; boolean customRelations() default false;
RuleChainType[] ruleChainTypes() default RuleChainType.SYSTEM; RuleChainType[] ruleChainTypes() default RuleChainType.CORE;
} }

3
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java

@ -35,6 +35,7 @@ import org.thingsboard.server.dao.cassandra.CassandraCluster;
import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.nosql.CassandraStatementTask; import org.thingsboard.server.dao.nosql.CassandraStatementTask;
@ -190,6 +191,8 @@ public interface TbContext {
EdgeService getEdgeService(); EdgeService getEdgeService();
EdgeEventService getEdgeEventService();
ListeningExecutor getJsExecutor(); ListeningExecutor getJsExecutor();
ListeningExecutor getMailExecutor(); ListeningExecutor getMailExecutor();

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java

@ -38,7 +38,7 @@ import org.thingsboard.server.common.msg.TbMsg;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeAssignToCustomerConfig", configDirective = "tbActionNodeAssignToCustomerConfig",
icon = "add_circle", icon = "add_circle",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode<TbAssignToCustomerNodeConfiguration> { public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode<TbAssignToCustomerNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java

@ -46,7 +46,7 @@ import org.thingsboard.server.common.msg.TbMsg;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeClearAlarmConfig", configDirective = "tbActionNodeClearAlarmConfig",
icon = "notifications_off", icon = "notifications_off",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbClearAlarmNode extends TbAbstractAlarmNode<TbClearAlarmNodeConfiguration> { public class TbClearAlarmNode extends TbAbstractAlarmNode<TbClearAlarmNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java

@ -58,7 +58,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig", configDirective = "tbNodeEmptyConfig",
icon = "content_copy", icon = "content_copy",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbCopyAttributesToEntityViewNode implements TbNode { public class TbCopyAttributesToEntityViewNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java

@ -52,7 +52,7 @@ import java.util.List;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeCreateAlarmConfig", configDirective = "tbActionNodeCreateAlarmConfig",
icon = "notifications_active", icon = "notifications_active",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbCreateAlarmNode extends TbAbstractAlarmNode<TbCreateAlarmNodeConfiguration> { public class TbCreateAlarmNode extends TbAbstractAlarmNode<TbCreateAlarmNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java

@ -55,7 +55,7 @@ import java.util.List;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeCreateRelationConfig", configDirective = "tbActionNodeCreateRelationConfig",
icon = "add_circle", icon = "add_circle",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbCreateRelationNode extends TbAbstractRelationActionNode<TbCreateRelationNodeConfiguration> { public class TbCreateRelationNode extends TbAbstractRelationActionNode<TbCreateRelationNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java

@ -45,7 +45,7 @@ import java.util.List;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeDeleteRelationConfig", configDirective = "tbActionNodeDeleteRelationConfig",
icon = "remove_circle", icon = "remove_circle",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbDeleteRelationNode extends TbAbstractRelationActionNode<TbDeleteRelationNodeConfiguration> { public class TbDeleteRelationNode extends TbAbstractRelationActionNode<TbDeleteRelationNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java

@ -38,7 +38,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeLogConfig", configDirective = "tbActionNodeLogConfig",
icon = "menu", icon = "menu",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbLogNode implements TbNode { public class TbLogNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java

@ -44,7 +44,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
icon = "functions", icon = "functions",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeMsgCountConfig", configDirective = "tbActionNodeMsgCountConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgCountNode implements TbNode { public class TbMsgCountNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java

@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.TbMsg;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeUnAssignToCustomerConfig", configDirective = "tbActionNodeUnAssignToCustomerConfig",
icon = "remove_circle", icon = "remove_circle",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbUnassignFromCustomerNode extends TbAbstractCustomerActionNode<TbUnassignFromCustomerNodeConfiguration> { public class TbUnassignFromCustomerNode extends TbAbstractCustomerActionNode<TbUnassignFromCustomerNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java

@ -47,7 +47,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeSnsConfig", configDirective = "tbActionNodeSnsConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbSnsNode implements TbNode { public class TbSnsNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java

@ -52,7 +52,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeSqsConfig", configDirective = "tbActionNodeSqsConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbSqsNode implements TbNode { public class TbSqsNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java

@ -45,7 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbActionNodeGeneratorConfig", configDirective = "tbActionNodeGeneratorConfig",
icon = "repeat", icon = "repeat",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgGeneratorNode implements TbNode { public class TbMsgGeneratorNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java

@ -46,7 +46,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
icon = "pause", icon = "pause",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeMsgDelayConfig", configDirective = "tbActionNodeMsgDelayConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgDelayNode implements TbNode { public class TbMsgDelayNode implements TbNode {

41
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/PushToEdgeNodeCallback.java

@ -1,41 +0,0 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.rule.engine.edge;
import com.google.common.util.concurrent.FutureCallback;
import lombok.Data;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.server.common.msg.TbMsg;
import javax.annotation.Nullable;
import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
@Data
class PushToEdgeNodeCallback implements FutureCallback<Void> {
private final TbContext ctx;
private final TbMsg msg;
@Override
public void onSuccess(@Nullable Void result) {
ctx.tellNext(msg, SUCCESS);
}
@Override
public void onFailure(Throwable t) {
ctx.tellFailure(msg, t);
}
}

97
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java

@ -15,6 +15,10 @@
*/ */
package org.thingsboard.rule.engine.edge; package org.thingsboard.rule.engine.edge;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; import org.thingsboard.rule.engine.api.EmptyNodeConfiguration;
import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.RuleNode;
@ -23,10 +27,25 @@ import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.msg.session.SessionMsgType;
import javax.annotation.Nullable;
import java.util.List;
import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
@Slf4j @Slf4j
@RuleNode( @RuleNode(
type = ComponentType.ACTION, type = ComponentType.ACTION,
@ -40,13 +59,10 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
) )
public class TbMsgPushToEdgeNode implements TbNode { public class TbMsgPushToEdgeNode implements TbNode {
private static final String CLOUD_MSG_SOURCE = "cloud";
private static final String EDGE_MSG_SOURCE = "edge";
private static final String MSG_SOURCE_KEY = "source";
private static final String TS_METADATA_KEY = "ts";
private EmptyNodeConfiguration config; private EmptyNodeConfiguration config;
private static final ObjectMapper json = new ObjectMapper();
@Override @Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
this.config = TbNodeUtils.convert(configuration, EmptyNodeConfiguration.class); this.config = TbNodeUtils.convert(configuration, EmptyNodeConfiguration.class);
@ -54,14 +70,71 @@ public class TbMsgPushToEdgeNode implements TbNode {
@Override @Override
public void onMsg(TbContext ctx, TbMsg msg) { public void onMsg(TbContext ctx, TbMsg msg) {
if (EDGE_MSG_SOURCE.equalsIgnoreCase(msg.getMetaData().getValue(MSG_SOURCE_KEY))) { if (EntityType.DEVICE.equals(msg.getOriginator().getEntityType()) ||
return; EntityType.DEVICE.equals(msg.getOriginator().getEntityType()) ||
} EntityType.DEVICE.equals(msg.getOriginator().getEntityType()) ||
if (msg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name())) { EntityType.DEVICE.equals(msg.getOriginator().getEntityType())) {
msg.getMetaData().putValue(TS_METADATA_KEY, Long.toString(System.currentTimeMillis())); if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msg.getType()) ||
SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msg.getType()) ||
DataConstants.ATTRIBUTES_UPDATED.equals(msg.getType()) ||
DataConstants.ATTRIBUTES_DELETED.equals(msg.getType())) {
ListenableFuture<EdgeId> getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator());
Futures.transform(getEdgeIdFuture, edgeId -> {
EdgeEventType edgeEventTypeByEntityType = ctx.getEdgeEventService().getEdgeEventTypeByEntityType(msg.getOriginator().getEntityType());
if (edgeEventTypeByEntityType == null) {
log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType());
ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '"+ msg.getOriginator().getEntityType() + "'"));
}
ActionType actionType;
if (SessionMsgType.POST_TELEMETRY_REQUEST.name().equals(msg.getType())) {
actionType = ActionType.TIMESERIES_UPDATED;
} else if (SessionMsgType.POST_ATTRIBUTES_REQUEST.name().equals(msg.getType()) ||
DataConstants.ATTRIBUTES_UPDATED.equals(msg.getType())) {
actionType = ActionType.ATTRIBUTES_UPDATED;
} else {
actionType = ActionType.ATTRIBUTES_DELETED;
}
EdgeEvent edgeEvent = new EdgeEvent();
edgeEvent.setTenantId(ctx.getTenantId());
edgeEvent.setEdgeId(edgeId);
edgeEvent.setEdgeEventAction(actionType.name());
edgeEvent.setEntityId(msg.getOriginator().getId());
edgeEvent.setEdgeEventType(edgeEventTypeByEntityType);
edgeEvent.setEntityBody(json.valueToTree(msg.getData()));
ListenableFuture<EdgeEvent> saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent);
Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
@Override
public void onSuccess(@Nullable EdgeEvent event) {
ctx.tellNext(msg, SUCCESS);
}
@Override
public void onFailure(Throwable th) {
log.error("Could not save edge event", th);
ctx.tellFailure(msg, th);
}
}, ctx.getDbCallbackExecutor());
return null;
}, ctx.getDbCallbackExecutor());
} else {
log.debug("Unsupported msg type {}", msg.getType());
ctx.tellFailure(msg, new RuntimeException("Unsupported msg type '" + msg.getType() + "'"));
}
} else {
log.debug("Unsupported originator type {}", msg.getOriginator().getEntityType());
ctx.tellFailure(msg, new RuntimeException("Unsupported originator type '" + msg.getOriginator().getEntityType() + "'"));
} }
msg.getMetaData().putValue(MSG_SOURCE_KEY, CLOUD_MSG_SOURCE); }
ctx.getEdgeService().pushEventToEdge(ctx.getTenantId(), msg, new PushToEdgeNodeCallback(ctx, msg));
private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) {
ListenableFuture<List<EntityRelation>> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
return Futures.transform(future, relations -> {
if (relations != null && relations.size() > 0) {
return new EdgeId(relations.get(0).getFrom().getId());
} else {
return null;
}
}, ctx.getDbCallbackExecutor());
} }
@Override @Override

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java

@ -41,7 +41,7 @@ import java.util.Map;
"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. ", "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. ",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckMessageConfig", configDirective = "tbFilterNodeCheckMessageConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbCheckMessageNode implements TbNode { public class TbCheckMessageNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java

@ -53,7 +53,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
nodeDetails = "If at least one relation exists - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.", nodeDetails = "If at least one relation exists - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckRelationConfig", configDirective = "tbFilterNodeCheckRelationConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbCheckRelationNode implements TbNode { public class TbCheckRelationNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java

@ -38,7 +38,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"Message type can be accessed via <code>msgType</code> property.", "Message type can be accessed via <code>msgType</code> property.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeScriptConfig", configDirective = "tbFilterNodeScriptConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbJsFilterNode implements TbNode { public class TbJsFilterNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java

@ -41,7 +41,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
"Message type can be accessed via <code>msgType</code> property.", "Message type can be accessed via <code>msgType</code> property.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeSwitchConfig", configDirective = "tbFilterNodeSwitchConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbJsSwitchNode implements TbNode { public class TbJsSwitchNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java

@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.", nodeDetails = "If incoming MessageType is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbFilterNodeMessageTypeConfig", configDirective = "tbFilterNodeMessageTypeConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgTypeFilterNode implements TbNode { public class TbMsgTypeFilterNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java

@ -36,7 +36,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
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.", 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.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig", configDirective = "tbNodeEmptyConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgTypeSwitchNode implements TbNode { public class TbMsgTypeSwitchNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java

@ -33,7 +33,7 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDetails = "If Originator Type of incoming message is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.", nodeDetails = "If Originator Type of incoming message is expected - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.",
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbFilterNodeOriginatorTypeConfig", configDirective = "tbFilterNodeOriginatorTypeConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbOriginatorTypeFilterNode implements TbNode { public class TbOriginatorTypeFilterNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java

@ -33,7 +33,7 @@ import org.thingsboard.server.common.msg.TbMsg;
nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).", nodeDetails = "Routes messages to chain according to the originator type ('Device', 'Asset', etc.).",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig", configDirective = "tbNodeEmptyConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbOriginatorTypeSwitchNode implements TbNode { public class TbOriginatorTypeSwitchNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java

@ -51,7 +51,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodePubSubConfig", configDirective = "tbActionNodePubSubConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=", iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbPubSubNode implements TbNode { public class TbPubSubNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java

@ -53,7 +53,7 @@ import java.util.concurrent.TimeoutException;
nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters", nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns different events based on configuration parameters",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeGpsGeofencingConfig", configDirective = "tbActionNodeGpsGeofencingConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> { public class TbGpsGeofencingActionNode extends AbstractGeofencingNode<TbGpsGeofencingActionNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java

@ -54,7 +54,7 @@ import java.util.List;
nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.", nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeGpsGeofencingConfig", configDirective = "tbFilterNodeGpsGeofencingConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode<TbGpsGeofencingFilterNodeConfiguration> { public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode<TbGpsGeofencingFilterNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java

@ -53,7 +53,7 @@ import java.util.Properties;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeKafkaConfig", configDirective = "tbActionNodeKafkaConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==", iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbKafkaNode implements TbNode { public class TbKafkaNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java

@ -42,7 +42,7 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbTransformationNodeToEmailConfig", configDirective = "tbTransformationNodeToEmailConfig",
icon = "email", icon = "email",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgToEmailNode implements TbNode { public class TbMsgToEmailNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java

@ -48,7 +48,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeSendEmailConfig", configDirective = "tbActionNodeSendEmailConfig",
icon = "send", icon = "send",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbSendEmailNode implements TbNode { public class TbSendEmailNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java

@ -42,7 +42,7 @@ import org.thingsboard.server.common.msg.TbMsg;
"<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ", "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeOriginatorAttributesConfig", configDirective = "tbEnrichmentNodeOriginatorAttributesConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> { public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java

@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
"<code>metadata.temperature</code>.", "<code>metadata.temperature</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbEnrichmentNodeCustomerAttributesConfig", configDirective = "tbEnrichmentNodeCustomerAttributesConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> { public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java

@ -44,7 +44,7 @@ import org.thingsboard.server.common.msg.TbMsg;
"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.", "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.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeEntityDetailsConfig", configDirective = "tbEnrichmentNodeEntityDetailsConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration> { public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java

@ -40,7 +40,7 @@ import org.thingsboard.server.common.msg.TbMsg;
"<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ", "<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeDeviceAttributesConfig", configDirective = "tbEnrichmentNodeDeviceAttributesConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> { public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java

@ -45,7 +45,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.", nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeOriginatorFieldsConfig", configDirective = "tbEnrichmentNodeOriginatorFieldsConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetOriginatorFieldsNode implements TbNode { public class TbGetOriginatorFieldsNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java

@ -37,7 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
"<code>metadata.temperature</code>.", "<code>metadata.temperature</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbEnrichmentNodeRelatedAttributesConfig", configDirective = "tbEnrichmentNodeRelatedAttributesConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> { public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java

@ -68,7 +68,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE;
"<b>Note</b>: The maximum size of the fetched array is 1000 records.\n ", "<b>Note</b>: The maximum size of the fetched array is 1000 records.\n ",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase", configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetTelemetryNode implements TbNode { public class TbGetTelemetryNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java

@ -37,7 +37,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
"<code>metadata.temperature</code>.", "<code>metadata.temperature</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbEnrichmentNodeTenantAttributesConfig", configDirective = "tbEnrichmentNodeTenantAttributesConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> { public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java

@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg;
"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.", "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.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeEntityDetailsConfig", configDirective = "tbEnrichmentNodeEntityDetailsConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration> { public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration> {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java

@ -51,7 +51,7 @@ import java.util.concurrent.TimeoutException;
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbActionNodeMqttConfig", configDirective = "tbActionNodeMqttConfig",
icon = "call_split", icon = "call_split",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMqttNode implements TbNode { public class TbMqttNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java

@ -41,7 +41,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeRabbitMqConfig", configDirective = "tbActionNodeRabbitMqConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbRabbitMqNode implements TbNode { public class TbRabbitMqNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java

@ -41,7 +41,7 @@ import org.thingsboard.server.common.msg.TbMsg;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeRestApiCallConfig", configDirective = "tbActionNodeRestApiCallConfig",
iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+", iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbRestApiCallNode implements TbNode { public class TbRestApiCallNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java

@ -41,7 +41,7 @@ import java.util.UUID;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeRpcReplyConfig", configDirective = "tbActionNodeRpcReplyConfig",
icon = "call_merge", icon = "call_merge",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbSendRPCReplyNode implements TbNode { public class TbSendRPCReplyNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java

@ -52,7 +52,7 @@ import java.util.concurrent.TimeUnit;
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbActionNodeRpcRequestConfig", configDirective = "tbActionNodeRpcRequestConfig",
icon = "call_made", icon = "call_made",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbSendRPCRequestNode implements TbNode { public class TbSendRPCRequestNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java

@ -46,7 +46,7 @@ import java.util.Set;
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbActionNodeAttributesConfig", configDirective = "tbActionNodeAttributesConfig",
icon = "file_upload", icon = "file_upload",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgAttributesNode implements TbNode { public class TbMsgAttributesNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java

@ -47,7 +47,7 @@ import java.util.Map;
uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
configDirective = "tbActionNodeTimeseriesConfig", configDirective = "tbActionNodeTimeseriesConfig",
icon = "file_upload", icon = "file_upload",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
public class TbMsgTimeseriesNode implements TbNode { public class TbMsgTimeseriesNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java

@ -40,7 +40,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
"Size of the queue per originator and timeout values are configurable on a system level", "Size of the queue per originator and timeout values are configurable on a system level",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbNodeEmptyConfig", configDirective = "tbNodeEmptyConfig",
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
@Deprecated @Deprecated
public class TbSynchronizationBeginNode implements TbNode { public class TbSynchronizationBeginNode implements TbNode {

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java

@ -40,7 +40,7 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
nodeDetails = "", nodeDetails = "",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = ("tbNodeEmptyConfig"), configDirective = ("tbNodeEmptyConfig"),
ruleChainTypes = {RuleChainType.SYSTEM, RuleChainType.EDGE} ruleChainTypes = {RuleChainType.CORE, RuleChainType.EDGE}
) )
@Deprecated @Deprecated
public class TbSynchronizationEndNode implements TbNode { public class TbSynchronizationEndNode implements TbNode {

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save