Showing
19 changed files
with
497 additions
and
2 deletions
... | ... | @@ -247,7 +247,7 @@ spring: |
247 | 247 | database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.HSQLDialect}" |
248 | 248 | datasource: |
249 | 249 | driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.hsqldb.jdbc.JDBCDriver}" |
250 | - url: "${SPRING_DATASOURCE_URL:jdbc:hsqldb:file:${SQL_DATA_FOLDER:/tmp}/thingsboardDb;sql.enforce_size=false}" | |
250 | + url: "${SPRING_DATASOURCE_URL:jdbc:hsqldb:file:${SQL_DATA_FOLDER:/tmp}/thingsboardDb;sql.enforce_size=false;hsqldb.log_size=5}" | |
251 | 251 | username: "${SPRING_DATASOURCE_USERNAME:sa}" |
252 | 252 | password: "${SPRING_DATASOURCE_PASSWORD:}" |
253 | 253 | ... | ... |
rule-engine/pom.xml
0 → 100644
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2017 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
20 | + <modelVersion>4.0.0</modelVersion> | |
21 | + <parent> | |
22 | + <groupId>org.thingsboard</groupId> | |
23 | + <version>1.4.0-SNAPSHOT</version> | |
24 | + <artifactId>thingsboard</artifactId> | |
25 | + </parent> | |
26 | + <groupId>org.thingsboard</groupId> | |
27 | + <artifactId>rule-engine</artifactId> | |
28 | + <packaging>pom</packaging> | |
29 | + | |
30 | + <name>Thingsboard Extensions</name> | |
31 | + <url>https://thingsboard.io</url> | |
32 | + | |
33 | + <properties> | |
34 | + <main.dir>${basedir}/..</main.dir> | |
35 | + </properties> | |
36 | + | |
37 | + <modules> | |
38 | + <module>rule-engine-api</module> | |
39 | + <module>rule-engine-components</module> | |
40 | + </modules> | |
41 | + | |
42 | +</project> | ... | ... |
rule-engine/rule-engine-api/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!-- | |
3 | + | |
4 | + Copyright © 2016-2017 The Thingsboard Authors | |
5 | + | |
6 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | + you may not use this file except in compliance with the License. | |
8 | + You may obtain a copy of the License at | |
9 | + | |
10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
11 | + | |
12 | + Unless required by applicable law or agreed to in writing, software | |
13 | + distributed under the License is distributed on an "AS IS" BASIS, | |
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | + See the License for the specific language governing permissions and | |
16 | + limitations under the License. | |
17 | + | |
18 | +--> | |
19 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | |
20 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
21 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
22 | + <modelVersion>4.0.0</modelVersion> | |
23 | + <parent> | |
24 | + <groupId>org.thingsboard</groupId> | |
25 | + <version>1.4.0-SNAPSHOT</version> | |
26 | + <artifactId>rule-engine</artifactId> | |
27 | + </parent> | |
28 | + <groupId>org.thingsboard.rule-engine</groupId> | |
29 | + <artifactId>rule-engine-api</artifactId> | |
30 | + <packaging>jar</packaging> | |
31 | + | |
32 | + <name>Thingsboard Rule Engine API</name> | |
33 | + <url>https://thingsboard.io</url> | |
34 | + | |
35 | + <properties> | |
36 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
37 | + <main.dir>${basedir}/../..</main.dir> | |
38 | + </properties> | |
39 | + | |
40 | + <dependencies> | |
41 | + <dependency> | |
42 | + <groupId>org.thingsboard.common</groupId> | |
43 | + <artifactId>message</artifactId> | |
44 | + <scope>provided</scope> | |
45 | + </dependency> | |
46 | + <dependency> | |
47 | + <groupId>org.thingsboard</groupId> | |
48 | + <artifactId>extensions-api</artifactId> | |
49 | + <scope>provided</scope> | |
50 | + </dependency> | |
51 | + <dependency> | |
52 | + <groupId>org.thingsboard</groupId> | |
53 | + <artifactId>dao</artifactId> | |
54 | + <scope>provided</scope> | |
55 | + </dependency> | |
56 | + <dependency> | |
57 | + <groupId>ch.qos.logback</groupId> | |
58 | + <artifactId>logback-core</artifactId> | |
59 | + <scope>provided</scope> | |
60 | + </dependency> | |
61 | + <dependency> | |
62 | + <groupId>ch.qos.logback</groupId> | |
63 | + <artifactId>logback-classic</artifactId> | |
64 | + <scope>provided</scope> | |
65 | + </dependency> | |
66 | + </dependencies> | |
67 | +</project> | |
\ No newline at end of file | ... | ... |
1 | +package org.thingsboard.rule.engine.api; | |
2 | + | |
3 | +import org.thingsboard.server.common.msg.cluster.ServerAddress; | |
4 | +import org.thingsboard.server.dao.attributes.AttributesService; | |
5 | + | |
6 | +import java.util.UUID; | |
7 | + | |
8 | +/** | |
9 | + * Created by ashvayka on 13.01.18. | |
10 | + */ | |
11 | +public interface TbContext { | |
12 | + | |
13 | + void tellNext(TbMsg msg); | |
14 | + | |
15 | + void tellNext(TbMsg msg, String relationType); | |
16 | + | |
17 | + void tellSelf(TbMsg msg, long delayMs); | |
18 | + | |
19 | + void tellOthers(TbMsg msg); | |
20 | + | |
21 | + void tellSibling(TbMsg msg, ServerAddress address); | |
22 | + | |
23 | + void spawn(TbMsg msg); | |
24 | + | |
25 | + void ack(UUID msg); | |
26 | + | |
27 | + AttributesService getAttributesService(); | |
28 | + | |
29 | +} | ... | ... |
1 | +package org.thingsboard.rule.engine.api; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import org.thingsboard.server.common.data.id.EntityId; | |
5 | + | |
6 | +import java.io.Serializable; | |
7 | +import java.util.UUID; | |
8 | + | |
9 | +/** | |
10 | + * Created by ashvayka on 13.01.18. | |
11 | + */ | |
12 | +@Data | |
13 | +public final class TbMsg implements Serializable { | |
14 | + | |
15 | + private final UUID id; | |
16 | + private final String type; | |
17 | + private final EntityId originator; | |
18 | + private final TbMsgMetaData metaData; | |
19 | + | |
20 | + private final byte[] data; | |
21 | + | |
22 | +} | ... | ... |
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbMsgMetaData.java
0 → 100644
1 | +package org.thingsboard.rule.engine.api; | |
2 | + | |
3 | +import lombok.Data; | |
4 | + | |
5 | +import java.io.Serializable; | |
6 | +import java.util.Map; | |
7 | + | |
8 | +/** | |
9 | + * Created by ashvayka on 13.01.18. | |
10 | + */ | |
11 | +@Data | |
12 | +public final class TbMsgMetaData implements Serializable { | |
13 | + | |
14 | + private Map<String, String> data; | |
15 | + | |
16 | + public String getValue(String key) { | |
17 | + return data.get(key); | |
18 | + } | |
19 | + | |
20 | + public void putValue(String key, String value) { | |
21 | + data.put(key, value); | |
22 | + } | |
23 | + | |
24 | +} | ... | ... |
1 | +package org.thingsboard.rule.engine.api; | |
2 | + | |
3 | +import java.util.concurrent.ExecutionException; | |
4 | + | |
5 | +/** | |
6 | + * Created by ashvayka on 19.01.18. | |
7 | + */ | |
8 | +public interface TbNode { | |
9 | + | |
10 | + void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException; | |
11 | + | |
12 | + void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException; | |
13 | + | |
14 | + void destroy(); | |
15 | + | |
16 | +} | ... | ... |
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbNodeException.java
0 → 100644
1 | +package org.thingsboard.rule.engine.api; | |
2 | + | |
3 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
4 | + | |
5 | +/** | |
6 | + * Created by ashvayka on 19.01.18. | |
7 | + */ | |
8 | +public class TbNodeException extends Exception { | |
9 | + | |
10 | + public TbNodeException(Exception e) { | |
11 | + super(e); | |
12 | + } | |
13 | + | |
14 | +} | ... | ... |
rule-engine/rule-engine-components/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!-- | |
3 | + | |
4 | + Copyright © 2016-2017 The Thingsboard Authors | |
5 | + | |
6 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | + you may not use this file except in compliance with the License. | |
8 | + You may obtain a copy of the License at | |
9 | + | |
10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
11 | + | |
12 | + Unless required by applicable law or agreed to in writing, software | |
13 | + distributed under the License is distributed on an "AS IS" BASIS, | |
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | + See the License for the specific language governing permissions and | |
16 | + limitations under the License. | |
17 | + | |
18 | +--> | |
19 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | |
20 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
21 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
22 | + <modelVersion>4.0.0</modelVersion> | |
23 | + <parent> | |
24 | + <groupId>org.thingsboard</groupId> | |
25 | + <version>1.4.0-SNAPSHOT</version> | |
26 | + <artifactId>rule-engine</artifactId> | |
27 | + </parent> | |
28 | + <groupId>org.thingsboard.rule-engine</groupId> | |
29 | + <artifactId>rule-engine-components</artifactId> | |
30 | + <packaging>jar</packaging> | |
31 | + | |
32 | + <name>Thingsboard Rule Engine Components</name> | |
33 | + <url>https://thingsboard.io</url> | |
34 | + | |
35 | + <properties> | |
36 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
37 | + <main.dir>${basedir}/../..</main.dir> | |
38 | + </properties> | |
39 | + | |
40 | + <dependencies> | |
41 | + <dependency> | |
42 | + <groupId>org.thingsboard</groupId> | |
43 | + <artifactId>dao</artifactId> | |
44 | + <scope>provided</scope> | |
45 | + </dependency> | |
46 | + <dependency> | |
47 | + <groupId>ch.qos.logback</groupId> | |
48 | + <artifactId>logback-core</artifactId> | |
49 | + <scope>provided</scope> | |
50 | + </dependency> | |
51 | + <dependency> | |
52 | + <groupId>ch.qos.logback</groupId> | |
53 | + <artifactId>logback-classic</artifactId> | |
54 | + <scope>provided</scope> | |
55 | + </dependency> | |
56 | + <dependency> | |
57 | + <groupId>org.thingsboard</groupId> | |
58 | + <artifactId>extensions-api</artifactId> | |
59 | + <scope>provided</scope> | |
60 | + </dependency> | |
61 | + <dependency> | |
62 | + <groupId>org.thingsboard.rule-engine</groupId> | |
63 | + <artifactId>rule-engine-api</artifactId> | |
64 | + <version>1.4.0-SNAPSHOT</version> | |
65 | + </dependency> | |
66 | + </dependencies> | |
67 | +</project> | |
\ No newline at end of file | ... | ... |
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/TbNodeUtils.java
0 → 100644
1 | +package org.thingsboard.rule.engine; | |
2 | + | |
3 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
4 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
5 | +import org.thingsboard.rule.engine.api.TbNodeConfiguration; | |
6 | +import org.thingsboard.rule.engine.api.TbNodeException; | |
7 | + | |
8 | +/** | |
9 | + * Created by ashvayka on 19.01.18. | |
10 | + */ | |
11 | +public class TbNodeUtils { | |
12 | + | |
13 | + private static final ObjectMapper mapper = new ObjectMapper(); | |
14 | + | |
15 | + public static <T> T convert(TbNodeConfiguration configuration, Class<T> clazz) throws TbNodeException { | |
16 | + try { | |
17 | + return mapper.treeToValue(configuration.getData(), clazz); | |
18 | + } catch (JsonProcessingException e) { | |
19 | + throw new TbNodeException(e); | |
20 | + } | |
21 | + } | |
22 | + | |
23 | +} | ... | ... |
1 | +package org.thingsboard.rule.engine.filter; | |
2 | + | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.thingsboard.rule.engine.TbNodeUtils; | |
5 | +import org.thingsboard.rule.engine.api.*; | |
6 | +import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; | |
7 | +import org.thingsboard.server.common.data.DataConstants; | |
8 | +import org.thingsboard.server.common.data.kv.AttributeKvEntry; | |
9 | +import org.thingsboard.server.dao.attributes.AttributesService; | |
10 | + | |
11 | +import java.util.List; | |
12 | + | |
13 | +/** | |
14 | + * Created by ashvayka on 19.01.18. | |
15 | + */ | |
16 | +@Slf4j | |
17 | +public class TbMsgTypeFilterNode implements TbNode { | |
18 | + | |
19 | + TbMsgTypeFilterNodeConfiguration config; | |
20 | + | |
21 | + @Override | |
22 | + public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException { | |
23 | + this.config = TbNodeUtils.convert(configuration, TbMsgTypeFilterNodeConfiguration.class); | |
24 | + } | |
25 | + | |
26 | + @Override | |
27 | + public void onMsg(TbContext ctx, TbMsg msg) throws TbNodeException { | |
28 | + ctx.tellNext(msg, Boolean.toString(config.getMessageTypes().contains(msg.getType()))); | |
29 | + } | |
30 | + | |
31 | + @Override | |
32 | + public void destroy() { | |
33 | + | |
34 | + } | |
35 | +} | ... | ... |
1 | +package org.thingsboard.rule.engine.metadata; | |
2 | + | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.thingsboard.rule.engine.TbNodeUtils; | |
5 | +import org.thingsboard.rule.engine.api.*; | |
6 | +import org.thingsboard.server.common.data.DataConstants; | |
7 | +import org.thingsboard.server.common.data.kv.AttributeKvEntry; | |
8 | +import org.thingsboard.server.dao.attributes.AttributesService; | |
9 | + | |
10 | +import java.util.List; | |
11 | + | |
12 | +/** | |
13 | + * Created by ashvayka on 19.01.18. | |
14 | + */ | |
15 | +@Slf4j | |
16 | +public class TbGetAttributesNode implements TbNode { | |
17 | + | |
18 | + TbGetAttributesNodeConfiguration config; | |
19 | + | |
20 | + @Override | |
21 | + public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException { | |
22 | + this.config = TbNodeUtils.convert(configuration, TbGetAttributesNodeConfiguration.class); | |
23 | + } | |
24 | + | |
25 | + @Override | |
26 | + public void onMsg(TbContext ctx, TbMsg msg) throws TbNodeException { | |
27 | + try { | |
28 | + //TODO: refactor this to work async and fetch attributes from cache. | |
29 | + AttributesService service = ctx.getAttributesService(); | |
30 | + fetchAttributes(msg, service, config.getClientAttributeNames(), DataConstants.CLIENT_SCOPE, "cs."); | |
31 | + fetchAttributes(msg, service, config.getServerAttributeNames(), DataConstants.SERVER_SCOPE, "ss."); | |
32 | + fetchAttributes(msg, service, config.getSharedAttributeNames(), DataConstants.SHARED_SCOPE, "shared."); | |
33 | + ctx.tellNext(msg); | |
34 | + } catch (Exception e) { | |
35 | + log.warn("[{}][{}] Failed to fetch attributes", msg.getOriginator(), msg.getId(), e); | |
36 | + throw new TbNodeException(e); | |
37 | + } | |
38 | + } | |
39 | + | |
40 | + private void fetchAttributes(TbMsg msg, AttributesService service, List<String> attributeNames, String scope, String prefix) throws InterruptedException, java.util.concurrent.ExecutionException { | |
41 | + if (attributeNames != null && attributeNames.isEmpty()) { | |
42 | + List<AttributeKvEntry> attributes = service.find(msg.getOriginator(), scope, attributeNames).get(); | |
43 | + attributes.forEach(attr -> msg.getMetaData().putValue(prefix + attr.getKey(), attr.getValueAsString())); | |
44 | + } | |
45 | + } | |
46 | + | |
47 | + @Override | |
48 | + public void destroy() { | |
49 | + | |
50 | + } | |
51 | +} | ... | ... |
1 | +package org.thingsboard.rule.engine.metadata; | |
2 | + | |
3 | +import lombok.Data; | |
4 | + | |
5 | +import java.util.List; | |
6 | + | |
7 | +/** | |
8 | + * Created by ashvayka on 19.01.18. | |
9 | + */ | |
10 | +@Data | |
11 | +public class TbGetAttributesNodeConfiguration { | |
12 | + | |
13 | + private List<String> clientAttributeNames; | |
14 | + private List<String> sharedAttributeNames; | |
15 | + private List<String> serverAttributeNames; | |
16 | + | |
17 | +} | ... | ... |
1 | +package org.thingsboard.rule.engine.transform; | |
2 | + | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.thingsboard.rule.engine.TbNodeUtils; | |
5 | +import org.thingsboard.rule.engine.api.*; | |
6 | +import org.thingsboard.rule.engine.metadata.TbGetAttributesNodeConfiguration; | |
7 | +import org.thingsboard.server.common.data.DataConstants; | |
8 | +import org.thingsboard.server.common.data.kv.AttributeKvEntry; | |
9 | +import org.thingsboard.server.dao.attributes.AttributesService; | |
10 | + | |
11 | +import java.util.List; | |
12 | + | |
13 | +/** | |
14 | + * Created by ashvayka on 19.01.18. | |
15 | + */ | |
16 | +@Slf4j | |
17 | +public class TbTransformNode implements TbNode { | |
18 | + | |
19 | + TbGetAttributesNodeConfiguration config; | |
20 | + | |
21 | + @Override | |
22 | + public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException { | |
23 | + this.config = TbNodeUtils.convert(configuration, TbGetAttributesNodeConfiguration.class); | |
24 | + } | |
25 | + | |
26 | + @Override | |
27 | + public void onMsg(TbContext ctx, TbMsg msg) throws TbNodeException { | |
28 | + try { | |
29 | + //TODO: refactor this to work async and fetch attributes from cache. | |
30 | + AttributesService service = ctx.getAttributesService(); | |
31 | + fetchAttributes(msg, service, config.getClientAttributeNames(), DataConstants.CLIENT_SCOPE, "cs."); | |
32 | + fetchAttributes(msg, service, config.getServerAttributeNames(), DataConstants.SERVER_SCOPE, "ss."); | |
33 | + fetchAttributes(msg, service, config.getSharedAttributeNames(), DataConstants.SHARED_SCOPE, "shared."); | |
34 | + ctx.tellNext(msg); | |
35 | + } catch (Exception e) { | |
36 | + log.warn("[{}][{}] Failed to fetch attributes", msg.getOriginator(), msg.getId(), e); | |
37 | + throw new TbNodeException(e); | |
38 | + } | |
39 | + } | |
40 | + | |
41 | + private void fetchAttributes(TbMsg msg, AttributesService service, List<String> attributeNames, String scope, String prefix) throws InterruptedException, java.util.concurrent.ExecutionException { | |
42 | + if (attributeNames != null && attributeNames.isEmpty()) { | |
43 | + List<AttributeKvEntry> attributes = service.find(msg.getOriginator(), scope, attributeNames).get(); | |
44 | + attributes.forEach(attr -> msg.getMetaData().putValue(prefix + attr.getKey(), attr.getValueAsString())); | |
45 | + } | |
46 | + } | |
47 | + | |
48 | + @Override | |
49 | + public void destroy() { | |
50 | + | |
51 | + } | |
52 | +} | ... | ... |