19 changed files with 642 additions and 64 deletions
@ -0,0 +1,41 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.actors.ruleChain; |
|||
|
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.ToString; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.RuleNodeId; |
|||
import org.thingsboard.server.common.msg.MsgType; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
|
|||
/** |
|||
* Created by ashvayka on 19.03.18. |
|||
*/ |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@ToString |
|||
public final class RuleChainInputMsg extends TbToRuleChainActorMsg { |
|||
|
|||
public RuleChainInputMsg(RuleChainId target, TbMsg tbMsg) { |
|||
super(tbMsg, target); |
|||
} |
|||
|
|||
@Override |
|||
public MsgType getMsgType() { |
|||
return MsgType.RULE_CHAIN_INPUT_MSG; |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.actors.ruleChain; |
|||
|
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.ToString; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.RuleNodeId; |
|||
import org.thingsboard.server.common.msg.MsgType; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
|
|||
/** |
|||
* Created by ashvayka on 19.03.18. |
|||
*/ |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@ToString |
|||
public final class RuleChainOutputMsg extends TbToRuleChainActorMsg { |
|||
|
|||
@Getter |
|||
private final RuleNodeId targetRuleNodeId; |
|||
|
|||
@Getter |
|||
private final String relationType; |
|||
|
|||
public RuleChainOutputMsg(RuleChainId target, RuleNodeId targetRuleNodeId, String relationType, TbMsg tbMsg) { |
|||
super(tbMsg, target); |
|||
this.targetRuleNodeId = targetRuleNodeId; |
|||
this.relationType = relationType; |
|||
} |
|||
|
|||
@Override |
|||
public MsgType getMsgType() { |
|||
return MsgType.RULE_CHAIN_OUTPUT_MSG; |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.actors.ruleChain; |
|||
|
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.ToString; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.msg.TbActorStopReason; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
import org.thingsboard.server.common.msg.TbRuleEngineActorMsg; |
|||
import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg; |
|||
import org.thingsboard.server.common.msg.queue.RuleEngineException; |
|||
|
|||
@EqualsAndHashCode(callSuper = true) |
|||
@ToString |
|||
public abstract class TbToRuleChainActorMsg extends TbRuleEngineActorMsg implements RuleChainAwareMsg { |
|||
|
|||
@Getter |
|||
private final RuleChainId target; |
|||
|
|||
public TbToRuleChainActorMsg(TbMsg msg, RuleChainId target) { |
|||
super(msg); |
|||
this.target = target; |
|||
} |
|||
|
|||
@Override |
|||
public RuleChainId getRuleChainId() { |
|||
return target; |
|||
} |
|||
|
|||
@Override |
|||
public void onTbActorStopped(TbActorStopReason reason) { |
|||
String message = reason == TbActorStopReason.STOPPED ? String.format("Rule chain [%s] stopped", target.getId()) : String.format("Failed to initialize rule chain [%s]!", target.getId()); |
|||
msg.getCallback().onFailure(new RuleEngineException(message)); |
|||
} |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.msg; |
|||
|
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.RuleNodeId; |
|||
import org.thingsboard.server.common.msg.gen.MsgProtos; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.LinkedList; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
|
|||
/** |
|||
* Created by ashvayka on 13.01.18. |
|||
*/ |
|||
public final class TbMsgProcessingCtx implements Serializable { |
|||
|
|||
private final AtomicInteger ruleNodeExecCounter; |
|||
private volatile LinkedList<TbMsgProcessingStackItem> stack; |
|||
|
|||
public TbMsgProcessingCtx() { |
|||
this(0); |
|||
} |
|||
|
|||
public TbMsgProcessingCtx(int ruleNodeExecCounter) { |
|||
this(ruleNodeExecCounter, null); |
|||
} |
|||
|
|||
protected TbMsgProcessingCtx(int ruleNodeExecCounter, LinkedList<TbMsgProcessingStackItem> stack) { |
|||
this.ruleNodeExecCounter = new AtomicInteger(ruleNodeExecCounter); |
|||
this.stack = stack; |
|||
} |
|||
|
|||
public int getAndIncrementRuleNodeCounter() { |
|||
return ruleNodeExecCounter.getAndIncrement(); |
|||
} |
|||
|
|||
public TbMsgProcessingCtx copy() { |
|||
return new TbMsgProcessingCtx(ruleNodeExecCounter.get()); |
|||
} |
|||
|
|||
public void push(RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
|||
if (stack == null) { |
|||
stack = new LinkedList<>(); |
|||
} |
|||
stack.add(new TbMsgProcessingStackItem(ruleChainId, ruleNodeId)); |
|||
} |
|||
|
|||
public TbMsgProcessingStackItem pop() { |
|||
return !stack.isEmpty() ? stack.removeLast() : null; |
|||
} |
|||
|
|||
public static TbMsgProcessingCtx fromProto(MsgProtos.TbMsgProcessingCtxProto ctx) { |
|||
int ruleNodeExecCounter = ctx.getRuleNodeExecCounter(); |
|||
if (ctx.getStackCount() > 0) { |
|||
LinkedList<TbMsgProcessingStackItem> stack = new LinkedList<>(); |
|||
for (MsgProtos.TbMsgProcessingStackItemProto item : ctx.getStackList()) { |
|||
stack.add(new TbMsgProcessingStackItem( |
|||
new RuleChainId(new UUID(item.getRuleChainIdMSB(), item.getRuleChainIdLSB())), |
|||
new RuleNodeId(new UUID(item.getRuleNodeIdMSB(), item.getRuleNodeIdLSB())) |
|||
)); |
|||
} |
|||
return new TbMsgProcessingCtx(ruleNodeExecCounter, stack); |
|||
} else { |
|||
return new TbMsgProcessingCtx(ruleNodeExecCounter); |
|||
} |
|||
} |
|||
|
|||
public MsgProtos.TbMsgProcessingCtxProto toProto() { |
|||
var ctxBuilder = MsgProtos.TbMsgProcessingCtxProto.newBuilder(); |
|||
ctxBuilder.setRuleNodeExecCounter(ruleNodeExecCounter.get()); |
|||
if (stack != null) { |
|||
for (TbMsgProcessingStackItem item : stack) { |
|||
ctxBuilder.addStack(item.toProto()); |
|||
} |
|||
} |
|||
return ctxBuilder.build(); |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.msg; |
|||
|
|||
import lombok.Data; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.RuleNodeId; |
|||
import org.thingsboard.server.common.msg.gen.MsgProtos; |
|||
|
|||
@Data |
|||
public class TbMsgProcessingStackItem { |
|||
|
|||
private final RuleChainId ruleChainId; |
|||
private final RuleNodeId ruleNodeId; |
|||
|
|||
MsgProtos.TbMsgProcessingStackItemProto toProto() { |
|||
return MsgProtos.TbMsgProcessingStackItemProto.newBuilder() |
|||
.setRuleChainIdMSB(ruleChainId.getId().getMostSignificantBits()) |
|||
.setRuleChainIdLSB(ruleChainId.getId().getLeastSignificantBits()) |
|||
.setRuleNodeIdMSB(ruleNodeId.getId().getMostSignificantBits()) |
|||
.setRuleNodeIdLSB(ruleNodeId.getId().getLeastSignificantBits()) |
|||
.build(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.flow; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.rule.engine.api.RuleNode; |
|||
import org.thingsboard.rule.engine.api.TbContext; |
|||
import org.thingsboard.rule.engine.api.TbNode; |
|||
import org.thingsboard.rule.engine.api.TbNodeConfiguration; |
|||
import org.thingsboard.rule.engine.api.TbNodeException; |
|||
import org.thingsboard.rule.engine.api.TbRelationTypes; |
|||
import org.thingsboard.rule.engine.api.util.TbNodeUtils; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.id.EntityIdFactory; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentType; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
@Slf4j |
|||
@RuleNode( |
|||
type = ComponentType.ACTION, |
|||
name = "rule chain input", |
|||
configClazz = TbRuleChainInputNodeConfiguration.class, |
|||
nodeDescription = "transfers the message to another rule chain", |
|||
nodeDetails = "Allows to nest the rule chain similar to single rule node. " + |
|||
"The incoming message is forwarded to the input node of the specified target rule chain. " + |
|||
"The target rule chain may produce multiple labeled outputs. " + |
|||
"You may use the outputs to forward the results of processing to other rule nodes.", |
|||
customRelations = true |
|||
) |
|||
public class TbRuleChainInputNode implements TbNode { |
|||
|
|||
private TbRuleChainInputNodeConfiguration config; |
|||
private RuleChainId ruleChainId; |
|||
|
|||
@Override |
|||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { |
|||
this.config = TbNodeUtils.convert(configuration, TbRuleChainInputNodeConfiguration.class); |
|||
this.ruleChainId = new RuleChainId(UUID.fromString(config.getRuleChainId())); |
|||
} |
|||
|
|||
@Override |
|||
public void onMsg(TbContext ctx, TbMsg msg) { |
|||
ctx.input(msg, ruleChainId); |
|||
} |
|||
|
|||
@Override |
|||
public void destroy() { |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.flow; |
|||
|
|||
import lombok.Data; |
|||
import org.thingsboard.rule.engine.api.NodeConfiguration; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
|
|||
@Data |
|||
public class TbRuleChainInputNodeConfiguration implements NodeConfiguration<TbRuleChainInputNodeConfiguration> { |
|||
|
|||
private String ruleChainId; |
|||
|
|||
@Override |
|||
public TbRuleChainInputNodeConfiguration defaultConfiguration() { |
|||
return new TbRuleChainInputNodeConfiguration(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.flow; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.rule.engine.api.RuleNode; |
|||
import org.thingsboard.rule.engine.api.TbContext; |
|||
import org.thingsboard.rule.engine.api.TbNode; |
|||
import org.thingsboard.rule.engine.api.TbNodeConfiguration; |
|||
import org.thingsboard.rule.engine.api.TbNodeException; |
|||
import org.thingsboard.rule.engine.api.TbRelationTypes; |
|||
import org.thingsboard.rule.engine.api.util.TbNodeUtils; |
|||
import org.thingsboard.server.common.data.plugin.ComponentType; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
|
|||
@Slf4j |
|||
@RuleNode( |
|||
type = ComponentType.ACTION, |
|||
name = "rule chain output", |
|||
configClazz = TbRuleChainOutputNodeConfiguration.class, |
|||
nodeDescription = "transfers the message to the caller rule chain", |
|||
nodeDetails = "Produces output of the rule chain processing. " + |
|||
"The output is forwarded to the caller rule chain, as an output of the corresponding \"input\" rule node. " + |
|||
"The rule node configuration contains the \"label\" parameter. " + |
|||
"This parameter corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain. ", |
|||
outEnabled = false |
|||
) |
|||
public class TbRuleChainOutputNode implements TbNode { |
|||
|
|||
private TbRuleChainOutputNodeConfiguration config; |
|||
|
|||
@Override |
|||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { |
|||
this.config = TbNodeUtils.convert(configuration, TbRuleChainOutputNodeConfiguration.class); |
|||
} |
|||
|
|||
@Override |
|||
public void onMsg(TbContext ctx, TbMsg msg) { |
|||
ctx.output(msg, config.getLabel()); |
|||
} |
|||
|
|||
@Override |
|||
public void destroy() { |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2021 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.flow; |
|||
|
|||
import lombok.Data; |
|||
import org.thingsboard.rule.engine.api.NodeConfiguration; |
|||
import org.thingsboard.rule.engine.api.TbRelationTypes; |
|||
import org.thingsboard.server.common.data.DataConstants; |
|||
|
|||
@Data |
|||
public class TbRuleChainOutputNodeConfiguration implements NodeConfiguration<TbRuleChainOutputNodeConfiguration> { |
|||
|
|||
private String label; |
|||
|
|||
@Override |
|||
public TbRuleChainOutputNodeConfiguration defaultConfiguration() { |
|||
var result = new TbRuleChainOutputNodeConfiguration(); |
|||
result.setLabel(TbRelationTypes.SUCCESS); |
|||
return result; |
|||
} |
|||
|
|||
} |
|||
Loading…
Reference in new issue