Commit 1f39d20ab77ad9ed178f11dc68424879f9732e89
Committed by
GitHub
Merge pull request #296 from thingsboard/feature/rpc-rule
RPC rule feature
Showing
14 changed files
with
414 additions
and
6 deletions
... | ... | @@ -44,6 +44,7 @@ import org.thingsboard.server.dao.customer.CustomerService; |
44 | 44 | import org.thingsboard.server.dao.device.DeviceService; |
45 | 45 | import org.thingsboard.server.dao.event.EventService; |
46 | 46 | import org.thingsboard.server.dao.plugin.PluginService; |
47 | +import org.thingsboard.server.dao.relation.RelationService; | |
47 | 48 | import org.thingsboard.server.dao.rule.RuleService; |
48 | 49 | import org.thingsboard.server.dao.tenant.TenantService; |
49 | 50 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
... | ... | @@ -110,6 +111,9 @@ public class ActorSystemContext { |
110 | 111 | @Getter private AlarmService alarmService; |
111 | 112 | |
112 | 113 | @Autowired |
114 | + @Getter private RelationService relationService; | |
115 | + | |
116 | + @Autowired | |
113 | 117 | @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint; |
114 | 118 | |
115 | 119 | @Value("${actors.session.sync.timeout}") | ... | ... |
... | ... | @@ -33,6 +33,8 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; |
33 | 33 | import org.thingsboard.server.common.data.kv.TsKvQuery; |
34 | 34 | import org.thingsboard.server.common.data.page.TextPageLink; |
35 | 35 | import org.thingsboard.server.common.data.plugin.PluginMetaData; |
36 | +import org.thingsboard.server.common.data.relation.EntityRelation; | |
37 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | |
36 | 38 | import org.thingsboard.server.common.data.rule.RuleMetaData; |
37 | 39 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
38 | 40 | import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; |
... | ... | @@ -395,6 +397,16 @@ public final class PluginProcessingContext implements PluginContext { |
395 | 397 | } |
396 | 398 | |
397 | 399 | @Override |
400 | + public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) { | |
401 | + return this.pluginCtx.relationService.findByFromAndType(from, relationType, RelationTypeGroup.COMMON); | |
402 | + } | |
403 | + | |
404 | + @Override | |
405 | + public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) { | |
406 | + return this.pluginCtx.relationService.findByToAndType(from, relationType, RelationTypeGroup.COMMON); | |
407 | + } | |
408 | + | |
409 | + @Override | |
398 | 410 | public Optional<ServerAddress> resolve(EntityId entityId) { |
399 | 411 | return pluginCtx.routingService.resolveById(entityId); |
400 | 412 | } | ... | ... |
... | ... | @@ -30,6 +30,7 @@ import org.thingsboard.server.dao.attributes.AttributesService; |
30 | 30 | import org.thingsboard.server.dao.customer.CustomerService; |
31 | 31 | import org.thingsboard.server.dao.device.DeviceService; |
32 | 32 | import org.thingsboard.server.dao.plugin.PluginService; |
33 | +import org.thingsboard.server.dao.relation.RelationService; | |
33 | 34 | import org.thingsboard.server.dao.rule.RuleService; |
34 | 35 | import org.thingsboard.server.dao.tenant.TenantService; |
35 | 36 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
... | ... | @@ -61,6 +62,7 @@ public final class SharedPluginProcessingContext { |
61 | 62 | final AttributesService attributesService; |
62 | 63 | final ClusterRpcService rpcService; |
63 | 64 | final ClusterRoutingService routingService; |
65 | + final RelationService relationService; | |
64 | 66 | final PluginId pluginId; |
65 | 67 | final TenantId tenantId; |
66 | 68 | |
... | ... | @@ -83,6 +85,7 @@ public final class SharedPluginProcessingContext { |
83 | 85 | this.pluginService = sysContext.getPluginService(); |
84 | 86 | this.customerService = sysContext.getCustomerService(); |
85 | 87 | this.tenantService = sysContext.getTenantService(); |
88 | + this.relationService = sysContext.getRelationService(); | |
86 | 89 | } |
87 | 90 | |
88 | 91 | public PluginId getPluginId() { | ... | ... |
... | ... | @@ -7,13 +7,13 @@ |
7 | 7 | </encoder> |
8 | 8 | </appender> |
9 | 9 | |
10 | - <logger name="org.thingsboard.server" level="INFO"/> | |
10 | + <logger name="org.thingsboard.server" level="WARN"/> | |
11 | 11 | <logger name="org.springframework" level="WARN"/> |
12 | 12 | <logger name="org.springframework.boot.test" level="DEBUG"/> |
13 | 13 | <logger name="org.apache.cassandra" level="WARN"/> |
14 | 14 | <logger name="org.cassandraunit" level="INFO"/> |
15 | 15 | |
16 | - <logger name="akka" level="DEBUG" /> | |
16 | + <logger name="akka" level="INFO" /> | |
17 | 17 | |
18 | 18 | <root level="WARN"> |
19 | 19 | <appender-ref ref="console"/> | ... | ... |
... | ... | @@ -9,8 +9,8 @@ |
9 | 9 | |
10 | 10 | <logger name="org.thingsboard.server.dao" level="WARN"/> |
11 | 11 | <logger name="org.apache.cassandra" level="WARN"/> |
12 | - <logger name="org.cassandraunit" level="INFO" /> | |
13 | - <logger name="org.apache.cassandra" level="INFO" /> | |
12 | + <logger name="org.cassandraunit" level="WARN" /> | |
13 | + <logger name="org.apache.cassandra" level="WARN" /> | |
14 | 14 | |
15 | 15 | <root level="WARN"> |
16 | 16 | <appender-ref ref="console"/> | ... | ... |
... | ... | @@ -15,11 +15,14 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.extensions.api.plugins; |
17 | 17 | |
18 | +import com.google.common.util.concurrent.ListenableFuture; | |
18 | 19 | import org.thingsboard.server.common.data.Device; |
19 | 20 | import org.thingsboard.server.common.data.id.*; |
20 | 21 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
21 | 22 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
22 | 23 | import org.thingsboard.server.common.data.kv.TsKvQuery; |
24 | +import org.thingsboard.server.common.data.relation.EntityRelation; | |
25 | +import org.thingsboard.server.common.data.relation.RelationTypeGroup; | |
23 | 26 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
24 | 27 | import org.thingsboard.server.extensions.api.plugins.msg.PluginToRuleMsg; |
25 | 28 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; |
... | ... | @@ -109,4 +112,12 @@ public interface PluginContext { |
109 | 112 | |
110 | 113 | void getCustomerDevices(TenantId tenantId, CustomerId customerId, int limit, PluginCallback<List<Device>> callback); |
111 | 114 | |
115 | + | |
116 | + /* | |
117 | + * Relations API | |
118 | + * */ | |
119 | + | |
120 | + ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType); | |
121 | + | |
122 | + ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType); | |
112 | 123 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.extensions.core.action.rpc; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.apache.velocity.Template; | |
20 | +import org.apache.velocity.VelocityContext; | |
21 | +import org.apache.velocity.runtime.parser.ParseException; | |
22 | +import org.springframework.util.StringUtils; | |
23 | +import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | |
24 | +import org.thingsboard.server.common.msg.session.ToDeviceMsg; | |
25 | +import org.thingsboard.server.extensions.api.component.Action; | |
26 | +import org.thingsboard.server.extensions.api.plugins.PluginAction; | |
27 | +import org.thingsboard.server.extensions.api.plugins.msg.PluginToRuleMsg; | |
28 | +import org.thingsboard.server.extensions.api.plugins.msg.ResponsePluginToRuleMsg; | |
29 | +import org.thingsboard.server.extensions.api.plugins.msg.RuleToPluginMsg; | |
30 | +import org.thingsboard.server.extensions.api.rules.RuleContext; | |
31 | +import org.thingsboard.server.extensions.api.rules.RuleProcessingMetaData; | |
32 | +import org.thingsboard.server.extensions.api.rules.SimpleRuleLifecycleComponent; | |
33 | +import org.thingsboard.server.extensions.core.utils.VelocityUtils; | |
34 | + | |
35 | +import java.util.Optional; | |
36 | + | |
37 | +/** | |
38 | + * Created by ashvayka on 14.09.17. | |
39 | + */ | |
40 | +@Action(name = "Server Side RPC Call Action", descriptor = "ServerSideRpcCallActionDescriptor.json", configuration = ServerSideRpcCallActionConfiguration.class) | |
41 | +@Slf4j | |
42 | +public class ServerSideRpcCallAction extends SimpleRuleLifecycleComponent implements PluginAction<ServerSideRpcCallActionConfiguration> { | |
43 | + | |
44 | + private ServerSideRpcCallActionConfiguration configuration; | |
45 | + private Optional<Template> deviceIdTemplate; | |
46 | + private Optional<Template> fromDeviceRelationTemplate; | |
47 | + private Optional<Template> toDeviceRelationTemplate; | |
48 | + private Optional<Template> rpcCallMethodTemplate; | |
49 | + private Optional<Template> rpcCallBodyTemplate; | |
50 | + | |
51 | + @Override | |
52 | + public void init(ServerSideRpcCallActionConfiguration configuration) { | |
53 | + this.configuration = configuration; | |
54 | + try { | |
55 | + deviceIdTemplate = toTemplate(configuration.getDeviceIdTemplate(), "Device Id Template"); | |
56 | + fromDeviceRelationTemplate = toTemplate(configuration.getFromDeviceRelationTemplate(), "From Device Relation Template"); | |
57 | + toDeviceRelationTemplate = toTemplate(configuration.getToDeviceRelationTemplate(), "To Device Relation Template"); | |
58 | + rpcCallMethodTemplate = toTemplate(configuration.getRpcCallMethodTemplate(), "RPC Call Method Template"); | |
59 | + rpcCallBodyTemplate = toTemplate(configuration.getRpcCallBodyTemplate(), "RPC Call Body Template"); | |
60 | + } catch (ParseException e) { | |
61 | + log.error("Failed to create templates based on provided configuration!", e); | |
62 | + throw new RuntimeException("Failed to create templates based on provided configuration!", e); | |
63 | + } | |
64 | + } | |
65 | + | |
66 | + @Override | |
67 | + public Optional<RuleToPluginMsg<?>> convert(RuleContext ctx, ToDeviceActorMsg toDeviceActorMsg, RuleProcessingMetaData metadata) { | |
68 | + String sendFlag = configuration.getSendFlag(); | |
69 | + if (StringUtils.isEmpty(sendFlag) || (Boolean) metadata.get(sendFlag).orElse(Boolean.FALSE)) { | |
70 | + VelocityContext context = VelocityUtils.createContext(metadata); | |
71 | + | |
72 | + ServerSideRpcCallActionMsg.ServerSideRpcCallActionMsgBuilder builder = ServerSideRpcCallActionMsg.builder(); | |
73 | + | |
74 | + deviceIdTemplate.ifPresent(t -> builder.deviceId(VelocityUtils.merge(t, context))); | |
75 | + fromDeviceRelationTemplate.ifPresent(t -> builder.fromDeviceRelation(VelocityUtils.merge(t, context))); | |
76 | + toDeviceRelationTemplate.ifPresent(t -> builder.toDeviceRelation(VelocityUtils.merge(t, context))); | |
77 | + rpcCallMethodTemplate.ifPresent(t -> builder.rpcCallMethod(VelocityUtils.merge(t, context))); | |
78 | + rpcCallBodyTemplate.ifPresent(t -> builder.rpcCallBody(VelocityUtils.merge(t, context))); | |
79 | + return Optional.of(new ServerSideRpcCallRuleToPluginActionMsg(toDeviceActorMsg.getTenantId(), toDeviceActorMsg.getCustomerId(), toDeviceActorMsg.getDeviceId(), | |
80 | + builder.build())); | |
81 | + } else { | |
82 | + return Optional.empty(); | |
83 | + } | |
84 | + } | |
85 | + | |
86 | + private Optional<Template> toTemplate(String source, String name) throws ParseException { | |
87 | + if (!StringUtils.isEmpty(source)) { | |
88 | + return Optional.of(VelocityUtils.create(source, name)); | |
89 | + } else { | |
90 | + return Optional.empty(); | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + @Override | |
95 | + public Optional<ToDeviceMsg> convert(PluginToRuleMsg<?> response) { | |
96 | + if (response instanceof ResponsePluginToRuleMsg) { | |
97 | + return Optional.of(((ResponsePluginToRuleMsg) response).getPayload()); | |
98 | + } | |
99 | + return Optional.empty(); | |
100 | + } | |
101 | + | |
102 | + @Override | |
103 | + public boolean isOneWayAction() { | |
104 | + return true; | |
105 | + } | |
106 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.extensions.core.action.rpc; | |
17 | + | |
18 | +import lombok.Data; | |
19 | + | |
20 | +/** | |
21 | + * @author Andrew Shvayka | |
22 | + */ | |
23 | +@Data | |
24 | +public class ServerSideRpcCallActionConfiguration { | |
25 | + | |
26 | + private String sendFlag; | |
27 | + | |
28 | + private String deviceIdTemplate; | |
29 | + private String rpcCallMethodTemplate; | |
30 | + private String rpcCallBodyTemplate; | |
31 | + private long rpcCallTimeoutInSec; | |
32 | + private String fromDeviceRelationTemplate; | |
33 | + private String toDeviceRelationTemplate; | |
34 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.extensions.core.action.rpc; | |
17 | + | |
18 | +import lombok.Builder; | |
19 | +import lombok.Data; | |
20 | + | |
21 | +import java.io.Serializable; | |
22 | + | |
23 | +/** | |
24 | + * Created by ashvayka on 14.09.17. | |
25 | + */ | |
26 | +@Data | |
27 | +@Builder | |
28 | +public class ServerSideRpcCallActionMsg implements Serializable { | |
29 | + | |
30 | + private String deviceId; | |
31 | + private String rpcCallMethod; | |
32 | + private String rpcCallBody; | |
33 | + private long rpcCallTimeoutInSec; | |
34 | + | |
35 | + private String fromDeviceRelation; | |
36 | + private String toDeviceRelation; | |
37 | + | |
38 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.extensions.core.action.rpc; | |
17 | + | |
18 | +import org.thingsboard.server.common.data.id.CustomerId; | |
19 | +import org.thingsboard.server.common.data.id.DeviceId; | |
20 | +import org.thingsboard.server.common.data.id.TenantId; | |
21 | +import org.thingsboard.server.extensions.api.plugins.msg.AbstractRuleToPluginMsg; | |
22 | + | |
23 | +/** | |
24 | + * Created by ashvayka on 14.09.17. | |
25 | + */ | |
26 | +public class ServerSideRpcCallRuleToPluginActionMsg extends AbstractRuleToPluginMsg<ServerSideRpcCallActionMsg> { | |
27 | + | |
28 | + public ServerSideRpcCallRuleToPluginActionMsg(TenantId tenantId, CustomerId customerId, DeviceId deviceId, | |
29 | + ServerSideRpcCallActionMsg payload) { | |
30 | + super(tenantId, customerId, deviceId, payload); | |
31 | + } | |
32 | +} | ... | ... |
... | ... | @@ -19,15 +19,19 @@ import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.thingsboard.server.extensions.api.component.Plugin; |
20 | 20 | import org.thingsboard.server.extensions.api.plugins.AbstractPlugin; |
21 | 21 | import org.thingsboard.server.extensions.api.plugins.PluginContext; |
22 | +import org.thingsboard.server.extensions.api.plugins.handlers.DefaultRuleMsgHandler; | |
22 | 23 | import org.thingsboard.server.extensions.api.plugins.handlers.RestMsgHandler; |
24 | +import org.thingsboard.server.extensions.api.plugins.handlers.RuleMsgHandler; | |
23 | 25 | import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse; |
24 | 26 | import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; |
27 | +import org.thingsboard.server.extensions.core.action.rpc.ServerSideRpcCallAction; | |
25 | 28 | import org.thingsboard.server.extensions.core.plugin.rpc.handlers.RpcRestMsgHandler; |
29 | +import org.thingsboard.server.extensions.core.plugin.rpc.handlers.RpcRuleMsgHandler; | |
26 | 30 | |
27 | 31 | /** |
28 | 32 | * @author Andrew Shvayka |
29 | 33 | */ |
30 | -@Plugin(name = "RPC Plugin", actions = {}, descriptor = "RpcPluginDescriptor.json", configuration = RpcPluginConfiguration.class) | |
34 | +@Plugin(name = "RPC Plugin", actions = {ServerSideRpcCallAction.class}, descriptor = "RpcPluginDescriptor.json", configuration = RpcPluginConfiguration.class) | |
31 | 35 | @Slf4j |
32 | 36 | public class RpcPlugin extends AbstractPlugin<RpcPluginConfiguration> { |
33 | 37 | |
... | ... | @@ -61,6 +65,11 @@ public class RpcPlugin extends AbstractPlugin<RpcPluginConfiguration> { |
61 | 65 | } |
62 | 66 | |
63 | 67 | @Override |
68 | + protected RuleMsgHandler getRuleMsgHandler() { | |
69 | + return new RpcRuleMsgHandler(); | |
70 | + } | |
71 | + | |
72 | + @Override | |
64 | 73 | public void resume(PluginContext ctx) { |
65 | 74 | |
66 | 75 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.extensions.core.plugin.rpc.handlers; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.springframework.util.StringUtils; | |
20 | +import org.thingsboard.server.common.data.id.DeviceId; | |
21 | +import org.thingsboard.server.common.data.id.EntityId; | |
22 | +import org.thingsboard.server.common.data.id.RuleId; | |
23 | +import org.thingsboard.server.common.data.id.TenantId; | |
24 | +import org.thingsboard.server.common.data.relation.EntityRelation; | |
25 | +import org.thingsboard.server.extensions.api.plugins.PluginCallback; | |
26 | +import org.thingsboard.server.extensions.api.plugins.PluginContext; | |
27 | +import org.thingsboard.server.extensions.api.plugins.handlers.RuleMsgHandler; | |
28 | +import org.thingsboard.server.extensions.api.plugins.msg.RuleToPluginMsg; | |
29 | +import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest; | |
30 | +import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestBody; | |
31 | +import org.thingsboard.server.extensions.api.rules.RuleException; | |
32 | +import org.thingsboard.server.extensions.core.action.rpc.ServerSideRpcCallActionMsg; | |
33 | +import org.thingsboard.server.extensions.core.action.rpc.ServerSideRpcCallRuleToPluginActionMsg; | |
34 | + | |
35 | +import java.util.Collections; | |
36 | +import java.util.List; | |
37 | +import java.util.UUID; | |
38 | +import java.util.concurrent.TimeUnit; | |
39 | +import java.util.stream.Collectors; | |
40 | + | |
41 | +/** | |
42 | + * Created by ashvayka on 14.09.17. | |
43 | + */ | |
44 | +@Slf4j | |
45 | +public class RpcRuleMsgHandler implements RuleMsgHandler { | |
46 | + | |
47 | + @Override | |
48 | + public void process(PluginContext ctx, TenantId tenantId, RuleId ruleId, RuleToPluginMsg<?> msg) throws RuleException { | |
49 | + if (msg instanceof ServerSideRpcCallRuleToPluginActionMsg) { | |
50 | + handle(ctx, tenantId, ruleId, ((ServerSideRpcCallRuleToPluginActionMsg) msg).getPayload()); | |
51 | + } else { | |
52 | + throw new RuntimeException("Not supported msg: " + msg + "!"); | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + private void handle(final PluginContext ctx, TenantId tenantId, RuleId ruleId, ServerSideRpcCallActionMsg msg) { | |
57 | + DeviceId deviceId = new DeviceId(UUID.fromString(msg.getDeviceId())); | |
58 | + ctx.checkAccess(deviceId, new PluginCallback<Void>() { | |
59 | + @Override | |
60 | + public void onSuccess(PluginContext dummy, Void value) { | |
61 | + try { | |
62 | + List<EntityId> deviceIds; | |
63 | + if (StringUtils.isEmpty(msg.getFromDeviceRelation()) && StringUtils.isEmpty(msg.getToDeviceRelation())) { | |
64 | + deviceIds = Collections.singletonList(deviceId); | |
65 | + } else if (!StringUtils.isEmpty(msg.getFromDeviceRelation())) { | |
66 | + List<EntityRelation> relations = ctx.findByFromAndType(deviceId, msg.getFromDeviceRelation()).get(); | |
67 | + deviceIds = relations.stream().map(EntityRelation::getTo).collect(Collectors.toList()); | |
68 | + } else { | |
69 | + List<EntityRelation> relations = ctx.findByToAndType(deviceId, msg.getFromDeviceRelation()).get(); | |
70 | + deviceIds = relations.stream().map(EntityRelation::getFrom).collect(Collectors.toList()); | |
71 | + } | |
72 | + ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(msg.getRpcCallMethod(), msg.getRpcCallBody()); | |
73 | + long expirationTime = System.currentTimeMillis() + msg.getRpcCallTimeoutInSec(); | |
74 | + for (EntityId address : deviceIds) { | |
75 | + DeviceId tmpId = new DeviceId(address.getId()); | |
76 | + ctx.checkAccess(tmpId, new PluginCallback<Void>() { | |
77 | + @Override | |
78 | + public void onSuccess(PluginContext ctx, Void value) { | |
79 | + ctx.sendRpcRequest(new ToDeviceRpcRequest(UUID.randomUUID(), | |
80 | + tenantId, tmpId, true, expirationTime, body) | |
81 | + ); | |
82 | + log.trace("[{}] Sent RPC Call Action msg", tmpId); | |
83 | + } | |
84 | + | |
85 | + @Override | |
86 | + public void onFailure(PluginContext ctx, Exception e) { | |
87 | + log.info("[{}] Failed to process RPC Call Action msg", tmpId, e); | |
88 | + } | |
89 | + }); | |
90 | + } | |
91 | + } catch (Exception e) { | |
92 | + log.info("Failed to process RPC Call Action msg", e); | |
93 | + } | |
94 | + } | |
95 | + | |
96 | + @Override | |
97 | + public void onFailure(PluginContext dummy, Exception e) { | |
98 | + log.info("[{}] Failed to process RPC Call Action msg", deviceId, e); | |
99 | + } | |
100 | + }); | |
101 | + } | |
102 | +} | ... | ... |
1 | +{ | |
2 | + "schema": { | |
3 | + "title": "Send Mail Action Configuration", | |
4 | + "type": "object", | |
5 | + "properties": { | |
6 | + "sendFlag": { | |
7 | + "title": "Send flag (empty or 'isNewAlarm', 'isExistingAlarm', 'isClearedAlarm', 'isNewOrClearedAlarm')", | |
8 | + "type": "string" | |
9 | + }, | |
10 | + "deviceIdTemplate": { | |
11 | + "title": "Device ID template", | |
12 | + "type": "string", | |
13 | + "default": "$deviceId" | |
14 | + }, | |
15 | + "rpcCallMethodTemplate": { | |
16 | + "title": "RPC Call template", | |
17 | + "type": "string" | |
18 | + }, | |
19 | + "rpcCallBodyTemplate": { | |
20 | + "title": "RPC Call Body template", | |
21 | + "type": "string" | |
22 | + }, | |
23 | + "rpcCallTimeoutInSec": { | |
24 | + "title": "RPC Call timeout in seconds", | |
25 | + "type": "integer", | |
26 | + "default": 60 | |
27 | + }, | |
28 | + "fromDeviceRelationTemplate": { | |
29 | + "title": "From Device Relation template", | |
30 | + "type": "string" | |
31 | + }, | |
32 | + "toDeviceRelationTemplate": { | |
33 | + "title": "To Device Relation template", | |
34 | + "type": "string" | |
35 | + } | |
36 | + }, | |
37 | + "required": [ | |
38 | + "deviceIdTemplate", | |
39 | + "rpcCallMethodTemplate", | |
40 | + "rpcCallBodyTemplate", | |
41 | + "rpcCallTimeoutInSec" | |
42 | + ] | |
43 | + }, | |
44 | + "form": [ | |
45 | + "sendFlag", | |
46 | + "deviceIdTemplate", | |
47 | + "rpcCallMethodTemplate", | |
48 | + { | |
49 | + "key": "rpcCallBodyTemplate", | |
50 | + "type": "textarea", | |
51 | + "rows": 5 | |
52 | + }, | |
53 | + "rpcCallTimeoutInSec", | |
54 | + "fromDeviceRelationTemplate", | |
55 | + "toDeviceRelationTemplate" | |
56 | + ] | |
57 | +} | |
\ No newline at end of file | ... | ... |