Commit de3dd0f7d3f1fd859aa73ba946f147f3c6198576

Authored by Andrew Shvayka
Committed by GitHub
2 parents 494bb544 69aac973

Merge pull request #725 from thingsboard/feature/rpc-refactoring

Server Side RPC, Telemetry, Default Rule Chain(s), Fixed Integration Tests
Showing 83 changed files with 1396 additions and 1718 deletions

Too many changes to show.

To preserve performance only 83 of 176 files are displayed.

@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 # limitations under the License. 14 # limitations under the License.
15 # 15 #
16 16
17 -export JAVA_OPTS="$JAVA_OPTS -Dplatform=@pkg.platform@" 17 +export JAVA_OPTS="$JAVA_OPTS -Dplatform=@pkg.platform@ -Dinstall.data_dir=@pkg.installFolder@"
18 export LOG_FILENAME=${pkg.name}.out 18 export LOG_FILENAME=${pkg.name}.out
19 export LOADER_PATH=${pkg.installFolder}/conf,${pkg.installFolder}/extensions 19 export LOADER_PATH=${pkg.installFolder}/conf,${pkg.installFolder}/extensions
20 export SQL_DATA_FOLDER=${pkg.installFolder}/data/sql 20 export SQL_DATA_FOLDER=${pkg.installFolder}/data/sql
1 -{  
2 - "apiToken": "messaging",  
3 - "name": "Demo Device Messaging RPC Plugin",  
4 - "clazz": "org.thingsboard.server.extensions.core.plugin.messaging.DeviceMessagingPlugin",  
5 - "publicAccess": false,  
6 - "state": "ACTIVE",  
7 - "configuration": {  
8 - "maxDeviceCountPerCustomer": 1024,  
9 - "defaultTimeout": 20000,  
10 - "maxTimeout": 60000  
11 - },  
12 - "additionalInfo": null  
13 -}  
1 -{  
2 - "apiToken": "mail",  
3 - "name": "Demo Email Plugin",  
4 - "clazz": "org.thingsboard.server.extensions.core.plugin.mail.MailPlugin",  
5 - "publicAccess": true,  
6 - "state": "ACTIVE",  
7 - "configuration": {  
8 - "host": "smtp.sendgrid.net",  
9 - "port": 2525,  
10 - "username": "apikey",  
11 - "password": "your_api_key",  
12 - "otherProperties": [  
13 - {  
14 - "key": "mail.smtp.auth",  
15 - "value": "true"  
16 - },  
17 - {  
18 - "key": "mail.smtp.timeout",  
19 - "value": "10000"  
20 - },  
21 - {  
22 - "key": "mail.smtp.starttls.enable",  
23 - "value": "true"  
24 - }  
25 - ]  
26 - },  
27 - "additionalInfo": null  
28 -}  
1 -{  
2 - "apiToken": "time",  
3 - "name": "Demo Time RPC Plugin",  
4 - "clazz": "org.thingsboard.server.extensions.core.plugin.time.TimePlugin",  
5 - "publicAccess": false,  
6 - "state": "ACTIVE",  
7 - "configuration": {  
8 - "timeFormat": "yyyy MM dd HH:mm:ss.SSS"  
9 - },  
10 - "additionalInfo": null  
11 -}  
1 -{  
2 - "name": "Demo Alarm Rule",  
3 - "state": "ACTIVE",  
4 - "weight": 0,  
5 - "pluginToken": "mail",  
6 - "filters": [  
7 - {  
8 - "clazz": "org.thingsboard.server.extensions.core.filter.MsgTypeFilter",  
9 - "name": "MsgTypeFilter",  
10 - "configuration": {  
11 - "messageTypes": [  
12 - "POST_TELEMETRY",  
13 - "POST_ATTRIBUTES",  
14 - "GET_ATTRIBUTES"  
15 - ]  
16 - }  
17 - },  
18 - {  
19 - "clazz": "org.thingsboard.server.extensions.core.filter.DeviceTelemetryFilter",  
20 - "name": "Temperature filter",  
21 - "configuration": {  
22 - "filter": "typeof temperature !== 'undefined' && temperature >= 100"  
23 - }  
24 - }  
25 - ],  
26 - "processor": {  
27 - "clazz": "org.thingsboard.server.extensions.core.processor.AlarmDeduplicationProcessor",  
28 - "name": "AlarmDeduplicationProcessor",  
29 - "configuration": {  
30 - "alarmIdTemplate": "[$date.get('yyyy-MM-dd HH:mm')] Device $cs.get('serialNumber')($cs.get('model')) temperature is high!",  
31 - "alarmBodyTemplate": "[$date.get('yyyy-MM-dd HH:mm:ss')] Device $cs.get('serialNumber')($cs.get('model')) temperature is $temp.valueAsString!"  
32 - }  
33 - },  
34 - "action": {  
35 - "clazz": "org.thingsboard.server.extensions.core.action.mail.SendMailAction",  
36 - "name": "Send Mail Action",  
37 - "configuration": {  
38 - "sendFlag": "isNewAlarm",  
39 - "fromTemplate": "thingsboard@gmail.com",  
40 - "toTemplate": "thingsboard@gmail.com",  
41 - "subjectTemplate": "$alarmId",  
42 - "bodyTemplate": "$alarmBody"  
43 - }  
44 - },  
45 - "additionalInfo": null  
46 -}  
1 -{  
2 - "name": "Demo getTime RPC Rule",  
3 - "state": "ACTIVE",  
4 - "weight": 0,  
5 - "pluginToken": "time",  
6 - "filters": [  
7 - {  
8 - "configuration": {  
9 - "messageTypes": [  
10 - "RPC_REQUEST"  
11 - ]  
12 - },  
13 - "name": "RPC Request Filter",  
14 - "clazz": "org.thingsboard.server.extensions.core.filter.MsgTypeFilter"  
15 - },  
16 - {  
17 - "configuration": {  
18 - "methodNames": [  
19 - {  
20 - "name": "getTime"  
21 - }  
22 - ]  
23 - },  
24 - "name": "getTime method filter",  
25 - "clazz": "org.thingsboard.server.extensions.core.filter.MethodNameFilter"  
26 - }  
27 - ],  
28 - "processor": null,  
29 - "action": {  
30 - "configuration": {},  
31 - "clazz": "org.thingsboard.server.extensions.core.action.rpc.RpcPluginAction",  
32 - "name": "getTimeAction"  
33 - },  
34 - "additionalInfo": null  
35 -}  
1 -{  
2 - "name": "Demo Messaging RPC Rule",  
3 - "state": "ACTIVE",  
4 - "weight": 0,  
5 - "pluginToken": "messaging",  
6 - "filters": [  
7 - {  
8 - "configuration": {  
9 - "messageTypes": [  
10 - "RPC_REQUEST"  
11 - ]  
12 - },  
13 - "name": "RPC Request Filter",  
14 - "clazz": "org.thingsboard.server.extensions.core.filter.MsgTypeFilter"  
15 - },  
16 - {  
17 - "configuration": {  
18 - "methodNames": [  
19 - {  
20 - "name": "getDevices"  
21 - },  
22 - {  
23 - "name": "sendMsg"  
24 - }  
25 - ]  
26 - },  
27 - "name": "Messaging methods filter",  
28 - "clazz": "org.thingsboard.server.extensions.core.filter.MethodNameFilter"  
29 - }  
30 - ],  
31 - "processor": null,  
32 - "action": {  
33 - "configuration": {},  
34 - "clazz": "org.thingsboard.server.extensions.core.action.rpc.RpcPluginAction",  
35 - "name": "Messaging RPC Action"  
36 - },  
37 - "additionalInfo": null  
38 -}  
1 -{  
2 - "apiToken": "rpc",  
3 - "name": "System RPC Plugin",  
4 - "clazz": "org.thingsboard.server.extensions.core.plugin.rpc.RpcPlugin",  
5 - "publicAccess": true,  
6 - "state": "ACTIVE",  
7 - "configuration": {  
8 - "defaultTimeout": 20000  
9 - },  
10 - "additionalInfo": null  
11 -}  
1 -{  
2 - "apiToken": "telemetry",  
3 - "name": "System Telemetry Plugin",  
4 - "clazz": "org.thingsboard.server.extensions.core.plugin.telemetry.TelemetryStoragePlugin",  
5 - "publicAccess": true,  
6 - "state": "ACTIVE",  
7 - "configuration": {},  
8 - "additionalInfo": null  
9 -}  
1 -{  
2 - "name": "System Telemetry Rule",  
3 - "state": "ACTIVE",  
4 - "weight": 0,  
5 - "pluginToken": "telemetry",  
6 - "filters": [  
7 - {  
8 - "clazz": "org.thingsboard.server.extensions.core.filter.MsgTypeFilter",  
9 - "name": "TelemetryFilter",  
10 - "configuration": {  
11 - "messageTypes": [  
12 - "POST_TELEMETRY",  
13 - "POST_ATTRIBUTES",  
14 - "GET_ATTRIBUTES"  
15 - ]  
16 - }  
17 - }  
18 - ],  
19 - "processor": null,  
20 - "action": {  
21 - "clazz": "org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction",  
22 - "name": "TelemetryMsgConverterAction",  
23 - "configuration": {  
24 - "timeUnit": "DAYS",  
25 - "ttlValue": 365  
26 - }  
27 - },  
28 - "additionalInfo": null  
29 -}  
  1 +{
  2 + "ruleChain": {
  3 + "additionalInfo": null,
  4 + "name": "Root Rule Chain",
  5 + "firstRuleNodeId": null,
  6 + "root": true,
  7 + "debugMode": false,
  8 + "configuration": null
  9 + },
  10 + "metadata": {
  11 + "firstNodeIndex": 2,
  12 + "nodes": [
  13 + {
  14 + "additionalInfo": {
  15 + "layoutX": 639,
  16 + "layoutY": 113
  17 + },
  18 + "type": "org.thingsboard.rule.engine.filter.TbMsgTypeFilterNode",
  19 + "name": "PostAttributes",
  20 + "debugMode": true,
  21 + "configuration": {
  22 + "messageTypes": [
  23 + "POST_ATTRIBUTES_REQUEST"
  24 + ]
  25 + }
  26 + },
  27 + {
  28 + "additionalInfo": {
  29 + "layoutX": 638,
  30 + "layoutY": 206
  31 + },
  32 + "type": "org.thingsboard.rule.engine.filter.TbMsgTypeFilterNode",
  33 + "name": "PostTelemetry",
  34 + "debugMode": true,
  35 + "configuration": {
  36 + "messageTypes": [
  37 + "POST_TELEMETRY_REQUEST"
  38 + ]
  39 + }
  40 + },
  41 + {
  42 + "additionalInfo": {
  43 + "layoutX": 297,
  44 + "layoutY": 148
  45 + },
  46 + "type": "org.thingsboard.rule.engine.action.TbLogNode",
  47 + "name": "Log",
  48 + "debugMode": false,
  49 + "configuration": {
  50 + "jsScript": "return 'incoming message = ' + msg;"
  51 + }
  52 + },
  53 + {
  54 + "additionalInfo": {
  55 + "layoutX": 905,
  56 + "layoutY": 203
  57 + },
  58 + "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
  59 + "name": "SaveTS",
  60 + "debugMode": true,
  61 + "configuration": {
  62 + "defaultTTL": 0
  63 + }
  64 + },
  65 + {
  66 + "additionalInfo": {
  67 + "layoutX": 904,
  68 + "layoutY": 110
  69 + },
  70 + "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
  71 + "name": "save client attributes",
  72 + "debugMode": true,
  73 + "configuration": {
  74 + "scope": "CLIENT_SCOPE"
  75 + }
  76 + }
  77 + ],
  78 + "connections": [
  79 + {
  80 + "fromIndex": 0,
  81 + "toIndex": 4,
  82 + "type": "True"
  83 + },
  84 + {
  85 + "fromIndex": 1,
  86 + "toIndex": 3,
  87 + "type": "True"
  88 + },
  89 + {
  90 + "fromIndex": 2,
  91 + "toIndex": 0,
  92 + "type": "Success"
  93 + },
  94 + {
  95 + "fromIndex": 2,
  96 + "toIndex": 1,
  97 + "type": "Success"
  98 + }
  99 + ],
  100 + "ruleChainConnections": null
  101 + }
  102 +}
@@ -61,6 +61,7 @@ import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; @@ -61,6 +61,7 @@ import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;
61 import org.thingsboard.server.service.component.ComponentDiscoveryService; 61 import org.thingsboard.server.service.component.ComponentDiscoveryService;
62 import org.thingsboard.server.service.executors.DbCallbackExecutorService; 62 import org.thingsboard.server.service.executors.DbCallbackExecutorService;
63 import org.thingsboard.server.service.mail.MailExecutorService; 63 import org.thingsboard.server.service.mail.MailExecutorService;
  64 +import org.thingsboard.server.service.rpc.DeviceRpcService;
64 import org.thingsboard.server.service.script.JsExecutorService; 65 import org.thingsboard.server.service.script.JsExecutorService;
65 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; 66 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
66 67
@@ -163,6 +164,10 @@ public class ActorSystemContext { @@ -163,6 +164,10 @@ public class ActorSystemContext {
163 164
164 @Autowired 165 @Autowired
165 @Getter 166 @Getter
  167 + private DeviceRpcService deviceRpcService;
  168 +
  169 + @Autowired
  170 + @Getter
166 @Setter 171 @Setter
167 private PluginWebSocketMsgEndpoint wsMsgEndpoint; 172 private PluginWebSocketMsgEndpoint wsMsgEndpoint;
168 173
@@ -186,17 +191,13 @@ public class ActorSystemContext { @@ -186,17 +191,13 @@ public class ActorSystemContext {
186 @Getter 191 @Getter
187 private long syncSessionTimeout; 192 private long syncSessionTimeout;
188 193
189 - @Value("${actors.plugin.termination.delay}")  
190 - @Getter  
191 - private long pluginActorTerminationDelay;  
192 -  
193 - @Value("${actors.plugin.processing.timeout}") 194 + @Value("${actors.queue.enabled}")
194 @Getter 195 @Getter
195 - private long pluginProcessingTimeout; 196 + private boolean queuePersistenceEnabled;
196 197
197 - @Value("${actors.plugin.error_persist_frequency}") 198 + @Value("${actors.queue.timeout}")
198 @Getter 199 @Getter
199 - private long pluginErrorPersistFrequency; 200 + private long queuePersistenceTimeout;
200 201
201 @Value("${actors.rule.chain.error_persist_frequency}") 202 @Value("${actors.rule.chain.error_persist_frequency}")
202 @Getter 203 @Getter
@@ -206,14 +207,6 @@ public class ActorSystemContext { @@ -206,14 +207,6 @@ public class ActorSystemContext {
206 @Getter 207 @Getter
207 private long ruleNodeErrorPersistFrequency; 208 private long ruleNodeErrorPersistFrequency;
208 209
209 - @Value("${actors.rule.termination.delay}")  
210 - @Getter  
211 - private long ruleActorTerminationDelay;  
212 -  
213 - @Value("${actors.rule.error_persist_frequency}")  
214 - @Getter  
215 - private long ruleErrorPersistFrequency;  
216 -  
217 @Value("${actors.statistics.enabled}") 210 @Value("${actors.statistics.enabled}")
218 @Getter 211 @Getter
219 private boolean statisticsEnabled; 212 private boolean statisticsEnabled;
@@ -29,13 +29,12 @@ import org.thingsboard.server.actors.shared.plugin.SystemPluginManager; @@ -29,13 +29,12 @@ import org.thingsboard.server.actors.shared.plugin.SystemPluginManager;
29 import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager; 29 import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager;
30 import org.thingsboard.server.actors.tenant.TenantActor; 30 import org.thingsboard.server.actors.tenant.TenantActor;
31 import org.thingsboard.server.common.data.Tenant; 31 import org.thingsboard.server.common.data.Tenant;
32 -import org.thingsboard.server.common.data.id.PluginId;  
33 -import org.thingsboard.server.common.data.id.RuleChainId;  
34 import org.thingsboard.server.common.data.id.TenantId; 32 import org.thingsboard.server.common.data.id.TenantId;
35 import org.thingsboard.server.common.data.page.PageDataIterable; 33 import org.thingsboard.server.common.data.page.PageDataIterable;
36 import org.thingsboard.server.common.msg.TbActorMsg; 34 import org.thingsboard.server.common.msg.TbActorMsg;
37 -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;  
38 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 35 +import org.thingsboard.server.common.msg.aware.DeviceAwareMsg;
  36 +import org.thingsboard.server.common.msg.aware.TenantAwareMsg;
  37 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
39 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 38 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
40 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; 39 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
41 import org.thingsboard.server.dao.model.ModelConstants; 40 import org.thingsboard.server.dao.model.ModelConstants;
@@ -90,12 +89,22 @@ public class AppActor extends RuleChainManagerActor { @@ -90,12 +89,22 @@ public class AppActor extends RuleChainManagerActor {
90 @Override 89 @Override
91 protected boolean process(TbActorMsg msg) { 90 protected boolean process(TbActorMsg msg) {
92 switch (msg.getMsgType()) { 91 switch (msg.getMsgType()) {
  92 + case CLUSTER_EVENT_MSG:
  93 + broadcast(msg);
  94 + break;
93 case COMPONENT_LIFE_CYCLE_MSG: 95 case COMPONENT_LIFE_CYCLE_MSG:
94 onComponentLifecycleMsg((ComponentLifecycleMsg) msg); 96 onComponentLifecycleMsg((ComponentLifecycleMsg) msg);
95 break; 97 break;
96 case SERVICE_TO_RULE_ENGINE_MSG: 98 case SERVICE_TO_RULE_ENGINE_MSG:
97 onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); 99 onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg);
98 break; 100 break;
  101 + case DEVICE_SESSION_TO_DEVICE_ACTOR_MSG:
  102 + case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG:
  103 + case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG:
  104 + case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG:
  105 + case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG:
  106 + onToDeviceActorMsg((TenantAwareMsg) msg);
  107 + break;
99 default: 108 default:
100 return false; 109 return false;
101 } 110 }
@@ -110,48 +119,12 @@ public class AppActor extends RuleChainManagerActor { @@ -110,48 +119,12 @@ public class AppActor extends RuleChainManagerActor {
110 } 119 }
111 } 120 }
112 121
113 -  
114 -// @Override  
115 -// public void onReceive(Object msg) throws Exception {  
116 -// logger.debug("Received message: {}", msg);  
117 -// if (msg instanceof ToDeviceActorMsg) {  
118 -// processDeviceMsg((ToDeviceActorMsg) msg);  
119 -// } else if (msg instanceof ToPluginActorMsg) {  
120 -// onToPluginMsg((ToPluginActorMsg) msg);  
121 -// } else if (msg instanceof ToDeviceActorNotificationMsg) {  
122 -// onToDeviceActorMsg((ToDeviceActorNotificationMsg) msg);  
123 -// } else if (msg instanceof Terminated) {  
124 -// processTermination((Terminated) msg);  
125 -// } else if (msg instanceof ClusterEventMsg) {  
126 -// broadcast(msg);  
127 -// } else if (msg instanceof ComponentLifecycleMsg) {  
128 -// onComponentLifecycleMsg((ComponentLifecycleMsg) msg);  
129 -// } else if (msg instanceof PluginTerminationMsg) {  
130 -// onPluginTerminated((PluginTerminationMsg) msg);  
131 -// } else {  
132 -// logger.warning("Unknown message: {}!", msg);  
133 -// }  
134 -// }  
135 -  
136 - private void onPluginTerminated(PluginTerminationMsg msg) {  
137 - pluginManager.remove(msg.getId());  
138 - }  
139 -  
140 - private void broadcast(Object msg) {  
141 - pluginManager.broadcast(msg); 122 + @Override
  123 + protected void broadcast(Object msg) {
  124 + super.broadcast(msg);
142 tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); 125 tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender()));
143 } 126 }
144 127
145 - private void onToPluginMsg(ToPluginActorMsg msg) {  
146 - ActorRef target;  
147 - if (SYSTEM_TENANT.equals(msg.getPluginTenantId())) {  
148 - target = pluginManager.getOrCreateActor(this.context(), msg.getPluginId());  
149 - } else {  
150 - target = getOrCreateTenantActor(msg.getPluginTenantId());  
151 - }  
152 - target.tell(msg, ActorRef.noSender());  
153 - }  
154 -  
155 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { 128 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
156 ActorRef target; 129 ActorRef target;
157 if (SYSTEM_TENANT.equals(msg.getTenantId())) { 130 if (SYSTEM_TENANT.equals(msg.getTenantId())) {
@@ -166,17 +139,17 @@ public class AppActor extends RuleChainManagerActor { @@ -166,17 +139,17 @@ public class AppActor extends RuleChainManagerActor {
166 } 139 }
167 } 140 }
168 141
169 - private void onToDeviceActorMsg(ToDeviceActorNotificationMsg msg) { 142 + private void onToDeviceActorMsg(TenantAwareMsg msg) {
170 getOrCreateTenantActor(msg.getTenantId()).tell(msg, ActorRef.noSender()); 143 getOrCreateTenantActor(msg.getTenantId()).tell(msg, ActorRef.noSender());
171 } 144 }
172 145
173 - private void processDeviceMsg(ToDeviceActorMsg toDeviceActorMsg) {  
174 - TenantId tenantId = toDeviceActorMsg.getTenantId(); 146 + private void processDeviceMsg(DeviceToDeviceActorMsg deviceToDeviceActorMsg) {
  147 + TenantId tenantId = deviceToDeviceActorMsg.getTenantId();
175 ActorRef tenantActor = getOrCreateTenantActor(tenantId); 148 ActorRef tenantActor = getOrCreateTenantActor(tenantId);
176 - if (toDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) {  
177 -// tenantActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, ruleManager.getRuleChain(this.context())), context().self()); 149 + if (deviceToDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) {
  150 +// tenantActor.tell(new RuleChainDeviceMsg(deviceToDeviceActorMsg, ruleManager.getRuleChain(this.context())), context().self());
178 } else { 151 } else {
179 - tenantActor.tell(toDeviceActorMsg, context().self()); 152 + tenantActor.tell(deviceToDeviceActorMsg, context().self());
180 } 153 }
181 } 154 }
182 155
@@ -24,59 +24,59 @@ import org.thingsboard.server.common.data.id.DeviceId; @@ -24,59 +24,59 @@ import org.thingsboard.server.common.data.id.DeviceId;
24 import org.thingsboard.server.common.data.id.TenantId; 24 import org.thingsboard.server.common.data.id.TenantId;
25 import org.thingsboard.server.common.msg.TbActorMsg; 25 import org.thingsboard.server.common.msg.TbActorMsg;
26 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; 26 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
27 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 27 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
  28 +import org.thingsboard.server.common.msg.timeout.DeviceActorQueueTimeoutMsg;
  29 +import org.thingsboard.server.common.msg.timeout.DeviceActorRpcTimeoutMsg;
28 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; 30 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
29 -import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg;  
30 import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; 31 import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg;
31 -import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;  
32 -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg;  
33 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg; 32 +import org.thingsboard.server.common.msg.timeout.TimeoutMsg;
  33 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
34 34
35 public class DeviceActor extends ContextAwareActor { 35 public class DeviceActor extends ContextAwareActor {
36 36
37 private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this); 37 private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this);
38 38
39 - private final TenantId tenantId;  
40 - private final DeviceId deviceId;  
41 private final DeviceActorMessageProcessor processor; 39 private final DeviceActorMessageProcessor processor;
42 40
43 private DeviceActor(ActorSystemContext systemContext, TenantId tenantId, DeviceId deviceId) { 41 private DeviceActor(ActorSystemContext systemContext, TenantId tenantId, DeviceId deviceId) {
44 super(systemContext); 42 super(systemContext);
45 - this.tenantId = tenantId;  
46 - this.deviceId = deviceId;  
47 - this.processor = new DeviceActorMessageProcessor(systemContext, logger, deviceId); 43 + this.processor = new DeviceActorMessageProcessor(systemContext, logger, tenantId, deviceId);
48 } 44 }
49 45
50 @Override 46 @Override
51 protected boolean process(TbActorMsg msg) { 47 protected boolean process(TbActorMsg msg) {
52 - return false;  
53 - }  
54 -  
55 - @Override  
56 - public void onReceive(Object msg) throws Exception {  
57 -// if (msg instanceof RuleChainDeviceMsg) {  
58 -// processor.process(context(), (RuleChainDeviceMsg) msg);  
59 -// } else if (msg instanceof RulesProcessedMsg) {  
60 -// processor.onRulesProcessedMsg(context(), (RulesProcessedMsg) msg);  
61 - if (msg instanceof ToDeviceActorMsg) {  
62 - processor.process(context(), (ToDeviceActorMsg) msg);  
63 - } else if (msg instanceof ToDeviceActorNotificationMsg) {  
64 - if (msg instanceof DeviceAttributesEventNotificationMsg) { 48 + switch (msg.getMsgType()) {
  49 + case CLUSTER_EVENT_MSG:
  50 + processor.processClusterEventMsg((ClusterEventMsg) msg);
  51 + break;
  52 + case DEVICE_SESSION_TO_DEVICE_ACTOR_MSG:
  53 + processor.process(context(), (DeviceToDeviceActorMsg) msg);
  54 + break;
  55 + case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG:
65 processor.processAttributesUpdate(context(), (DeviceAttributesEventNotificationMsg) msg); 56 processor.processAttributesUpdate(context(), (DeviceAttributesEventNotificationMsg) msg);
66 - } else if (msg instanceof ToDeviceRpcRequestPluginMsg) {  
67 - processor.processRpcRequest(context(), (ToDeviceRpcRequestPluginMsg) msg);  
68 - } else if (msg instanceof DeviceCredentialsUpdateNotificationMsg){ 57 + break;
  58 + case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG:
69 processor.processCredentialsUpdate(); 59 processor.processCredentialsUpdate();
70 - } else if (msg instanceof DeviceNameOrTypeUpdateMsg){ 60 + break;
  61 + case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG:
71 processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg); 62 processor.processNameOrTypeUpdate((DeviceNameOrTypeUpdateMsg) msg);
72 - }  
73 - } else if (msg instanceof TimeoutMsg) {  
74 - processor.processTimeout(context(), (TimeoutMsg) msg);  
75 - } else if (msg instanceof ClusterEventMsg) {  
76 - processor.processClusterEventMsg((ClusterEventMsg) msg);  
77 - } else {  
78 - logger.debug("[{}][{}] Unknown msg type.", tenantId, deviceId, msg.getClass().getName()); 63 + break;
  64 + case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG:
  65 + processor.processRpcRequest(context(), (ToDeviceRpcRequestMsg) msg);
  66 + break;
  67 + case DEVICE_ACTOR_RPC_TIMEOUT_MSG:
  68 + processor.processRpcTimeout(context(), (DeviceActorRpcTimeoutMsg) msg);
  69 + break;
  70 + case DEVICE_ACTOR_QUEUE_TIMEOUT_MSG:
  71 + processor.processQueueTimeout(context(), (DeviceActorQueueTimeoutMsg) msg);
  72 + break;
  73 + case RULE_ENGINE_QUEUE_PUT_ACK_MSG:
  74 + processor.processQueueAck(context(), (RuleEngineQueuePutAckMsg) msg);
  75 + break;
  76 + default:
  77 + return false;
79 } 78 }
  79 + return true;
80 } 80 }
81 81
82 public static class ActorCreator extends ContextBasedCreator<DeviceActor> { 82 public static class ActorCreator extends ContextBasedCreator<DeviceActor> {
@@ -18,29 +18,75 @@ package org.thingsboard.server.actors.device; @@ -18,29 +18,75 @@ package org.thingsboard.server.actors.device;
18 import akka.actor.ActorContext; 18 import akka.actor.ActorContext;
19 import akka.actor.ActorRef; 19 import akka.actor.ActorRef;
20 import akka.event.LoggingAdapter; 20 import akka.event.LoggingAdapter;
  21 +import com.datastax.driver.core.utils.UUIDs;
  22 +import com.google.common.util.concurrent.FutureCallback;
  23 +import com.google.common.util.concurrent.Futures;
  24 +import com.google.common.util.concurrent.ListenableFuture;
  25 +import com.google.gson.Gson;
  26 +import com.google.gson.JsonArray;
  27 +import com.google.gson.JsonObject;
21 import org.thingsboard.server.actors.ActorSystemContext; 28 import org.thingsboard.server.actors.ActorSystemContext;
22 import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; 29 import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor;
23 import org.thingsboard.server.common.data.DataConstants; 30 import org.thingsboard.server.common.data.DataConstants;
24 import org.thingsboard.server.common.data.Device; 31 import org.thingsboard.server.common.data.Device;
25 import org.thingsboard.server.common.data.id.DeviceId; 32 import org.thingsboard.server.common.data.id.DeviceId;
26 import org.thingsboard.server.common.data.id.SessionId; 33 import org.thingsboard.server.common.data.id.SessionId;
  34 +import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.common.data.kv.AttributeKey; 35 import org.thingsboard.server.common.data.kv.AttributeKey;
28 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 36 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  37 +import org.thingsboard.server.common.data.kv.KvEntry;
  38 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
  39 +import org.thingsboard.server.common.msg.TbMsg;
  40 +import org.thingsboard.server.common.msg.TbMsgDataType;
  41 +import org.thingsboard.server.common.msg.TbMsgMetaData;
29 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; 42 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
30 import org.thingsboard.server.common.msg.cluster.ServerAddress; 43 import org.thingsboard.server.common.msg.cluster.ServerAddress;
31 -import org.thingsboard.server.common.msg.core.*;  
32 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 44 +import org.thingsboard.server.common.msg.core.AttributesUpdateNotification;
  45 +import org.thingsboard.server.common.msg.core.AttributesUpdateRequest;
  46 +import org.thingsboard.server.common.msg.core.BasicCommandAckResponse;
  47 +import org.thingsboard.server.common.msg.core.BasicGetAttributesResponse;
  48 +import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse;
  49 +import org.thingsboard.server.common.msg.core.BasicToDeviceSessionActorMsg;
  50 +import org.thingsboard.server.common.msg.core.GetAttributesRequest;
  51 +import org.thingsboard.server.common.msg.core.RuleEngineError;
  52 +import org.thingsboard.server.common.msg.core.RuleEngineErrorMsg;
  53 +import org.thingsboard.server.common.msg.core.SessionCloseMsg;
  54 +import org.thingsboard.server.common.msg.core.SessionCloseNotification;
  55 +import org.thingsboard.server.common.msg.core.SessionOpenMsg;
  56 +import org.thingsboard.server.common.msg.core.StatusCodeResponse;
  57 +import org.thingsboard.server.common.msg.core.TelemetryUploadRequest;
  58 +import org.thingsboard.server.common.msg.core.ToDeviceRpcRequestMsg;
  59 +import org.thingsboard.server.common.msg.core.ToDeviceRpcResponseMsg;
  60 +import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
  61 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
33 import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg; 62 import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg;
  63 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
34 import org.thingsboard.server.common.msg.session.FromDeviceMsg; 64 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
35 -import org.thingsboard.server.common.msg.session.MsgType; 65 +import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg;
  66 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  67 +import org.thingsboard.server.common.msg.session.SessionMsgType;
36 import org.thingsboard.server.common.msg.session.SessionType; 68 import org.thingsboard.server.common.msg.session.SessionType;
37 import org.thingsboard.server.common.msg.session.ToDeviceMsg; 69 import org.thingsboard.server.common.msg.session.ToDeviceMsg;
38 -import org.thingsboard.server.extensions.api.device.DeviceAttributes; 70 +import org.thingsboard.server.common.msg.timeout.DeviceActorQueueTimeoutMsg;
  71 +import org.thingsboard.server.common.msg.timeout.DeviceActorRpcTimeoutMsg;
39 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; 72 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
40 import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; 73 import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg;
41 -import org.thingsboard.server.extensions.api.plugins.msg.*;  
42 -  
43 -import java.util.*; 74 +import org.thingsboard.server.extensions.api.plugins.PluginCallback;
  75 +import org.thingsboard.server.extensions.api.plugins.PluginContext;
  76 +import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse;
  77 +import org.thingsboard.server.extensions.api.plugins.msg.RpcError;
  78 +
  79 +import javax.annotation.Nullable;
  80 +import java.util.ArrayList;
  81 +import java.util.Arrays;
  82 +import java.util.Collections;
  83 +import java.util.HashMap;
  84 +import java.util.HashSet;
  85 +import java.util.List;
  86 +import java.util.Map;
  87 +import java.util.Optional;
  88 +import java.util.Set;
  89 +import java.util.UUID;
44 import java.util.concurrent.ExecutionException; 90 import java.util.concurrent.ExecutionException;
45 import java.util.concurrent.TimeoutException; 91 import java.util.concurrent.TimeoutException;
46 import java.util.function.Consumer; 92 import java.util.function.Consumer;
@@ -52,46 +98,43 @@ import java.util.stream.Collectors; @@ -52,46 +98,43 @@ import java.util.stream.Collectors;
52 */ 98 */
53 public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { 99 public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
54 100
  101 + private final TenantId tenantId;
55 private final DeviceId deviceId; 102 private final DeviceId deviceId;
56 private final Map<SessionId, SessionInfo> sessions; 103 private final Map<SessionId, SessionInfo> sessions;
57 private final Map<SessionId, SessionInfo> attributeSubscriptions; 104 private final Map<SessionId, SessionInfo> attributeSubscriptions;
58 private final Map<SessionId, SessionInfo> rpcSubscriptions; 105 private final Map<SessionId, SessionInfo> rpcSubscriptions;
59 -  
60 private final Map<Integer, ToDeviceRpcRequestMetadata> rpcPendingMap; 106 private final Map<Integer, ToDeviceRpcRequestMetadata> rpcPendingMap;
  107 + private final Map<UUID, PendingSessionMsgData> pendingMsgs;
  108 +
  109 + private final Gson gson = new Gson();
61 110
62 private int rpcSeq = 0; 111 private int rpcSeq = 0;
63 private String deviceName; 112 private String deviceName;
64 private String deviceType; 113 private String deviceType;
65 - private DeviceAttributes deviceAttributes; 114 + private TbMsgMetaData defaultMetaData;
66 115
67 - public DeviceActorMessageProcessor(ActorSystemContext systemContext, LoggingAdapter logger, DeviceId deviceId) { 116 + public DeviceActorMessageProcessor(ActorSystemContext systemContext, LoggingAdapter logger, TenantId tenantId, DeviceId deviceId) {
68 super(systemContext, logger); 117 super(systemContext, logger);
  118 + this.tenantId = tenantId;
69 this.deviceId = deviceId; 119 this.deviceId = deviceId;
70 this.sessions = new HashMap<>(); 120 this.sessions = new HashMap<>();
71 this.attributeSubscriptions = new HashMap<>(); 121 this.attributeSubscriptions = new HashMap<>();
72 this.rpcSubscriptions = new HashMap<>(); 122 this.rpcSubscriptions = new HashMap<>();
73 this.rpcPendingMap = new HashMap<>(); 123 this.rpcPendingMap = new HashMap<>();
  124 + this.pendingMsgs = new HashMap<>();
74 initAttributes(); 125 initAttributes();
75 } 126 }
76 127
77 private void initAttributes() { 128 private void initAttributes() {
78 - //TODO: add invalidation of deviceType cache.  
79 Device device = systemContext.getDeviceService().findDeviceById(deviceId); 129 Device device = systemContext.getDeviceService().findDeviceById(deviceId);
80 this.deviceName = device.getName(); 130 this.deviceName = device.getName();
81 this.deviceType = device.getType(); 131 this.deviceType = device.getType();
82 - this.deviceAttributes = new DeviceAttributes(fetchAttributes(DataConstants.CLIENT_SCOPE),  
83 - fetchAttributes(DataConstants.SERVER_SCOPE), fetchAttributes(DataConstants.SHARED_SCOPE));  
84 - }  
85 -  
86 - private void refreshAttributes(DeviceAttributesEventNotificationMsg msg) {  
87 - if (msg.isDeleted()) {  
88 - msg.getDeletedKeys().forEach(key -> deviceAttributes.remove(key));  
89 - } else {  
90 - deviceAttributes.update(msg.getScope(), msg.getValues());  
91 - } 132 + this.defaultMetaData = new TbMsgMetaData();
  133 + this.defaultMetaData.putValue("deviceName", deviceName);
  134 + this.defaultMetaData.putValue("deviceType", deviceType);
92 } 135 }
93 136
94 - void processRpcRequest(ActorContext context, ToDeviceRpcRequestPluginMsg msg) { 137 + void processRpcRequest(ActorContext context, org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg msg) {
95 ToDeviceRpcRequest request = msg.getMsg(); 138 ToDeviceRpcRequest request = msg.getMsg();
96 ToDeviceRpcRequestBody body = request.getBody(); 139 ToDeviceRpcRequestBody body = request.getBody();
97 ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg( 140 ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg(
@@ -118,9 +161,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -118,9 +161,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
118 syncSessionSet.forEach(rpcSubscriptions::remove); 161 syncSessionSet.forEach(rpcSubscriptions::remove);
119 162
120 if (request.isOneway() && sent) { 163 if (request.isOneway() && sent) {
121 - ToPluginRpcResponseDeviceMsg responsePluginMsg = toPluginRpcResponseMsg(msg, (String) null);  
122 - context.parent().tell(responsePluginMsg, ActorRef.noSender());  
123 logger.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId()); 164 logger.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId());
  165 + systemContext.getDeviceRpcService().process(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null));
124 } else { 166 } else {
125 registerPendingRpcRequest(context, msg, sent, rpcRequest, timeout); 167 registerPendingRpcRequest(context, msg, sent, rpcRequest, timeout);
126 } 168 }
@@ -132,18 +174,36 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -132,18 +174,36 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
132 174
133 } 175 }
134 176
135 - private void registerPendingRpcRequest(ActorContext context, ToDeviceRpcRequestPluginMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) { 177 + private void registerPendingRpcRequest(ActorContext context, org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg msg, boolean sent, ToDeviceRpcRequestMsg rpcRequest, long timeout) {
136 rpcPendingMap.put(rpcRequest.getRequestId(), new ToDeviceRpcRequestMetadata(msg, sent)); 178 rpcPendingMap.put(rpcRequest.getRequestId(), new ToDeviceRpcRequestMetadata(msg, sent));
137 - TimeoutIntMsg timeoutMsg = new TimeoutIntMsg(rpcRequest.getRequestId(), timeout); 179 + DeviceActorRpcTimeoutMsg timeoutMsg = new DeviceActorRpcTimeoutMsg(rpcRequest.getRequestId(), timeout);
138 scheduleMsgWithDelay(context, timeoutMsg, timeoutMsg.getTimeout()); 180 scheduleMsgWithDelay(context, timeoutMsg, timeoutMsg.getTimeout());
139 } 181 }
140 182
141 - public void processTimeout(ActorContext context, TimeoutMsg msg) { 183 + void processRpcTimeout(ActorContext context, DeviceActorRpcTimeoutMsg msg) {
142 ToDeviceRpcRequestMetadata requestMd = rpcPendingMap.remove(msg.getId()); 184 ToDeviceRpcRequestMetadata requestMd = rpcPendingMap.remove(msg.getId());
143 if (requestMd != null) { 185 if (requestMd != null) {
144 logger.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); 186 logger.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId());
145 - ToPluginRpcResponseDeviceMsg responsePluginMsg = toPluginRpcResponseMsg(requestMd.getMsg(), requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION);  
146 - context.parent().tell(responsePluginMsg, ActorRef.noSender()); 187 + systemContext.getDeviceRpcService().process(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(),
  188 + null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION));
  189 + }
  190 + }
  191 +
  192 + void processQueueTimeout(ActorContext context, DeviceActorQueueTimeoutMsg msg) {
  193 + PendingSessionMsgData data = pendingMsgs.remove(msg.getId());
  194 + if (data != null) {
  195 + logger.debug("[{}] Queue put [{}] timeout detected!", deviceId, msg.getId());
  196 + ToDeviceMsg toDeviceMsg = new RuleEngineErrorMsg(data.getSessionMsgType(), RuleEngineError.QUEUE_PUT_TIMEOUT);
  197 + sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(toDeviceMsg, data.getSessionId()), data.getServerAddress());
  198 + }
  199 + }
  200 +
  201 + void processQueueAck(ActorContext context, RuleEngineQueuePutAckMsg msg) {
  202 + PendingSessionMsgData data = pendingMsgs.remove(msg.getId());
  203 + if (data != null) {
  204 + logger.debug("[{}] Queue put [{}] ack detected!", deviceId, msg.getId());
  205 + ToDeviceMsg toDeviceMsg = BasicStatusCodeResponse.onSuccess(data.getSessionMsgType(), data.getRequestId());
  206 + sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(toDeviceMsg, data.getSessionId()), data.getServerAddress());
147 } 207 }
148 } 208 }
149 209
@@ -173,8 +233,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -173,8 +233,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
173 ToDeviceRpcRequestBody body = request.getBody(); 233 ToDeviceRpcRequestBody body = request.getBody();
174 if (request.isOneway()) { 234 if (request.isOneway()) {
175 sentOneWayIds.add(entry.getKey()); 235 sentOneWayIds.add(entry.getKey());
176 - ToPluginRpcResponseDeviceMsg responsePluginMsg = toPluginRpcResponseMsg(entry.getValue().getMsg(), (String) null);  
177 - context.parent().tell(responsePluginMsg, ActorRef.noSender()); 236 + systemContext.getDeviceRpcService().process(new FromDeviceRpcResponse(request.getId(), null, null));
178 } 237 }
179 ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg( 238 ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg(
180 entry.getKey(), 239 entry.getKey(),
@@ -186,14 +245,120 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -186,14 +245,120 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
186 }; 245 };
187 } 246 }
188 247
189 - void process(ActorContext context, ToDeviceActorMsg msg) { 248 + void process(ActorContext context, DeviceToDeviceActorMsg msg) {
190 processSubscriptionCommands(context, msg); 249 processSubscriptionCommands(context, msg);
191 processRpcResponses(context, msg); 250 processRpcResponses(context, msg);
192 processSessionStateMsgs(msg); 251 processSessionStateMsgs(msg);
  252 +
  253 + SessionMsgType sessionMsgType = msg.getPayload().getMsgType();
  254 + if (sessionMsgType.requiresRulesProcessing()) {
  255 + switch (sessionMsgType) {
  256 + case GET_ATTRIBUTES_REQUEST:
  257 + handleGetAttributesRequest(msg);
  258 + break;
  259 + case POST_ATTRIBUTES_REQUEST:
  260 + handlePostAttributesRequest(context, msg);
  261 + break;
  262 + case POST_TELEMETRY_REQUEST:
  263 + handlePostTelemetryRequest(context, msg);
  264 + break;
  265 + case TO_SERVER_RPC_REQUEST:
  266 + break;
  267 + //TODO: push to queue and start processing!
  268 + }
  269 + }
  270 + }
  271 +
  272 + private void handleGetAttributesRequest(DeviceToDeviceActorMsg src) {
  273 + GetAttributesRequest request = (GetAttributesRequest) src.getPayload();
  274 + ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, request.getClientAttributeNames());
  275 + ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, request.getClientAttributeNames());
  276 +
  277 + Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback<List<List<AttributeKvEntry>>>() {
  278 + @Override
  279 + public void onSuccess(@Nullable List<List<AttributeKvEntry>> result) {
  280 + BasicGetAttributesResponse response = BasicGetAttributesResponse.onSuccess(request.getMsgType(),
  281 + request.getRequestId(), BasicAttributeKVMsg.from(result.get(0), result.get(1)));
  282 + sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(response, src.getSessionId()), src.getServerAddress());
  283 + }
  284 +
  285 + @Override
  286 + public void onFailure(Throwable t) {
  287 + if (t instanceof Exception) {
  288 + ToDeviceMsg toDeviceMsg = BasicStatusCodeResponse.onError(SessionMsgType.GET_ATTRIBUTES_REQUEST, request.getRequestId(), (Exception) t);
  289 + sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(toDeviceMsg, src.getSessionId()), src.getServerAddress());
  290 + } else {
  291 + logger.error("[{}] Failed to process attributes request", deviceId, t);
  292 + }
  293 + }
  294 + });
  295 + }
  296 +
  297 + private ListenableFuture<List<AttributeKvEntry>> getAttributeKvEntries(DeviceId deviceId, String scope, Optional<Set<String>> names) {
  298 + if (names.isPresent()) {
  299 + if (!names.get().isEmpty()) {
  300 + return systemContext.getAttributesService().find(deviceId, scope, names.get());
  301 + } else {
  302 + return systemContext.getAttributesService().findAll(deviceId, scope);
  303 + }
  304 + } else {
  305 + return Futures.immediateFuture(Collections.emptyList());
  306 + }
  307 + }
  308 +
  309 + private void handlePostAttributesRequest(ActorContext context, DeviceToDeviceActorMsg src) {
  310 + AttributesUpdateRequest request = (AttributesUpdateRequest) src.getPayload();
  311 +
  312 + JsonObject json = new JsonObject();
  313 + for (AttributeKvEntry kv : request.getAttributes()) {
  314 + kv.getBooleanValue().ifPresent(v -> json.addProperty(kv.getKey(), v));
  315 + kv.getLongValue().ifPresent(v -> json.addProperty(kv.getKey(), v));
  316 + kv.getDoubleValue().ifPresent(v -> json.addProperty(kv.getKey(), v));
  317 + kv.getStrValue().ifPresent(v -> json.addProperty(kv.getKey(), v));
  318 + }
  319 +
  320 + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), deviceId, defaultMetaData, TbMsgDataType.JSON, gson.toJson(json));
  321 + pushToRuleEngineWithTimeout(context, tbMsg, src, request);
  322 + }
  323 +
  324 + private void handlePostTelemetryRequest(ActorContext context, DeviceToDeviceActorMsg src) {
  325 + TelemetryUploadRequest request = (TelemetryUploadRequest) src.getPayload();
  326 +
  327 + Map<Long, List<KvEntry>> tsData = request.getData();
  328 +
  329 + JsonArray json = new JsonArray();
  330 + for (Map.Entry<Long, List<KvEntry>> entry : tsData.entrySet()) {
  331 + JsonObject ts = new JsonObject();
  332 + ts.addProperty("ts", entry.getKey());
  333 + JsonObject values = new JsonObject();
  334 + for (KvEntry kv : entry.getValue()) {
  335 + kv.getBooleanValue().ifPresent(v -> values.addProperty(kv.getKey(), v));
  336 + kv.getLongValue().ifPresent(v -> values.addProperty(kv.getKey(), v));
  337 + kv.getDoubleValue().ifPresent(v -> values.addProperty(kv.getKey(), v));
  338 + kv.getStrValue().ifPresent(v -> values.addProperty(kv.getKey(), v));
  339 + }
  340 + ts.add("values", values);
  341 + json.add(ts);
  342 + }
  343 +
  344 + TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_TELEMETRY_REQUEST.name(), deviceId, defaultMetaData, TbMsgDataType.JSON, gson.toJson(json));
  345 + pushToRuleEngineWithTimeout(context, tbMsg, src, request);
  346 + }
  347 +
  348 + private void pushToRuleEngineWithTimeout(ActorContext context, TbMsg tbMsg, DeviceToDeviceActorMsg src, FromDeviceRequestMsg fromDeviceRequestMsg) {
  349 + SessionMsgType sessionMsgType = fromDeviceRequestMsg.getMsgType();
  350 + int requestId = fromDeviceRequestMsg.getRequestId();
  351 + if (systemContext.isQueuePersistenceEnabled()) {
  352 + pendingMsgs.put(tbMsg.getId(), new PendingSessionMsgData(src.getSessionId(), src.getServerAddress(), sessionMsgType, requestId));
  353 + scheduleMsgWithDelay(context, new DeviceActorQueueTimeoutMsg(tbMsg.getId(), systemContext.getQueuePersistenceTimeout()), systemContext.getQueuePersistenceTimeout());
  354 + } else {
  355 + ToDeviceSessionActorMsg response = new BasicToDeviceSessionActorMsg(BasicStatusCodeResponse.onSuccess(sessionMsgType, requestId), src.getSessionId());
  356 + sendMsgToSessionActor(response, src.getServerAddress());
  357 + }
  358 + context.parent().tell(new DeviceActorToRuleEngineMsg(context.self(), tbMsg), context.self());
193 } 359 }
194 360
195 void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) { 361 void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) {
196 - refreshAttributes(msg);  
197 if (attributeSubscriptions.size() > 0) { 362 if (attributeSubscriptions.size() > 0) {
198 ToDeviceMsg notification = null; 363 ToDeviceMsg notification = null;
199 if (msg.isDeleted()) { 364 if (msg.isDeleted()) {
@@ -223,50 +388,29 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -223,50 +388,29 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
223 } 388 }
224 } 389 }
225 390
226 -// void process(ActorContext context, RuleChainDeviceMsg srcMsg) {  
227 -// ChainProcessingMetaData md = new ChainProcessingMetaData(srcMsg.getRuleChain(),  
228 -// srcMsg.getToDeviceActorMsg(), new DeviceMetaData(deviceId, deviceName, deviceType, deviceAttributes), context.self());  
229 -// ChainProcessingContext ctx = new ChainProcessingContext(md);  
230 -// if (ctx.getChainLength() > 0) {  
231 -// RuleProcessingMsg msg = new RuleProcessingMsg(ctx);  
232 -// ActorRef ruleActorRef = ctx.getCurrentActor();  
233 -// ruleActorRef.tell(msg, ActorRef.noSender());  
234 -// } else {  
235 -// context.self().tell(new RulesProcessedMsg(ctx), context.self());  
236 -// }  
237 -// }  
238 -  
239 - void processRpcResponses(ActorContext context, ToDeviceActorMsg msg) { 391 + private void processRpcResponses(ActorContext context, DeviceToDeviceActorMsg msg) {
240 SessionId sessionId = msg.getSessionId(); 392 SessionId sessionId = msg.getSessionId();
241 FromDeviceMsg inMsg = msg.getPayload(); 393 FromDeviceMsg inMsg = msg.getPayload();
242 - if (inMsg.getMsgType() == MsgType.TO_DEVICE_RPC_RESPONSE) { 394 + if (inMsg.getMsgType() == SessionMsgType.TO_DEVICE_RPC_RESPONSE) {
243 logger.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId); 395 logger.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId);
244 ToDeviceRpcResponseMsg responseMsg = (ToDeviceRpcResponseMsg) inMsg; 396 ToDeviceRpcResponseMsg responseMsg = (ToDeviceRpcResponseMsg) inMsg;
245 ToDeviceRpcRequestMetadata requestMd = rpcPendingMap.remove(responseMsg.getRequestId()); 397 ToDeviceRpcRequestMetadata requestMd = rpcPendingMap.remove(responseMsg.getRequestId());
246 boolean success = requestMd != null; 398 boolean success = requestMd != null;
247 if (success) { 399 if (success) {
248 - ToPluginRpcResponseDeviceMsg responsePluginMsg = toPluginRpcResponseMsg(requestMd.getMsg(), responseMsg.getData());  
249 - Optional<ServerAddress> pluginServerAddress = requestMd.getMsg().getServerAddress();  
250 - if (pluginServerAddress.isPresent()) {  
251 - systemContext.getRpcService().tell(pluginServerAddress.get(), responsePluginMsg);  
252 - logger.debug("[{}] Rpc command response sent to remote plugin actor [{}]!", deviceId, requestMd.getMsg().getMsg().getId());  
253 - } else {  
254 - context.parent().tell(responsePluginMsg, ActorRef.noSender());  
255 - logger.debug("[{}] Rpc command response sent to local plugin actor [{}]!", deviceId, requestMd.getMsg().getMsg().getId());  
256 - } 400 + systemContext.getDeviceRpcService().process(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), responseMsg.getData(), null));
257 } else { 401 } else {
258 logger.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId()); 402 logger.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
259 } 403 }
260 if (msg.getSessionType() == SessionType.SYNC) { 404 if (msg.getSessionType() == SessionType.SYNC) {
261 BasicCommandAckResponse response = success 405 BasicCommandAckResponse response = success
262 - ? BasicCommandAckResponse.onSuccess(MsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId())  
263 - : BasicCommandAckResponse.onError(MsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId(), new TimeoutException()); 406 + ? BasicCommandAckResponse.onSuccess(SessionMsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId())
  407 + : BasicCommandAckResponse.onError(SessionMsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId(), new TimeoutException());
264 sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(response, msg.getSessionId()), msg.getServerAddress()); 408 sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(response, msg.getSessionId()), msg.getServerAddress());
265 } 409 }
266 } 410 }
267 } 411 }
268 412
269 - public void processClusterEventMsg(ClusterEventMsg msg) { 413 + void processClusterEventMsg(ClusterEventMsg msg) {
270 if (!msg.isAdded()) { 414 if (!msg.isAdded()) {
271 logger.debug("[{}] Clearing attributes/rpc subscription for server [{}]", deviceId, msg.getServerAddress()); 415 logger.debug("[{}] Clearing attributes/rpc subscription for server [{}]", deviceId, msg.getServerAddress());
272 Predicate<Map.Entry<SessionId, SessionInfo>> filter = e -> e.getValue().getServer() 416 Predicate<Map.Entry<SessionId, SessionInfo>> filter = e -> e.getValue().getServer()
@@ -276,59 +420,27 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -276,59 +420,27 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
276 } 420 }
277 } 421 }
278 422
279 - private ToPluginRpcResponseDeviceMsg toPluginRpcResponseMsg(ToDeviceRpcRequestPluginMsg requestMsg, String data) {  
280 - return toPluginRpcResponseMsg(requestMsg, data, null);  
281 - }  
282 -  
283 - private ToPluginRpcResponseDeviceMsg toPluginRpcResponseMsg(ToDeviceRpcRequestPluginMsg requestMsg, RpcError error) {  
284 - return toPluginRpcResponseMsg(requestMsg, null, error);  
285 - }  
286 -  
287 - private ToPluginRpcResponseDeviceMsg toPluginRpcResponseMsg(ToDeviceRpcRequestPluginMsg requestMsg, String data, RpcError error) {  
288 - return new ToPluginRpcResponseDeviceMsg(  
289 - requestMsg.getPluginId(),  
290 - requestMsg.getPluginTenantId(),  
291 - new FromDeviceRpcResponse(requestMsg.getMsg().getId(),  
292 - data,  
293 - error  
294 - )  
295 - );  
296 - }  
297 -  
298 -// void onRulesProcessedMsg(ActorContext context, RulesProcessedMsg msg) {  
299 -// ChainProcessingContext ctx = msg.getCtx();  
300 -// ToDeviceActorMsg inMsg = ctx.getInMsg();  
301 -// SessionId sid = inMsg.getSessionId();  
302 -// ToDeviceSessionActorMsg response;  
303 -// if (ctx.getResponse() != null) {  
304 -// response = new BasicToDeviceSessionActorMsg(ctx.getResponse(), sid);  
305 -// } else {  
306 -// response = new BasicToDeviceSessionActorMsg(ctx.getError(), sid);  
307 -// }  
308 -// sendMsgToSessionActor(response, inMsg.getServerAddress());  
309 -// }  
310 -  
311 - private void processSubscriptionCommands(ActorContext context, ToDeviceActorMsg msg) { 423 + private void processSubscriptionCommands(ActorContext context, DeviceToDeviceActorMsg msg) {
312 SessionId sessionId = msg.getSessionId(); 424 SessionId sessionId = msg.getSessionId();
313 SessionType sessionType = msg.getSessionType(); 425 SessionType sessionType = msg.getSessionType();
314 FromDeviceMsg inMsg = msg.getPayload(); 426 FromDeviceMsg inMsg = msg.getPayload();
315 - if (inMsg.getMsgType() == MsgType.SUBSCRIBE_ATTRIBUTES_REQUEST) { 427 + if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_ATTRIBUTES_REQUEST) {
316 logger.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId); 428 logger.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId);
317 attributeSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress())); 429 attributeSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress()));
318 - } else if (inMsg.getMsgType() == MsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST) { 430 + } else if (inMsg.getMsgType() == SessionMsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST) {
319 logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId); 431 logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId);
320 attributeSubscriptions.remove(sessionId); 432 attributeSubscriptions.remove(sessionId);
321 - } else if (inMsg.getMsgType() == MsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST) { 433 + } else if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST) {
322 logger.debug("[{}] Registering rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType); 434 logger.debug("[{}] Registering rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType);
323 rpcSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress())); 435 rpcSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress()));
324 sendPendingRequests(context, sessionId, sessionType, msg.getServerAddress()); 436 sendPendingRequests(context, sessionId, sessionType, msg.getServerAddress());
325 - } else if (inMsg.getMsgType() == MsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST) { 437 + } else if (inMsg.getMsgType() == SessionMsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST) {
326 logger.debug("[{}] Canceling rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType); 438 logger.debug("[{}] Canceling rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType);
327 rpcSubscriptions.remove(sessionId); 439 rpcSubscriptions.remove(sessionId);
328 } 440 }
329 } 441 }
330 442
331 - private void processSessionStateMsgs(ToDeviceActorMsg msg) { 443 + private void processSessionStateMsgs(DeviceToDeviceActorMsg msg) {
332 SessionId sessionId = msg.getSessionId(); 444 SessionId sessionId = msg.getSessionId();
333 FromDeviceMsg inMsg = msg.getPayload(); 445 FromDeviceMsg inMsg = msg.getPayload();
334 if (inMsg instanceof SessionOpenMsg) { 446 if (inMsg instanceof SessionOpenMsg) {
@@ -352,17 +464,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -352,17 +464,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
352 } 464 }
353 } 465 }
354 466
355 - private List<AttributeKvEntry> fetchAttributes(String scope) {  
356 - try {  
357 - //TODO: replace this with async operation. Happens only during actor creation, but is still criticla for performance,  
358 - return systemContext.getAttributesService().findAll(this.deviceId, scope).get();  
359 - } catch (InterruptedException | ExecutionException e) {  
360 - logger.warning("[{}] Failed to fetch attributes for scope: {}", deviceId, scope);  
361 - throw new RuntimeException(e);  
362 - }  
363 - }  
364 -  
365 - public void processCredentialsUpdate() { 467 + void processCredentialsUpdate() {
366 sessions.forEach((k, v) -> { 468 sessions.forEach((k, v) -> {
367 sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(new SessionCloseNotification(), k), v.getServer()); 469 sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(new SessionCloseNotification(), k), v.getServer());
368 }); 470 });
@@ -370,8 +472,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso @@ -370,8 +472,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
370 rpcSubscriptions.clear(); 472 rpcSubscriptions.clear();
371 } 473 }
372 474
373 - public void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) { 475 + void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) {
374 this.deviceName = msg.getDeviceName(); 476 this.deviceName = msg.getDeviceName();
375 this.deviceType = msg.getDeviceType(); 477 this.deviceType = msg.getDeviceType();
  478 + this.defaultMetaData = new TbMsgMetaData();
  479 + this.defaultMetaData.putValue("deviceName", deviceName);
  480 + this.defaultMetaData.putValue("deviceType", deviceType);
376 } 481 }
  482 +
377 } 483 }
application/src/main/java/org/thingsboard/server/actors/device/DeviceActorToRuleEngineMsg.java renamed from application/src/test/java/org/thingsboard/server/controller/sql/PluginControllerSqlTest.java
@@ -13,14 +13,26 @@ @@ -13,14 +13,26 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.controller.sql; 16 +package org.thingsboard.server.actors.device;
17 17
18 -import org.thingsboard.server.controller.BasePluginControllerTest;  
19 -import org.thingsboard.server.dao.service.DaoSqlTest; 18 +import akka.actor.ActorRef;
  19 +import lombok.Data;
  20 +import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.msg.MsgType;
  22 +import org.thingsboard.server.common.msg.TbActorMsg;
  23 +import org.thingsboard.server.common.msg.TbMsg;
20 24
21 /** 25 /**
22 - * Created by Valerii Sosliuk on 6/28/2017. 26 + * Created by ashvayka on 15.03.18.
23 */ 27 */
24 -@DaoSqlTest  
25 -public class PluginControllerSqlTest extends BasePluginControllerTest { 28 +@Data
  29 +public final class DeviceActorToRuleEngineMsg implements TbActorMsg {
  30 +
  31 + private final ActorRef callbackRef;
  32 + private final TbMsg tbMsg;
  33 +
  34 + @Override
  35 + public MsgType getMsgType() {
  36 + return MsgType.DEVICE_ACTOR_TO_RULE_ENGINE_MSG;
  37 + }
26 } 38 }
application/src/main/java/org/thingsboard/server/actors/device/PendingSessionMsgData.java renamed from extensions-core/src/main/java/org/thingsboard/server/extensions/core/plugin/rpc/RpcPluginConfiguration.java
@@ -13,14 +13,24 @@ @@ -13,14 +13,24 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.extensions.core.plugin.rpc; 16 +package org.thingsboard.server.actors.device;
17 17
18 import lombok.Data; 18 import lombok.Data;
  19 +import org.thingsboard.server.common.data.id.SessionId;
  20 +import org.thingsboard.server.common.msg.cluster.ServerAddress;
  21 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  22 +
  23 +import java.util.Optional;
19 24
20 /** 25 /**
21 - * @author Andrew Shvayka 26 + * Created by ashvayka on 17.04.18.
22 */ 27 */
23 @Data 28 @Data
24 -public class RpcPluginConfiguration {  
25 - private long defaultTimeout; 29 +public final class PendingSessionMsgData {
  30 +
  31 + private final SessionId sessionId;
  32 + private final Optional<ServerAddress> serverAddress;
  33 + private final SessionMsgType sessionMsgType;
  34 + private final int requestId;
  35 +
26 } 36 }
application/src/main/java/org/thingsboard/server/actors/device/RuleEngineQueuePutAckMsg.java renamed from application/src/test/java/org/thingsboard/server/controller/nosql/PluginControllerNoSqlTest.java
@@ -13,14 +13,24 @@ @@ -13,14 +13,24 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.controller.nosql; 16 +package org.thingsboard.server.actors.device;
17 17
18 -import org.thingsboard.server.controller.BasePluginControllerTest;  
19 -import org.thingsboard.server.dao.service.DaoNoSqlTest; 18 +import lombok.Data;
  19 +import org.thingsboard.server.common.msg.MsgType;
  20 +import org.thingsboard.server.common.msg.TbActorMsg;
  21 +
  22 +import java.util.UUID;
20 23
21 /** 24 /**
22 - * Created by Valerii Sosliuk on 6/28/2017. 25 + * Created by ashvayka on 15.03.18.
23 */ 26 */
24 -@DaoNoSqlTest  
25 -public class PluginControllerNoSqlTest extends BasePluginControllerTest { 27 +@Data
  28 +public final class RuleEngineQueuePutAckMsg implements TbActorMsg {
  29 +
  30 + private final UUID id;
  31 +
  32 + @Override
  33 + public MsgType getMsgType() {
  34 + return MsgType.RULE_ENGINE_QUEUE_PUT_ACK_MSG;
  35 + }
26 } 36 }
@@ -16,13 +16,13 @@ @@ -16,13 +16,13 @@
16 package org.thingsboard.server.actors.device; 16 package org.thingsboard.server.actors.device;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg; 19 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
20 20
21 /** 21 /**
22 * @author Andrew Shvayka 22 * @author Andrew Shvayka
23 */ 23 */
24 @Data 24 @Data
25 public class ToDeviceRpcRequestMetadata { 25 public class ToDeviceRpcRequestMetadata {
26 - private final ToDeviceRpcRequestPluginMsg msg; 26 + private final ToDeviceRpcRequestMsg msg;
27 private final boolean sent; 27 private final boolean sent;
28 } 28 }
@@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.id.TenantId;
26 import org.thingsboard.server.common.msg.TbActorMsg; 26 import org.thingsboard.server.common.msg.TbActorMsg;
27 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; 27 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
28 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 28 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
29 -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; 29 +import org.thingsboard.server.common.msg.timeout.TimeoutMsg;
30 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg; 30 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg;
31 import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg; 31 import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg;
32 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; 32 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
@@ -153,6 +153,7 @@ public class PluginActor extends ComponentActor<PluginId, PluginActorMessageProc @@ -153,6 +153,7 @@ public class PluginActor extends ComponentActor<PluginId, PluginActorMessageProc
153 153
154 @Override 154 @Override
155 protected long getErrorPersistFrequency() { 155 protected long getErrorPersistFrequency() {
156 - return systemContext.getPluginErrorPersistFrequency(); 156 + return 0;
  157 +// return systemContext.getPluginErrorPersistFrequency();
157 } 158 }
158 } 159 }
@@ -30,13 +30,14 @@ import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; @@ -30,13 +30,14 @@ import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
30 import org.thingsboard.server.common.msg.cluster.ServerAddress; 30 import org.thingsboard.server.common.msg.cluster.ServerAddress;
31 import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse; 31 import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse;
32 import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg; 32 import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg;
33 -import org.thingsboard.server.common.msg.session.MsgType; 33 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  34 +import org.thingsboard.server.common.msg.session.SessionMsgType;
34 import org.thingsboard.server.extensions.api.plugins.Plugin; 35 import org.thingsboard.server.extensions.api.plugins.Plugin;
35 import org.thingsboard.server.extensions.api.plugins.PluginInitializationException; 36 import org.thingsboard.server.extensions.api.plugins.PluginInitializationException;
36 import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse; 37 import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse;
37 import org.thingsboard.server.extensions.api.plugins.msg.ResponsePluginToRuleMsg; 38 import org.thingsboard.server.extensions.api.plugins.msg.ResponsePluginToRuleMsg;
38 import org.thingsboard.server.extensions.api.plugins.msg.RuleToPluginMsg; 39 import org.thingsboard.server.extensions.api.plugins.msg.RuleToPluginMsg;
39 -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg; 40 +import org.thingsboard.server.common.msg.timeout.TimeoutMsg;
40 import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg; 41 import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg;
41 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; 42 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
42 import org.thingsboard.server.extensions.api.plugins.ws.msg.PluginWebsocketMsg; 43 import org.thingsboard.server.extensions.api.plugins.ws.msg.PluginWebsocketMsg;
@@ -108,7 +109,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> @@ -108,7 +109,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId>
108 } catch (Exception ex) { 109 } catch (Exception ex) {
109 logger.debug("[{}] Failed to process RuleToPlugin msg: [{}] [{}]", tenantId, msg.getMsg(), ex); 110 logger.debug("[{}] Failed to process RuleToPlugin msg: [{}] [{}]", tenantId, msg.getMsg(), ex);
110 RuleToPluginMsg ruleMsg = msg.getMsg(); 111 RuleToPluginMsg ruleMsg = msg.getMsg();
111 - MsgType responceMsgType = MsgType.RULE_ENGINE_ERROR; 112 + SessionMsgType responceMsgType = SessionMsgType.RULE_ENGINE_ERROR;
112 Integer requestId = 0; 113 Integer requestId = 0;
113 if (ruleMsg.getPayload() instanceof FromDeviceRequestMsg) { 114 if (ruleMsg.getPayload() instanceof FromDeviceRequestMsg) {
114 requestId = ((FromDeviceRequestMsg) ruleMsg.getPayload()).getRequestId(); 115 requestId = ((FromDeviceRequestMsg) ruleMsg.getPayload()).getRequestId();
@@ -216,7 +217,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId> @@ -216,7 +217,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId>
216 @Override 217 @Override
217 public void onStop(ActorContext context) { 218 public void onStop(ActorContext context) {
218 onStop(); 219 onStop();
219 - scheduleMsgWithDelay(context, new PluginTerminationMsg(entityId), systemContext.getPluginActorTerminationDelay()); 220 +// scheduleMsgWithDelay(context, new PluginTerminationMsg(entityId), systemContext.getPluginActorTerminationDelay());
220 } 221 }
221 222
222 private void onStop() { 223 private void onStop() {
@@ -36,9 +36,12 @@ import org.thingsboard.server.common.data.page.TextPageLink; @@ -36,9 +36,12 @@ import org.thingsboard.server.common.data.page.TextPageLink;
36 import org.thingsboard.server.common.data.plugin.PluginMetaData; 36 import org.thingsboard.server.common.data.plugin.PluginMetaData;
37 import org.thingsboard.server.common.data.relation.EntityRelation; 37 import org.thingsboard.server.common.data.relation.EntityRelation;
38 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 38 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
  39 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
39 import org.thingsboard.server.common.data.rule.RuleChain; 40 import org.thingsboard.server.common.data.rule.RuleChain;
40 import org.thingsboard.server.common.data.rule.RuleMetaData; 41 import org.thingsboard.server.common.data.rule.RuleMetaData;
41 import org.thingsboard.server.common.msg.cluster.ServerAddress; 42 import org.thingsboard.server.common.msg.cluster.ServerAddress;
  43 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
  44 +import org.thingsboard.server.common.msg.timeout.TimeoutMsg;
42 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; 45 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
43 import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext; 46 import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext;
44 import org.thingsboard.server.extensions.api.plugins.PluginCallback; 47 import org.thingsboard.server.extensions.api.plugins.PluginCallback;
@@ -348,7 +351,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -348,7 +351,7 @@ public final class PluginProcessingContext implements PluginContext {
348 throw new IllegalStateException("Not Implemented!"); 351 throw new IllegalStateException("Not Implemented!");
349 } 352 }
350 } else { 353 } else {
351 - callback.onSuccess(this, ValidationResult.ok()); 354 + callback.onSuccess(this, ValidationResult.ok(null));
352 } 355 }
353 } 356 }
354 357
@@ -366,7 +369,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -366,7 +369,7 @@ public final class PluginProcessingContext implements PluginContext {
366 } else if (ctx.isCustomerUser() && !device.getCustomerId().equals(ctx.getCustomerId())) { 369 } else if (ctx.isCustomerUser() && !device.getCustomerId().equals(ctx.getCustomerId())) {
367 return ValidationResult.accessDenied("Device doesn't belong to the current Customer!"); 370 return ValidationResult.accessDenied("Device doesn't belong to the current Customer!");
368 } else { 371 } else {
369 - return ValidationResult.ok(); 372 + return ValidationResult.ok(null);
370 } 373 }
371 } 374 }
372 })); 375 }));
@@ -387,7 +390,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -387,7 +390,7 @@ public final class PluginProcessingContext implements PluginContext {
387 } else if (ctx.isCustomerUser() && !asset.getCustomerId().equals(ctx.getCustomerId())) { 390 } else if (ctx.isCustomerUser() && !asset.getCustomerId().equals(ctx.getCustomerId())) {
388 return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!"); 391 return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!");
389 } else { 392 } else {
390 - return ValidationResult.ok(); 393 + return ValidationResult.ok(null);
391 } 394 }
392 } 395 }
393 })); 396 }));
@@ -408,7 +411,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -408,7 +411,7 @@ public final class PluginProcessingContext implements PluginContext {
408 } else if (ctx.isSystemAdmin() && !rule.getTenantId().isNullUid()) { 411 } else if (ctx.isSystemAdmin() && !rule.getTenantId().isNullUid()) {
409 return ValidationResult.accessDenied("Rule is not in system scope!"); 412 return ValidationResult.accessDenied("Rule is not in system scope!");
410 } else { 413 } else {
411 - return ValidationResult.ok(); 414 + return ValidationResult.ok(null);
412 } 415 }
413 } 416 }
414 })); 417 }));
@@ -429,7 +432,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -429,7 +432,7 @@ public final class PluginProcessingContext implements PluginContext {
429 } else if (ctx.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) { 432 } else if (ctx.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) {
430 return ValidationResult.accessDenied("Rule chain is not in system scope!"); 433 return ValidationResult.accessDenied("Rule chain is not in system scope!");
431 } else { 434 } else {
432 - return ValidationResult.ok(); 435 + return ValidationResult.ok(null);
433 } 436 }
434 } 437 }
435 })); 438 }));
@@ -451,7 +454,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -451,7 +454,7 @@ public final class PluginProcessingContext implements PluginContext {
451 } else if (ctx.isSystemAdmin() && !plugin.getTenantId().isNullUid()) { 454 } else if (ctx.isSystemAdmin() && !plugin.getTenantId().isNullUid()) {
452 return ValidationResult.accessDenied("Plugin is not in system scope!"); 455 return ValidationResult.accessDenied("Plugin is not in system scope!");
453 } else { 456 } else {
454 - return ValidationResult.ok(); 457 + return ValidationResult.ok(null);
455 } 458 }
456 } 459 }
457 })); 460 }));
@@ -472,7 +475,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -472,7 +475,7 @@ public final class PluginProcessingContext implements PluginContext {
472 } else if (ctx.isCustomerUser() && !customer.getId().equals(ctx.getCustomerId())) { 475 } else if (ctx.isCustomerUser() && !customer.getId().equals(ctx.getCustomerId())) {
473 return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!"); 476 return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!");
474 } else { 477 } else {
475 - return ValidationResult.ok(); 478 + return ValidationResult.ok(null);
476 } 479 }
477 } 480 }
478 })); 481 }));
@@ -483,7 +486,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -483,7 +486,7 @@ public final class PluginProcessingContext implements PluginContext {
483 if (ctx.isCustomerUser()) { 486 if (ctx.isCustomerUser()) {
484 callback.onSuccess(this, ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); 487 callback.onSuccess(this, ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
485 } else if (ctx.isSystemAdmin()) { 488 } else if (ctx.isSystemAdmin()) {
486 - callback.onSuccess(this, ValidationResult.ok()); 489 + callback.onSuccess(this, ValidationResult.ok(null));
487 } else { 490 } else {
488 ListenableFuture<Tenant> tenantFuture = pluginCtx.tenantService.findTenantByIdAsync(new TenantId(entityId.getId())); 491 ListenableFuture<Tenant> tenantFuture = pluginCtx.tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
489 Futures.addCallback(tenantFuture, getCallback(callback, tenant -> { 492 Futures.addCallback(tenantFuture, getCallback(callback, tenant -> {
@@ -492,7 +495,7 @@ public final class PluginProcessingContext implements PluginContext { @@ -492,7 +495,7 @@ public final class PluginProcessingContext implements PluginContext {
492 } else if (!tenant.getId().equals(ctx.getTenantId())) { 495 } else if (!tenant.getId().equals(ctx.getTenantId())) {
493 return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!"); 496 return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!");
494 } else { 497 } else {
495 - return ValidationResult.ok(); 498 + return ValidationResult.ok(null);
496 } 499 }
497 })); 500 }));
498 } 501 }
@@ -18,13 +18,13 @@ package org.thingsboard.server.actors.plugin; @@ -18,13 +18,13 @@ package org.thingsboard.server.actors.plugin;
18 import akka.actor.ActorRef; 18 import akka.actor.ActorRef;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 import org.thingsboard.server.actors.ActorSystemContext; 20 import org.thingsboard.server.actors.ActorSystemContext;
21 -import org.thingsboard.server.common.data.Device;  
22 import org.thingsboard.server.common.data.id.DeviceId; 21 import org.thingsboard.server.common.data.id.DeviceId;
23 -import org.thingsboard.server.common.data.id.EntityId; 22 +import org.thingsboard.server.common.data.id.PluginId;
24 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
25 import org.thingsboard.server.common.msg.cluster.ServerAddress; 24 import org.thingsboard.server.common.msg.cluster.ServerAddress;
  25 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
  26 +import org.thingsboard.server.common.msg.timeout.TimeoutMsg;
26 import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint; 27 import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
27 -import org.thingsboard.server.common.data.id.PluginId;  
28 import org.thingsboard.server.dao.asset.AssetService; 28 import org.thingsboard.server.dao.asset.AssetService;
29 import org.thingsboard.server.dao.attributes.AttributesService; 29 import org.thingsboard.server.dao.attributes.AttributesService;
30 import org.thingsboard.server.dao.audit.AuditLogService; 30 import org.thingsboard.server.dao.audit.AuditLogService;
@@ -37,9 +37,6 @@ import org.thingsboard.server.dao.rule.RuleService; @@ -37,9 +37,6 @@ import org.thingsboard.server.dao.rule.RuleService;
37 import org.thingsboard.server.dao.tenant.TenantService; 37 import org.thingsboard.server.dao.tenant.TenantService;
38 import org.thingsboard.server.dao.timeseries.TimeseriesService; 38 import org.thingsboard.server.dao.timeseries.TimeseriesService;
39 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg; 39 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
40 -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg;  
41 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest;  
42 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg;  
43 import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; 40 import org.thingsboard.server.service.cluster.routing.ClusterRoutingService;
44 import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; 41 import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;
45 import scala.concurrent.duration.Duration; 42 import scala.concurrent.duration.Duration;
@@ -108,8 +105,8 @@ public final class SharedPluginProcessingContext { @@ -108,8 +105,8 @@ public final class SharedPluginProcessingContext {
108 105
109 public void sendRpcRequest(ToDeviceRpcRequest msg) { 106 public void sendRpcRequest(ToDeviceRpcRequest msg) {
110 log.trace("[{}] Forwarding msg {} to device actor!", pluginId, msg); 107 log.trace("[{}] Forwarding msg {} to device actor!", pluginId, msg);
111 - ToDeviceRpcRequestPluginMsg rpcMsg = new ToDeviceRpcRequestPluginMsg(pluginId, tenantId, msg);  
112 - forward(msg.getDeviceId(), rpcMsg, rpcService::tell); 108 +// ToDeviceRpcRequestPluginMsg rpcMsg = new ToDeviceRpcRequestPluginMsg(pluginId, tenantId, msg);
  109 +// forward(msg.getDeviceId(), rpcMsg, rpcService::tell);
113 } 110 }
114 111
115 private <T> void forward(DeviceId deviceId, T msg, BiConsumer<ServerAddress, T> rpcFunction) { 112 private <T> void forward(DeviceId deviceId, T msg, BiConsumer<ServerAddress, T> rpcFunction) {
@@ -20,29 +20,30 @@ import lombok.Data; @@ -20,29 +20,30 @@ import lombok.Data;
20 20
21 @Data 21 @Data
22 @AllArgsConstructor 22 @AllArgsConstructor
23 -public class ValidationResult { 23 +public class ValidationResult<V> {
24 24
25 private final ValidationResultCode resultCode; 25 private final ValidationResultCode resultCode;
26 private final String message; 26 private final String message;
  27 + private final V v;
27 28
28 - public static ValidationResult ok() {  
29 - return new ValidationResult(ValidationResultCode.OK, "Ok"); 29 + public static <V> ValidationResult<V> ok(V v) {
  30 + return new ValidationResult<>(ValidationResultCode.OK, "Ok", v);
30 } 31 }
31 32
32 - public static ValidationResult accessDenied(String message) {  
33 - return new ValidationResult(ValidationResultCode.ACCESS_DENIED, message); 33 + public static <V> ValidationResult<V> accessDenied(String message) {
  34 + return new ValidationResult<>(ValidationResultCode.ACCESS_DENIED, message, null);
34 } 35 }
35 36
36 - public static ValidationResult entityNotFound(String message) {  
37 - return new ValidationResult(ValidationResultCode.ENTITY_NOT_FOUND, message); 37 + public static <V> ValidationResult<V> entityNotFound(String message) {
  38 + return new ValidationResult<>(ValidationResultCode.ENTITY_NOT_FOUND, message, null);
38 } 39 }
39 40
40 - public static ValidationResult unauthorized(String message) {  
41 - return new ValidationResult(ValidationResultCode.UNAUTHORIZED, message); 41 + public static <V> ValidationResult<V> unauthorized(String message) {
  42 + return new ValidationResult<>(ValidationResultCode.UNAUTHORIZED, message, null);
42 } 43 }
43 44
44 - public static ValidationResult internalError(String message) {  
45 - return new ValidationResult(ValidationResultCode.INTERNAL_ERROR, message); 45 + public static <V> ValidationResult<V> internalError(String message) {
  46 + return new ValidationResult<>(ValidationResultCode.INTERNAL_ERROR, message, null);
46 } 47 }
47 48
48 } 49 }
@@ -24,10 +24,12 @@ import org.thingsboard.server.actors.service.ActorService; @@ -24,10 +24,12 @@ import org.thingsboard.server.actors.service.ActorService;
24 import org.thingsboard.server.common.data.id.DeviceId; 24 import org.thingsboard.server.common.data.id.DeviceId;
25 import org.thingsboard.server.common.data.id.PluginId; 25 import org.thingsboard.server.common.data.id.PluginId;
26 import org.thingsboard.server.common.data.id.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
27 import org.thingsboard.server.common.msg.cluster.ServerAddress; 28 import org.thingsboard.server.common.msg.cluster.ServerAddress;
28 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; 29 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
29 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; 30 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
30 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 31 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
  32 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
31 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 33 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
32 import org.thingsboard.server.extensions.api.plugins.msg.*; 34 import org.thingsboard.server.extensions.api.plugins.msg.*;
33 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; 35 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
@@ -35,6 +37,7 @@ import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg; @@ -35,6 +37,7 @@ import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg;
35 import org.thingsboard.server.gen.cluster.ClusterAPIProtos; 37 import org.thingsboard.server.gen.cluster.ClusterAPIProtos;
36 import org.thingsboard.server.service.cluster.rpc.GrpcSession; 38 import org.thingsboard.server.service.cluster.rpc.GrpcSession;
37 import org.thingsboard.server.service.cluster.rpc.GrpcSessionListener; 39 import org.thingsboard.server.service.cluster.rpc.GrpcSessionListener;
  40 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
38 41
39 import java.io.Serializable; 42 import java.io.Serializable;
40 import java.util.UUID; 43 import java.util.UUID;
@@ -83,7 +86,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener { @@ -83,7 +86,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
83 @Override 86 @Override
84 public void onToDeviceActorRpcMsg(GrpcSession session, ClusterAPIProtos.ToDeviceActorRpcMessage msg) { 87 public void onToDeviceActorRpcMsg(GrpcSession session, ClusterAPIProtos.ToDeviceActorRpcMessage msg) {
85 log.trace("{} session [{}] received device actor msg {}", getType(session), session.getRemoteServer(), msg); 88 log.trace("{} session [{}] received device actor msg {}", getType(session), session.getRemoteServer(), msg);
86 - service.onMsg((ToDeviceActorMsg) deserialize(msg.getData().toByteArray())); 89 + service.onMsg((DeviceToDeviceActorMsg) deserialize(msg.getData().toByteArray()));
87 } 90 }
88 91
89 @Override 92 @Override
@@ -139,28 +142,20 @@ public class BasicRpcSessionListener implements GrpcSessionListener { @@ -139,28 +142,20 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
139 return new UUID(uid.getPluginUuidMsb(), uid.getPluginUuidLsb()); 142 return new UUID(uid.getPluginUuidMsb(), uid.getPluginUuidLsb());
140 } 143 }
141 144
142 - private static ToDeviceRpcRequestPluginMsg deserialize(ServerAddress serverAddress, ClusterAPIProtos.ToDeviceRpcRequestRpcMessage msg) {  
143 - ClusterAPIProtos.PluginAddress address = msg.getAddress();  
144 - TenantId pluginTenantId = new TenantId(toUUID(address.getTenantId()));  
145 - PluginId pluginId = new PluginId(toUUID(address.getPluginId()));  
146 - 145 + private static ToDeviceRpcRequestMsg deserialize(ServerAddress serverAddress, ClusterAPIProtos.ToDeviceRpcRequestRpcMessage msg) {
147 TenantId deviceTenantId = new TenantId(toUUID(msg.getDeviceTenantId())); 146 TenantId deviceTenantId = new TenantId(toUUID(msg.getDeviceTenantId()));
148 DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId())); 147 DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId()));
149 148
150 ToDeviceRpcRequestBody requestBody = new ToDeviceRpcRequestBody(msg.getMethod(), msg.getParams()); 149 ToDeviceRpcRequestBody requestBody = new ToDeviceRpcRequestBody(msg.getMethod(), msg.getParams());
151 - ToDeviceRpcRequest request = new ToDeviceRpcRequest(toUUID(msg.getMsgId()), null, deviceTenantId, deviceId, msg.getOneway(), msg.getExpTime(), requestBody); 150 + ToDeviceRpcRequest request = new ToDeviceRpcRequest(toUUID(msg.getMsgId()), deviceTenantId, deviceId, msg.getOneway(), msg.getExpTime(), requestBody);
152 151
153 - return new ToDeviceRpcRequestPluginMsg(serverAddress, pluginId, pluginTenantId, request); 152 + return new ToDeviceRpcRequestMsg(serverAddress, request);
154 } 153 }
155 154
156 private static ToPluginRpcResponseDeviceMsg deserialize(ServerAddress serverAddress, ClusterAPIProtos.ToPluginRpcResponseRpcMessage msg) { 155 private static ToPluginRpcResponseDeviceMsg deserialize(ServerAddress serverAddress, ClusterAPIProtos.ToPluginRpcResponseRpcMessage msg) {
157 - ClusterAPIProtos.PluginAddress address = msg.getAddress();  
158 - TenantId pluginTenantId = new TenantId(toUUID(address.getTenantId()));  
159 - PluginId pluginId = new PluginId(toUUID(address.getPluginId()));  
160 -  
161 RpcError error = !StringUtils.isEmpty(msg.getError()) ? RpcError.valueOf(msg.getError()) : null; 156 RpcError error = !StringUtils.isEmpty(msg.getError()) ? RpcError.valueOf(msg.getError()) : null;
162 FromDeviceRpcResponse response = new FromDeviceRpcResponse(toUUID(msg.getMsgId()), msg.getResponse(), error); 157 FromDeviceRpcResponse response = new FromDeviceRpcResponse(toUUID(msg.getMsgId()), msg.getResponse(), error);
163 - return new ToPluginRpcResponseDeviceMsg(pluginId, pluginTenantId, response); 158 + return new ToPluginRpcResponseDeviceMsg(null, null, response);
164 } 159 }
165 160
166 @SuppressWarnings("unchecked") 161 @SuppressWarnings("unchecked")
@@ -18,6 +18,7 @@ package org.thingsboard.server.actors.ruleChain; @@ -18,6 +18,7 @@ package org.thingsboard.server.actors.ruleChain;
18 import akka.actor.OneForOneStrategy; 18 import akka.actor.OneForOneStrategy;
19 import akka.actor.SupervisorStrategy; 19 import akka.actor.SupervisorStrategy;
20 import org.thingsboard.server.actors.ActorSystemContext; 20 import org.thingsboard.server.actors.ActorSystemContext;
  21 +import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg;
21 import org.thingsboard.server.actors.service.ComponentActor; 22 import org.thingsboard.server.actors.service.ComponentActor;
22 import org.thingsboard.server.actors.service.ContextBasedCreator; 23 import org.thingsboard.server.actors.service.ContextBasedCreator;
23 import org.thingsboard.server.common.data.id.RuleChainId; 24 import org.thingsboard.server.common.data.id.RuleChainId;
@@ -44,6 +45,9 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe @@ -44,6 +45,9 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe
44 case SERVICE_TO_RULE_ENGINE_MSG: 45 case SERVICE_TO_RULE_ENGINE_MSG:
45 processor.onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); 46 processor.onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg);
46 break; 47 break;
  48 + case DEVICE_ACTOR_TO_RULE_ENGINE_MSG:
  49 + processor.onDeviceActorToRuleEngineMsg((DeviceActorToRuleEngineMsg) msg);
  50 + break;
47 case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG: 51 case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG:
48 processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg); 52 processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg);
49 break; 53 break;
@@ -20,6 +20,8 @@ import akka.actor.ActorRef; @@ -20,6 +20,8 @@ import akka.actor.ActorRef;
20 import akka.actor.Props; 20 import akka.actor.Props;
21 import akka.event.LoggingAdapter; 21 import akka.event.LoggingAdapter;
22 import org.thingsboard.server.actors.ActorSystemContext; 22 import org.thingsboard.server.actors.ActorSystemContext;
  23 +import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg;
  24 +import org.thingsboard.server.actors.device.RuleEngineQueuePutAckMsg;
23 import org.thingsboard.server.actors.service.DefaultActorService; 25 import org.thingsboard.server.actors.service.DefaultActorService;
24 import org.thingsboard.server.actors.shared.ComponentMsgProcessor; 26 import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
25 import org.thingsboard.server.common.data.EntityType; 27 import org.thingsboard.server.common.data.EntityType;
@@ -58,6 +60,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -58,6 +60,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
58 60
59 private RuleNodeId firstId; 61 private RuleNodeId firstId;
60 private RuleNodeCtx firstNode; 62 private RuleNodeCtx firstNode;
  63 + private boolean started;
61 64
62 RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext 65 RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext
63 , LoggingAdapter logger, ActorRef parent, ActorRef self) { 66 , LoggingAdapter logger, ActorRef parent, ActorRef self) {
@@ -71,14 +74,19 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -71,14 +74,19 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
71 74
72 @Override 75 @Override
73 public void start(ActorContext context) throws Exception { 76 public void start(ActorContext context) throws Exception {
74 - RuleChain ruleChain = service.findRuleChainById(entityId);  
75 - List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId);  
76 - // Creating and starting the actors;  
77 - for (RuleNode ruleNode : ruleNodeList) {  
78 - ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode);  
79 - nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode)); 77 + if (!started) {
  78 + RuleChain ruleChain = service.findRuleChainById(entityId);
  79 + List<RuleNode> ruleNodeList = service.getRuleChainNodes(entityId);
  80 + // Creating and starting the actors;
  81 + for (RuleNode ruleNode : ruleNodeList) {
  82 + ActorRef ruleNodeActor = createRuleNodeActor(context, ruleNode);
  83 + nodeActors.put(ruleNode.getId(), new RuleNodeCtx(tenantId, self, ruleNodeActor, ruleNode));
  84 + }
  85 + initRoutes(ruleChain, ruleNodeList);
  86 + started = true;
  87 + } else {
  88 + onUpdate(context);
80 } 89 }
81 - initRoutes(ruleChain, ruleNodeList);  
82 } 90 }
83 91
84 @Override 92 @Override
@@ -113,6 +121,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -113,6 +121,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
113 nodeActors.clear(); 121 nodeActors.clear();
114 nodeRoutes.clear(); 122 nodeRoutes.clear();
115 context.stop(self); 123 context.stop(self);
  124 + started = false;
116 } 125 }
117 126
118 @Override 127 @Override
@@ -157,6 +166,14 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -157,6 +166,14 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
157 pushMsgToNode(firstNode, tbMsg); 166 pushMsgToNode(firstNode, tbMsg);
158 } 167 }
159 168
  169 + public void onDeviceActorToRuleEngineMsg(DeviceActorToRuleEngineMsg envelope) {
  170 + checkActive();
  171 + TbMsg tbMsg = envelope.getTbMsg();
  172 + //TODO: push to queue and act on ack in async way
  173 + pushMsgToNode(firstNode, tbMsg);
  174 + envelope.getCallbackRef().tell(new RuleEngineQueuePutAckMsg(tbMsg.getId()), self);
  175 + }
  176 +
160 void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) { 177 void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) {
161 checkActive(); 178 checkActive();
162 RuleNodeId originator = envelope.getOriginator(); 179 RuleNodeId originator = envelope.getOriginator();
@@ -191,5 +208,4 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -191,5 +208,4 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
191 nodeCtx.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self); 208 nodeCtx.getSelfActor().tell(new RuleChainToRuleNodeMsg(new DefaultTbContext(systemContext, nodeCtx), msg), self);
192 } 209 }
193 } 210 }
194 -  
195 } 211 }
@@ -31,31 +31,29 @@ import org.thingsboard.server.dao.rule.RuleChainService; @@ -31,31 +31,29 @@ import org.thingsboard.server.dao.rule.RuleChainService;
31 public abstract class RuleChainManagerActor extends ContextAwareActor { 31 public abstract class RuleChainManagerActor extends ContextAwareActor {
32 32
33 protected final RuleChainManager ruleChainManager; 33 protected final RuleChainManager ruleChainManager;
34 - protected final PluginManager pluginManager;  
35 protected final RuleChainService ruleChainService; 34 protected final RuleChainService ruleChainService;
36 35
37 public RuleChainManagerActor(ActorSystemContext systemContext, RuleChainManager ruleChainManager, PluginManager pluginManager) { 36 public RuleChainManagerActor(ActorSystemContext systemContext, RuleChainManager ruleChainManager, PluginManager pluginManager) {
38 super(systemContext); 37 super(systemContext);
39 this.ruleChainManager = ruleChainManager; 38 this.ruleChainManager = ruleChainManager;
40 - this.pluginManager = pluginManager;  
41 this.ruleChainService = systemContext.getRuleChainService(); 39 this.ruleChainService = systemContext.getRuleChainService();
42 } 40 }
43 41
44 protected void initRuleChains() { 42 protected void initRuleChains() {
45 - pluginManager.init(this.context());  
46 ruleChainManager.init(this.context()); 43 ruleChainManager.init(this.context());
47 } 44 }
48 45
49 protected ActorRef getEntityActorRef(EntityId entityId) { 46 protected ActorRef getEntityActorRef(EntityId entityId) {
50 ActorRef target = null; 47 ActorRef target = null;
51 switch (entityId.getEntityType()) { 48 switch (entityId.getEntityType()) {
52 - case PLUGIN:  
53 - target = pluginManager.getOrCreateActor(this.context(), (PluginId) entityId);  
54 - break;  
55 case RULE_CHAIN: 49 case RULE_CHAIN:
56 target = ruleChainManager.getOrCreateActor(this.context(), (RuleChainId) entityId); 50 target = ruleChainManager.getOrCreateActor(this.context(), (RuleChainId) entityId);
57 break; 51 break;
58 } 52 }
59 return target; 53 return target;
60 } 54 }
  55 +
  56 + protected void broadcast(Object msg) {
  57 + ruleChainManager.broadcast(msg);
  58 + }
61 } 59 }
@@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; @@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
39 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; 39 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
40 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; 40 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
41 import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg; 41 import org.thingsboard.server.extensions.api.device.DeviceNameOrTypeUpdateMsg;
42 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 42 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
43 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 43 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
44 import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg; 44 import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg;
45 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 45 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
@@ -156,7 +156,7 @@ public class DefaultActorService implements ActorService { @@ -156,7 +156,7 @@ public class DefaultActorService implements ActorService {
156 } 156 }
157 157
158 @Override 158 @Override
159 - public void onMsg(ToDeviceActorMsg msg) { 159 + public void onMsg(DeviceToDeviceActorMsg msg) {
160 log.trace("Processing device rpc msg: {}", msg); 160 log.trace("Processing device rpc msg: {}", msg);
161 appActor.tell(msg, ActorRef.noSender()); 161 appActor.tell(msg, ActorRef.noSender());
162 } 162 }
@@ -22,12 +22,11 @@ import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; @@ -22,12 +22,11 @@ import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
22 import org.thingsboard.server.common.msg.cluster.ServerAddress; 22 import org.thingsboard.server.common.msg.cluster.ServerAddress;
23 import org.thingsboard.server.common.msg.core.*; 23 import org.thingsboard.server.common.msg.core.*;
24 import org.thingsboard.server.common.msg.core.SessionCloseMsg; 24 import org.thingsboard.server.common.msg.core.SessionCloseMsg;
25 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 25 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
26 import org.thingsboard.server.common.msg.session.*; 26 import org.thingsboard.server.common.msg.session.*;
27 27
28 import akka.actor.ActorContext; 28 import akka.actor.ActorContext;
29 import akka.event.LoggingAdapter; 29 import akka.event.LoggingAdapter;
30 -import org.thingsboard.server.common.msg.session.ctrl.*;  
31 import org.thingsboard.server.common.msg.session.ex.SessionException; 30 import org.thingsboard.server.common.msg.session.ex.SessionException;
32 31
33 import java.util.HashMap; 32 import java.util.HashMap;
@@ -37,7 +36,7 @@ import java.util.Optional; @@ -37,7 +36,7 @@ import java.util.Optional;
37 class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor { 36 class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor {
38 37
39 private boolean firstMsg = true; 38 private boolean firstMsg = true;
40 - private Map<Integer, ToDeviceActorMsg> pendingMap = new HashMap<>(); 39 + private Map<Integer, DeviceToDeviceActorMsg> pendingMap = new HashMap<>();
41 private Optional<ServerAddress> currentTargetServer; 40 private Optional<ServerAddress> currentTargetServer;
42 private boolean subscribedToAttributeUpdates; 41 private boolean subscribedToAttributeUpdates;
43 private boolean subscribedToRpcCommands; 42 private boolean subscribedToRpcCommands;
@@ -53,7 +52,7 @@ class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor { @@ -53,7 +52,7 @@ class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor {
53 toDeviceMsg(new SessionOpenMsg()).ifPresent(m -> forwardToAppActor(ctx, m)); 52 toDeviceMsg(new SessionOpenMsg()).ifPresent(m -> forwardToAppActor(ctx, m));
54 firstMsg = false; 53 firstMsg = false;
55 } 54 }
56 - ToDeviceActorMsg pendingMsg = toDeviceMsg(msg); 55 + DeviceToDeviceActorMsg pendingMsg = toDeviceMsg(msg);
57 FromDeviceMsg fromDeviceMsg = pendingMsg.getPayload(); 56 FromDeviceMsg fromDeviceMsg = pendingMsg.getPayload();
58 switch (fromDeviceMsg.getMsgType()) { 57 switch (fromDeviceMsg.getMsgType()) {
59 case POST_TELEMETRY_REQUEST: 58 case POST_TELEMETRY_REQUEST:
@@ -86,8 +85,8 @@ class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor { @@ -86,8 +85,8 @@ class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor {
86 @Override 85 @Override
87 public void processToDeviceMsg(ActorContext context, ToDeviceMsg msg) { 86 public void processToDeviceMsg(ActorContext context, ToDeviceMsg msg) {
88 try { 87 try {
89 - if (msg.getMsgType() != MsgType.SESSION_CLOSE) {  
90 - switch (msg.getMsgType()) { 88 + if (msg.getSessionMsgType() != SessionMsgType.SESSION_CLOSE) {
  89 + switch (msg.getSessionMsgType()) {
91 case STATUS_CODE_RESPONSE: 90 case STATUS_CODE_RESPONSE:
92 case GET_ATTRIBUTES_RESPONSE: 91 case GET_ATTRIBUTES_RESPONSE:
93 ResponseMsg responseMsg = (ResponseMsg) msg; 92 ResponseMsg responseMsg = (ResponseMsg) msg;
@@ -22,8 +22,8 @@ import org.thingsboard.server.common.data.id.DeviceId; @@ -22,8 +22,8 @@ import org.thingsboard.server.common.data.id.DeviceId;
22 import org.thingsboard.server.common.data.id.SessionId; 22 import org.thingsboard.server.common.data.id.SessionId;
23 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; 23 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
24 import org.thingsboard.server.common.msg.cluster.ServerAddress; 24 import org.thingsboard.server.common.msg.cluster.ServerAddress;
25 -import org.thingsboard.server.common.msg.device.BasicToDeviceActorMsg;  
26 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 25 +import org.thingsboard.server.common.msg.device.BasicDeviceToDeviceActorMsg;
  26 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
27 import org.thingsboard.server.common.msg.session.*; 27 import org.thingsboard.server.common.msg.session.*;
28 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; 28 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
29 29
@@ -37,7 +37,7 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP @@ -37,7 +37,7 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
37 37
38 protected final SessionId sessionId; 38 protected final SessionId sessionId;
39 protected SessionContext sessionCtx; 39 protected SessionContext sessionCtx;
40 - protected ToDeviceActorMsg toDeviceActorMsgPrototype; 40 + protected DeviceToDeviceActorMsg deviceToDeviceActorMsgPrototype;
41 41
42 protected AbstractSessionActorMsgProcessor(ActorSystemContext ctx, LoggingAdapter logger, SessionId sessionId) { 42 protected AbstractSessionActorMsgProcessor(ActorSystemContext ctx, LoggingAdapter logger, SessionId sessionId) {
43 super(ctx, logger); 43 super(ctx, logger);
@@ -64,29 +64,29 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP @@ -64,29 +64,29 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
64 64
65 protected void updateSessionCtx(ToDeviceActorSessionMsg msg, SessionType type) { 65 protected void updateSessionCtx(ToDeviceActorSessionMsg msg, SessionType type) {
66 sessionCtx = msg.getSessionMsg().getSessionContext(); 66 sessionCtx = msg.getSessionMsg().getSessionContext();
67 - toDeviceActorMsgPrototype = new BasicToDeviceActorMsg(msg, type); 67 + deviceToDeviceActorMsgPrototype = new BasicDeviceToDeviceActorMsg(msg, type);
68 } 68 }
69 69
70 - protected ToDeviceActorMsg toDeviceMsg(ToDeviceActorSessionMsg msg) { 70 + protected DeviceToDeviceActorMsg toDeviceMsg(ToDeviceActorSessionMsg msg) {
71 AdaptorToSessionActorMsg adaptorMsg = msg.getSessionMsg(); 71 AdaptorToSessionActorMsg adaptorMsg = msg.getSessionMsg();
72 - return new BasicToDeviceActorMsg(toDeviceActorMsgPrototype, adaptorMsg.getMsg()); 72 + return new BasicDeviceToDeviceActorMsg(deviceToDeviceActorMsgPrototype, adaptorMsg.getMsg());
73 } 73 }
74 74
75 - protected Optional<ToDeviceActorMsg> toDeviceMsg(FromDeviceMsg msg) {  
76 - if (toDeviceActorMsgPrototype != null) {  
77 - return Optional.of(new BasicToDeviceActorMsg(toDeviceActorMsgPrototype, msg)); 75 + protected Optional<DeviceToDeviceActorMsg> toDeviceMsg(FromDeviceMsg msg) {
  76 + if (deviceToDeviceActorMsgPrototype != null) {
  77 + return Optional.of(new BasicDeviceToDeviceActorMsg(deviceToDeviceActorMsgPrototype, msg));
78 } else { 78 } else {
79 return Optional.empty(); 79 return Optional.empty();
80 } 80 }
81 } 81 }
82 82
83 - protected Optional<ServerAddress> forwardToAppActor(ActorContext ctx, ToDeviceActorMsg toForward) { 83 + protected Optional<ServerAddress> forwardToAppActor(ActorContext ctx, DeviceToDeviceActorMsg toForward) {
84 Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(toForward.getDeviceId()); 84 Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(toForward.getDeviceId());
85 forwardToAppActor(ctx, toForward, address); 85 forwardToAppActor(ctx, toForward, address);
86 return address; 86 return address;
87 } 87 }
88 88
89 - protected Optional<ServerAddress> forwardToAppActorIfAdressChanged(ActorContext ctx, ToDeviceActorMsg toForward, Optional<ServerAddress> oldAddress) { 89 + protected Optional<ServerAddress> forwardToAppActorIfAdressChanged(ActorContext ctx, DeviceToDeviceActorMsg toForward, Optional<ServerAddress> oldAddress) {
90 Optional<ServerAddress> newAddress = systemContext.getRoutingService().resolveById(toForward.getDeviceId()); 90 Optional<ServerAddress> newAddress = systemContext.getRoutingService().resolveById(toForward.getDeviceId());
91 if (!newAddress.equals(oldAddress)) { 91 if (!newAddress.equals(oldAddress)) {
92 if (newAddress.isPresent()) { 92 if (newAddress.isPresent()) {
@@ -99,7 +99,7 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP @@ -99,7 +99,7 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
99 return newAddress; 99 return newAddress;
100 } 100 }
101 101
102 - protected void forwardToAppActor(ActorContext ctx, ToDeviceActorMsg toForward, Optional<ServerAddress> address) { 102 + protected void forwardToAppActor(ActorContext ctx, DeviceToDeviceActorMsg toForward, Optional<ServerAddress> address) {
103 if (address.isPresent()) { 103 if (address.isPresent()) {
104 systemContext.getRpcService().tell(address.get(), 104 systemContext.getRpcService().tell(address.get(),
105 toForward.toOtherAddress(systemContext.getRoutingService().getCurrentServer())); 105 toForward.toOtherAddress(systemContext.getRoutingService().getCurrentServer()));
@@ -114,6 +114,6 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP @@ -114,6 +114,6 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
114 } 114 }
115 115
116 public DeviceId getDeviceId() { 116 public DeviceId getDeviceId() {
117 - return toDeviceActorMsgPrototype.getDeviceId(); 117 + return deviceToDeviceActorMsgPrototype.getDeviceId();
118 } 118 }
119 } 119 }
@@ -20,7 +20,7 @@ import org.thingsboard.server.actors.shared.SessionTimeoutMsg; @@ -20,7 +20,7 @@ import org.thingsboard.server.actors.shared.SessionTimeoutMsg;
20 import org.thingsboard.server.common.data.id.SessionId; 20 import org.thingsboard.server.common.data.id.SessionId;
21 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; 21 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
22 import org.thingsboard.server.common.msg.cluster.ServerAddress; 22 import org.thingsboard.server.common.msg.cluster.ServerAddress;
23 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 23 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
24 import org.thingsboard.server.common.msg.session.*; 24 import org.thingsboard.server.common.msg.session.*;
25 import org.thingsboard.server.common.msg.session.ToDeviceActorSessionMsg; 25 import org.thingsboard.server.common.msg.session.ToDeviceActorSessionMsg;
26 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg; 26 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
@@ -32,7 +32,7 @@ import akka.event.LoggingAdapter; @@ -32,7 +32,7 @@ import akka.event.LoggingAdapter;
32 import java.util.Optional; 32 import java.util.Optional;
33 33
34 class SyncMsgProcessor extends AbstractSessionActorMsgProcessor { 34 class SyncMsgProcessor extends AbstractSessionActorMsgProcessor {
35 - private ToDeviceActorMsg pendingMsg; 35 + private DeviceToDeviceActorMsg pendingMsg;
36 private Optional<ServerAddress> currentTargetServer; 36 private Optional<ServerAddress> currentTargetServer;
37 private boolean pendingResponse; 37 private boolean pendingResponse;
38 38
@@ -17,10 +17,9 @@ package org.thingsboard.server.actors.tenant; @@ -17,10 +17,9 @@ package org.thingsboard.server.actors.tenant;
17 17
18 import akka.actor.ActorRef; 18 import akka.actor.ActorRef;
19 import akka.actor.Props; 19 import akka.actor.Props;
20 -import akka.event.Logging;  
21 -import akka.event.LoggingAdapter;  
22 import org.thingsboard.server.actors.ActorSystemContext; 20 import org.thingsboard.server.actors.ActorSystemContext;
23 import org.thingsboard.server.actors.device.DeviceActor; 21 import org.thingsboard.server.actors.device.DeviceActor;
  22 +import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg;
24 import org.thingsboard.server.actors.plugin.PluginTerminationMsg; 23 import org.thingsboard.server.actors.plugin.PluginTerminationMsg;
25 import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; 24 import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor;
26 import org.thingsboard.server.actors.service.ContextBasedCreator; 25 import org.thingsboard.server.actors.service.ContextBasedCreator;
@@ -30,7 +29,8 @@ import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager; @@ -30,7 +29,8 @@ import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager;
30 import org.thingsboard.server.common.data.id.DeviceId; 29 import org.thingsboard.server.common.data.id.DeviceId;
31 import org.thingsboard.server.common.data.id.TenantId; 30 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.msg.TbActorMsg; 31 import org.thingsboard.server.common.msg.TbActorMsg;
33 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 32 +import org.thingsboard.server.common.msg.aware.DeviceAwareMsg;
  33 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
34 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 34 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
35 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; 35 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
36 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 36 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
@@ -64,63 +64,47 @@ public class TenantActor extends RuleChainManagerActor { @@ -64,63 +64,47 @@ public class TenantActor extends RuleChainManagerActor {
64 @Override 64 @Override
65 protected boolean process(TbActorMsg msg) { 65 protected boolean process(TbActorMsg msg) {
66 switch (msg.getMsgType()) { 66 switch (msg.getMsgType()) {
  67 + case CLUSTER_EVENT_MSG:
  68 + broadcast(msg);
  69 + break;
67 case COMPONENT_LIFE_CYCLE_MSG: 70 case COMPONENT_LIFE_CYCLE_MSG:
68 onComponentLifecycleMsg((ComponentLifecycleMsg) msg); 71 onComponentLifecycleMsg((ComponentLifecycleMsg) msg);
69 break; 72 break;
70 case SERVICE_TO_RULE_ENGINE_MSG: 73 case SERVICE_TO_RULE_ENGINE_MSG:
71 onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg); 74 onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg);
72 break; 75 break;
  76 + case DEVICE_ACTOR_TO_RULE_ENGINE_MSG:
  77 + onDeviceActorToRuleEngineMsg((DeviceActorToRuleEngineMsg) msg);
  78 + break;
  79 + case DEVICE_SESSION_TO_DEVICE_ACTOR_MSG:
  80 + case DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG:
  81 + case DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG:
  82 + case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG:
  83 + case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG:
  84 + onToDeviceActorMsg((DeviceAwareMsg) msg);
  85 + break;
73 default: 86 default:
74 return false; 87 return false;
75 } 88 }
76 return true; 89 return true;
77 } 90 }
78 91
79 - private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) {  
80 - ruleChainManager.getRootChainActor().tell(msg, self());  
81 - }  
82 -  
83 -  
84 -// @Override  
85 -// public void onReceive(Object msg) throws Exception {  
86 -// logger.debug("[{}] Received message: {}", tenantId, msg);  
87 -// if (msg instanceof ToDeviceActorMsg) {  
88 -// onToDeviceActorMsg((ToDeviceActorMsg) msg);  
89 -// } else if (msg instanceof ToPluginActorMsg) {  
90 -// onToPluginMsg((ToPluginActorMsg) msg);  
91 -// } else if (msg instanceof ToDeviceActorNotificationMsg) {  
92 -// onToDeviceActorMsg((ToDeviceActorNotificationMsg) msg);  
93 -// } else if (msg instanceof ClusterEventMsg) {  
94 -// broadcast(msg);  
95 -// } else if (msg instanceof ComponentLifecycleMsg) {  
96 -// onComponentLifecycleMsg((ComponentLifecycleMsg) msg);  
97 -// } else if (msg instanceof PluginTerminationMsg) {  
98 -// onPluginTerminated((PluginTerminationMsg) msg);  
99 -// } else {  
100 -// logger.warning("[{}] Unknown message: {}!", tenantId, msg);  
101 -// }  
102 -// }  
103 -  
104 - private void broadcast(Object msg) {  
105 - pluginManager.broadcast(msg); 92 + @Override
  93 + protected void broadcast(Object msg) {
  94 + super.broadcast(msg);
106 deviceActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); 95 deviceActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender()));
107 } 96 }
108 97
109 - private void onToDeviceActorMsg(ToDeviceActorMsg msg) {  
110 - getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); 98 + private void onServiceToRuleEngineMsg(ServiceToRuleEngineMsg msg) {
  99 + ruleChainManager.getRootChainActor().tell(msg, self());
111 } 100 }
112 101
113 - private void onToDeviceActorMsg(ToDeviceActorNotificationMsg msg) {  
114 - getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); 102 + private void onDeviceActorToRuleEngineMsg(DeviceActorToRuleEngineMsg msg) {
  103 + ruleChainManager.getRootChainActor().tell(msg, self());
115 } 104 }
116 105
117 - private void onToPluginMsg(ToPluginActorMsg msg) {  
118 - if (msg.getPluginTenantId().equals(tenantId)) {  
119 - ActorRef pluginActor = pluginManager.getOrCreateActor(this.context(), msg.getPluginId());  
120 - pluginActor.tell(msg, ActorRef.noSender());  
121 - } else {  
122 - context().parent().tell(msg, ActorRef.noSender());  
123 - } 106 + private void onToDeviceActorMsg(DeviceAwareMsg msg) {
  107 + getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender());
124 } 108 }
125 109
126 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { 110 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
@@ -132,11 +116,6 @@ public class TenantActor extends RuleChainManagerActor { @@ -132,11 +116,6 @@ public class TenantActor extends RuleChainManagerActor {
132 } 116 }
133 } 117 }
134 118
135 - private void onPluginTerminated(PluginTerminationMsg msg) {  
136 - pluginManager.remove(msg.getId());  
137 - }  
138 -  
139 -  
140 private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { 119 private ActorRef getOrCreateDeviceActor(DeviceId deviceId) {
141 return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId)) 120 return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId))
142 .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), deviceId.toString())); 121 .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), deviceId.toString()));
@@ -606,7 +606,7 @@ public abstract class BaseController { @@ -606,7 +606,7 @@ public abstract class BaseController {
606 auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo); 606 auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo);
607 } 607 }
608 608
609 - protected static Exception toException(Throwable error) { 609 + public static Exception toException(Throwable error) {
610 return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); 610 return Exception.class.isInstance(error) ? (Exception) error : new Exception(error);
611 } 611 }
612 612
  1 +/**
  2 + * Copyright © 2016-2018 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.controller;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import com.fasterxml.jackson.databind.ObjectMapper;
  20 +import com.google.common.util.concurrent.FutureCallback;
  21 +import lombok.extern.slf4j.Slf4j;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.http.HttpStatus;
  24 +import org.springframework.http.ResponseEntity;
  25 +import org.springframework.security.access.prepost.PreAuthorize;
  26 +import org.springframework.web.bind.annotation.PathVariable;
  27 +import org.springframework.web.bind.annotation.RequestBody;
  28 +import org.springframework.web.bind.annotation.RequestMapping;
  29 +import org.springframework.web.bind.annotation.RequestMethod;
  30 +import org.springframework.web.bind.annotation.ResponseBody;
  31 +import org.springframework.web.bind.annotation.RestController;
  32 +import org.springframework.web.context.request.async.DeferredResult;
  33 +import org.thingsboard.server.actors.plugin.ValidationResult;
  34 +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
  35 +import org.thingsboard.server.common.data.exception.ThingsboardException;
  36 +import org.thingsboard.server.common.data.id.DeviceId;
  37 +import org.thingsboard.server.common.data.id.TenantId;
  38 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
  39 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
  40 +import org.thingsboard.server.extensions.api.exception.ToErrorResponseEntity;
  41 +import org.thingsboard.server.extensions.api.plugins.PluginConstants;
  42 +import org.thingsboard.server.common.data.rpc.RpcRequest;
  43 +import org.thingsboard.server.service.rpc.LocalRequestMetaData;
  44 +import org.thingsboard.server.service.rpc.DeviceRpcService;
  45 +import org.thingsboard.server.service.security.AccessValidator;
  46 +import org.thingsboard.server.service.security.model.SecurityUser;
  47 +
  48 +import javax.annotation.Nullable;
  49 +import javax.annotation.PostConstruct;
  50 +import javax.annotation.PreDestroy;
  51 +import java.io.IOException;
  52 +import java.util.Optional;
  53 +import java.util.UUID;
  54 +import java.util.concurrent.ExecutorService;
  55 +import java.util.concurrent.Executors;
  56 +
  57 +/**
  58 + * Created by ashvayka on 22.03.18.
  59 + */
  60 +@RestController
  61 +@RequestMapping(PluginConstants.RPC_URL_PREFIX)
  62 +@Slf4j
  63 +public class RpcController extends BaseController {
  64 +
  65 + public static final int DEFAULT_TIMEOUT = 10000;
  66 + protected final ObjectMapper jsonMapper = new ObjectMapper();
  67 +
  68 + @Autowired
  69 + private DeviceRpcService deviceRpcService;
  70 +
  71 + @Autowired
  72 + private AccessValidator accessValidator;
  73 +
  74 + private ExecutorService executor;
  75 +
  76 + @PostConstruct
  77 + public void initExecutor() {
  78 + executor = Executors.newSingleThreadExecutor();
  79 + }
  80 +
  81 + @PreDestroy
  82 + public void shutdownExecutor() {
  83 + if (executor != null) {
  84 + executor.shutdownNow();
  85 + }
  86 + }
  87 +
  88 + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
  89 + @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
  90 + @ResponseBody
  91 + public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
  92 + return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody);
  93 + }
  94 +
  95 + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
  96 + @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
  97 + @ResponseBody
  98 + public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
  99 + return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody);
  100 + }
  101 +
  102 +
  103 + private DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody) throws ThingsboardException {
  104 + try {
  105 + JsonNode rpcRequestBody = jsonMapper.readTree(requestBody);
  106 + RpcRequest cmd = new RpcRequest(rpcRequestBody.get("method").asText(),
  107 + jsonMapper.writeValueAsString(rpcRequestBody.get("params")));
  108 +
  109 + if (rpcRequestBody.has("timeout")) {
  110 + cmd.setTimeout(rpcRequestBody.get("timeout").asLong());
  111 + }
  112 + SecurityUser currentUser = getCurrentUser();
  113 + TenantId tenantId = currentUser.getTenantId();
  114 + final DeferredResult<ResponseEntity> response = new DeferredResult<>();
  115 + long timeout = System.currentTimeMillis() + (cmd.getTimeout() != null ? cmd.getTimeout() : DEFAULT_TIMEOUT);
  116 + ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(cmd.getMethodName(), cmd.getRequestData());
  117 + accessValidator.validate(currentUser, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() {
  118 + @Override
  119 + public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
  120 +
  121 + ToDeviceRpcRequest rpcRequest = new ToDeviceRpcRequest(UUID.randomUUID(),
  122 + tenantId,
  123 + deviceId,
  124 + oneWay,
  125 + timeout,
  126 + body
  127 + );
  128 + deviceRpcService.process(rpcRequest, new LocalRequestMetaData(rpcRequest, currentUser, result));
  129 + }
  130 +
  131 + @Override
  132 + public void onFailure(Throwable e) {
  133 + ResponseEntity entity;
  134 + if (e instanceof ToErrorResponseEntity) {
  135 + entity = ((ToErrorResponseEntity) e).toErrorResponseEntity();
  136 + } else {
  137 + entity = new ResponseEntity(HttpStatus.UNAUTHORIZED);
  138 + }
  139 + deviceRpcService.logRpcCall(currentUser, deviceId, body, oneWay, Optional.empty(), e);
  140 + response.setResult(entity);
  141 + }
  142 + }));
  143 + return response;
  144 + } catch (IOException ioe) {
  145 + throw new ThingsboardException("Invalid request body", ioe, ThingsboardErrorCode.BAD_REQUEST_PARAMS);
  146 + }
  147 + }
  148 +
  149 +}
@@ -15,21 +15,34 @@ @@ -15,21 +15,34 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import lombok.extern.slf4j.Slf4j;
18 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.http.HttpStatus; 20 import org.springframework.http.HttpStatus;
20 import org.springframework.security.access.prepost.PreAuthorize; 21 import org.springframework.security.access.prepost.PreAuthorize;
21 -import org.springframework.web.bind.annotation.*; 22 +import org.springframework.web.bind.annotation.PathVariable;
  23 +import org.springframework.web.bind.annotation.RequestBody;
  24 +import org.springframework.web.bind.annotation.RequestMapping;
  25 +import org.springframework.web.bind.annotation.RequestMethod;
  26 +import org.springframework.web.bind.annotation.RequestParam;
  27 +import org.springframework.web.bind.annotation.ResponseBody;
  28 +import org.springframework.web.bind.annotation.ResponseStatus;
  29 +import org.springframework.web.bind.annotation.RestController;
22 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
  31 +import org.thingsboard.server.common.data.exception.ThingsboardException;
23 import org.thingsboard.server.common.data.id.TenantId; 32 import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.common.data.page.TextPageData; 33 import org.thingsboard.server.common.data.page.TextPageData;
25 import org.thingsboard.server.common.data.page.TextPageLink; 34 import org.thingsboard.server.common.data.page.TextPageLink;
26 import org.thingsboard.server.dao.tenant.TenantService; 35 import org.thingsboard.server.dao.tenant.TenantService;
27 -import org.thingsboard.server.common.data.exception.ThingsboardException; 36 +import org.thingsboard.server.service.install.InstallScripts;
28 37
29 @RestController 38 @RestController
30 @RequestMapping("/api") 39 @RequestMapping("/api")
  40 +@Slf4j
31 public class TenantController extends BaseController { 41 public class TenantController extends BaseController {
32 - 42 +
  43 + @Autowired
  44 + private InstallScripts installScripts;
  45 +
33 @Autowired 46 @Autowired
34 private TenantService tenantService; 47 private TenantService tenantService;
35 48
@@ -49,10 +62,15 @@ public class TenantController extends BaseController { @@ -49,10 +62,15 @@ public class TenantController extends BaseController {
49 62
50 @PreAuthorize("hasAuthority('SYS_ADMIN')") 63 @PreAuthorize("hasAuthority('SYS_ADMIN')")
51 @RequestMapping(value = "/tenant", method = RequestMethod.POST) 64 @RequestMapping(value = "/tenant", method = RequestMethod.POST)
52 - @ResponseBody 65 + @ResponseBody
53 public Tenant saveTenant(@RequestBody Tenant tenant) throws ThingsboardException { 66 public Tenant saveTenant(@RequestBody Tenant tenant) throws ThingsboardException {
54 try { 67 try {
55 - return checkNotNull(tenantService.saveTenant(tenant)); 68 + boolean newTenant = tenant.getId() == null;
  69 + tenant = checkNotNull(tenantService.saveTenant(tenant));
  70 + if (newTenant) {
  71 + installScripts.createDefaultRuleChains(tenant.getId());
  72 + }
  73 + return tenant;
56 } catch (Exception e) { 74 } catch (Exception e) {
57 throw handleException(e); 75 throw handleException(e);
58 } 76 }
@@ -72,7 +90,7 @@ public class TenantController extends BaseController { @@ -72,7 +90,7 @@ public class TenantController extends BaseController {
72 } 90 }
73 91
74 @PreAuthorize("hasAuthority('SYS_ADMIN')") 92 @PreAuthorize("hasAuthority('SYS_ADMIN')")
75 - @RequestMapping(value = "/tenants", params = { "limit" }, method = RequestMethod.GET) 93 + @RequestMapping(value = "/tenants", params = {"limit"}, method = RequestMethod.GET)
76 @ResponseBody 94 @ResponseBody
77 public TextPageData<Tenant> getTenants(@RequestParam int limit, 95 public TextPageData<Tenant> getTenants(@RequestParam int limit,
78 @RequestParam(required = false) String textSearch, 96 @RequestParam(required = false) String textSearch,
@@ -85,5 +103,5 @@ public class TenantController extends BaseController { @@ -85,5 +103,5 @@ public class TenantController extends BaseController {
85 throw handleException(e); 103 throw handleException(e);
86 } 104 }
87 } 105 }
88 - 106 +
89 } 107 }
@@ -131,8 +131,8 @@ public class ThingsboardInstallService { @@ -131,8 +131,8 @@ public class ThingsboardInstallService {
131 systemDataLoaderService.createSysAdmin(); 131 systemDataLoaderService.createSysAdmin();
132 systemDataLoaderService.createAdminSettings(); 132 systemDataLoaderService.createAdminSettings();
133 systemDataLoaderService.loadSystemWidgets(); 133 systemDataLoaderService.loadSystemWidgets();
134 - systemDataLoaderService.loadSystemPlugins();  
135 - systemDataLoaderService.loadSystemRules(); 134 +// systemDataLoaderService.loadSystemPlugins();
  135 +// systemDataLoaderService.loadSystemRules();
136 136
137 if (loadDemo) { 137 if (loadDemo) {
138 log.info("Loading demo data..."); 138 log.info("Loading demo data...");
@@ -19,7 +19,6 @@ import com.google.protobuf.ByteString; @@ -19,7 +19,6 @@ import com.google.protobuf.ByteString;
19 import io.grpc.Server; 19 import io.grpc.Server;
20 import io.grpc.ServerBuilder; 20 import io.grpc.ServerBuilder;
21 import io.grpc.stub.StreamObserver; 21 import io.grpc.stub.StreamObserver;
22 -import lombok.Setter;  
23 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
24 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
@@ -27,29 +26,24 @@ import org.springframework.util.SerializationUtils; @@ -27,29 +26,24 @@ import org.springframework.util.SerializationUtils;
27 import org.thingsboard.server.actors.rpc.RpcBroadcastMsg; 26 import org.thingsboard.server.actors.rpc.RpcBroadcastMsg;
28 import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; 27 import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg;
29 import org.thingsboard.server.actors.rpc.RpcSessionTellMsg; 28 import org.thingsboard.server.actors.rpc.RpcSessionTellMsg;
30 -import org.thingsboard.server.actors.service.ActorService;  
31 import org.thingsboard.server.common.data.id.EntityId; 29 import org.thingsboard.server.common.data.id.EntityId;
32 import org.thingsboard.server.common.msg.cluster.ServerAddress; 30 import org.thingsboard.server.common.msg.cluster.ServerAddress;
33 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; 31 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
34 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; 32 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
35 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 33 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
36 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 34 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
37 import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse; 35 import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse;
38 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest;  
39 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg; 36 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
40 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg; 37 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg;
41 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; 38 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
42 import org.thingsboard.server.gen.cluster.ClusterAPIProtos; 39 import org.thingsboard.server.gen.cluster.ClusterAPIProtos;
43 import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc; 40 import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc;
44 -import org.thingsboard.server.service.cluster.discovery.DiscoveryService;  
45 import org.thingsboard.server.service.cluster.discovery.ServerInstance; 41 import org.thingsboard.server.service.cluster.discovery.ServerInstance;
46 import org.thingsboard.server.service.cluster.discovery.ServerInstanceService; 42 import org.thingsboard.server.service.cluster.discovery.ServerInstanceService;
47 -import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; 43 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
48 44
49 -import javax.annotation.PostConstruct;  
50 import javax.annotation.PreDestroy; 45 import javax.annotation.PreDestroy;
51 import java.io.IOException; 46 import java.io.IOException;
52 -import java.util.Set;  
53 import java.util.UUID; 47 import java.util.UUID;
54 import java.util.concurrent.ConcurrentHashMap; 48 import java.util.concurrent.ConcurrentHashMap;
55 import java.util.concurrent.ConcurrentMap; 49 import java.util.concurrent.ConcurrentMap;
@@ -124,7 +118,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI @@ -124,7 +118,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
124 } 118 }
125 119
126 @Override 120 @Override
127 - public void tell(ServerAddress serverAddress, ToDeviceActorMsg toForward) { 121 + public void tell(ServerAddress serverAddress, DeviceToDeviceActorMsg toForward) {
128 ClusterAPIProtos.ToRpcServerMessage msg = ClusterAPIProtos.ToRpcServerMessage.newBuilder() 122 ClusterAPIProtos.ToRpcServerMessage msg = ClusterAPIProtos.ToRpcServerMessage.newBuilder()
129 .setToDeviceActorRpcMsg(toProtoMsg(toForward)).build(); 123 .setToDeviceActorRpcMsg(toProtoMsg(toForward)).build();
130 tell(serverAddress, msg); 124 tell(serverAddress, msg);
@@ -138,7 +132,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI @@ -138,7 +132,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
138 } 132 }
139 133
140 @Override 134 @Override
141 - public void tell(ServerAddress serverAddress, ToDeviceRpcRequestPluginMsg toForward) { 135 + public void tell(ServerAddress serverAddress, ToDeviceRpcRequestMsg toForward) {
142 ClusterAPIProtos.ToRpcServerMessage msg = ClusterAPIProtos.ToRpcServerMessage.newBuilder() 136 ClusterAPIProtos.ToRpcServerMessage msg = ClusterAPIProtos.ToRpcServerMessage.newBuilder()
143 .setToDeviceRpcRequestRpcMsg(toProtoMsg(toForward)).build(); 137 .setToDeviceRpcRequestRpcMsg(toProtoMsg(toForward)).build();
144 tell(serverAddress, msg); 138 tell(serverAddress, msg);
@@ -190,7 +184,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI @@ -190,7 +184,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
190 } 184 }
191 } 185 }
192 186
193 - private static ClusterAPIProtos.ToDeviceActorRpcMessage toProtoMsg(ToDeviceActorMsg msg) { 187 + private static ClusterAPIProtos.ToDeviceActorRpcMessage toProtoMsg(DeviceToDeviceActorMsg msg) {
194 return ClusterAPIProtos.ToDeviceActorRpcMessage.newBuilder().setData( 188 return ClusterAPIProtos.ToDeviceActorRpcMessage.newBuilder().setData(
195 ByteString.copyFrom(SerializationUtils.serialize(msg)) 189 ByteString.copyFrom(SerializationUtils.serialize(msg))
196 ).build(); 190 ).build();
@@ -202,15 +196,10 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI @@ -202,15 +196,10 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
202 ).build(); 196 ).build();
203 } 197 }
204 198
205 - private static ClusterAPIProtos.ToDeviceRpcRequestRpcMessage toProtoMsg(ToDeviceRpcRequestPluginMsg msg) { 199 + private static ClusterAPIProtos.ToDeviceRpcRequestRpcMessage toProtoMsg(ToDeviceRpcRequestMsg msg) {
206 ClusterAPIProtos.ToDeviceRpcRequestRpcMessage.Builder builder = ClusterAPIProtos.ToDeviceRpcRequestRpcMessage.newBuilder(); 200 ClusterAPIProtos.ToDeviceRpcRequestRpcMessage.Builder builder = ClusterAPIProtos.ToDeviceRpcRequestRpcMessage.newBuilder();
207 ToDeviceRpcRequest request = msg.getMsg(); 201 ToDeviceRpcRequest request = msg.getMsg();
208 202
209 - builder.setAddress(ClusterAPIProtos.PluginAddress.newBuilder()  
210 - .setTenantId(toUid(msg.getPluginTenantId().getId()))  
211 - .setPluginId(toUid(msg.getPluginId().getId()))  
212 - .build());  
213 -  
214 builder.setDeviceTenantId(toUid(msg.getTenantId())); 203 builder.setDeviceTenantId(toUid(msg.getTenantId()));
215 builder.setDeviceId(toUid(msg.getDeviceId())); 204 builder.setDeviceId(toUid(msg.getDeviceId()));
216 205
@@ -227,11 +216,6 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI @@ -227,11 +216,6 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
227 ClusterAPIProtos.ToPluginRpcResponseRpcMessage.Builder builder = ClusterAPIProtos.ToPluginRpcResponseRpcMessage.newBuilder(); 216 ClusterAPIProtos.ToPluginRpcResponseRpcMessage.Builder builder = ClusterAPIProtos.ToPluginRpcResponseRpcMessage.newBuilder();
228 FromDeviceRpcResponse request = msg.getResponse(); 217 FromDeviceRpcResponse request = msg.getResponse();
229 218
230 - builder.setAddress(ClusterAPIProtos.PluginAddress.newBuilder()  
231 - .setTenantId(toUid(msg.getPluginTenantId().getId()))  
232 - .setPluginId(toUid(msg.getPluginId().getId()))  
233 - .build());  
234 -  
235 builder.setMsgId(toUid(request.getId())); 219 builder.setMsgId(toUid(request.getId()));
236 request.getResponse().ifPresent(builder::setResponse); 220 request.getResponse().ifPresent(builder::setResponse);
237 request.getError().ifPresent(e -> builder.setError(e.name())); 221 request.getError().ifPresent(e -> builder.setError(e.name()));
@@ -19,12 +19,12 @@ import io.grpc.stub.StreamObserver; @@ -19,12 +19,12 @@ import io.grpc.stub.StreamObserver;
19 import org.thingsboard.server.common.msg.cluster.ServerAddress; 19 import org.thingsboard.server.common.msg.cluster.ServerAddress;
20 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; 20 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
21 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; 21 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
22 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 22 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
23 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 23 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
24 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg;  
25 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg; 24 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg;
26 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; 25 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
27 import org.thingsboard.server.gen.cluster.ClusterAPIProtos; 26 import org.thingsboard.server.gen.cluster.ClusterAPIProtos;
  27 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
28 28
29 import java.util.UUID; 29 import java.util.UUID;
30 30
@@ -35,13 +35,13 @@ public interface ClusterRpcService { @@ -35,13 +35,13 @@ public interface ClusterRpcService {
35 35
36 void init(RpcMsgListener listener); 36 void init(RpcMsgListener listener);
37 37
38 - void tell(ServerAddress serverAddress, ToDeviceActorMsg toForward); 38 + void tell(ServerAddress serverAddress, DeviceToDeviceActorMsg toForward);
39 39
40 void tell(ServerAddress serverAddress, ToDeviceSessionActorMsg toForward); 40 void tell(ServerAddress serverAddress, ToDeviceSessionActorMsg toForward);
41 41
42 void tell(ServerAddress serverAddress, ToDeviceActorNotificationMsg toForward); 42 void tell(ServerAddress serverAddress, ToDeviceActorNotificationMsg toForward);
43 43
44 - void tell(ServerAddress serverAddress, ToDeviceRpcRequestPluginMsg toForward); 44 + void tell(ServerAddress serverAddress, ToDeviceRpcRequestMsg toForward);
45 45
46 void tell(ServerAddress serverAddress, ToPluginRpcResponseDeviceMsg toForward); 46 void tell(ServerAddress serverAddress, ToPluginRpcResponseDeviceMsg toForward);
47 47
@@ -50,4 +50,5 @@ public interface ClusterRpcService { @@ -50,4 +50,5 @@ public interface ClusterRpcService {
50 void broadcast(ToAllNodesMsg msg); 50 void broadcast(ToAllNodesMsg msg);
51 51
52 void onSessionCreated(UUID msgUid, StreamObserver<ClusterAPIProtos.ToRpcServerMessage> inputStream); 52 void onSessionCreated(UUID msgUid, StreamObserver<ClusterAPIProtos.ToRpcServerMessage> inputStream);
  53 +
53 } 54 }
@@ -20,18 +20,16 @@ import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg; @@ -20,18 +20,16 @@ import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg;
20 import org.thingsboard.server.actors.rpc.RpcSessionTellMsg; 20 import org.thingsboard.server.actors.rpc.RpcSessionTellMsg;
21 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; 21 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
22 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg; 22 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
23 -import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; 23 +import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
24 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 24 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
25 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginActorMsg; 25 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginActorMsg;
26 -import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;  
27 -import org.thingsboard.server.gen.cluster.ClusterAPIProtos;  
28 26
29 /** 27 /**
30 * @author Andrew Shvayka 28 * @author Andrew Shvayka
31 */ 29 */
32 public interface RpcMsgListener { 30 public interface RpcMsgListener {
33 31
34 - void onMsg(ToDeviceActorMsg msg); 32 + void onMsg(DeviceToDeviceActorMsg msg);
35 33
36 void onMsg(ToDeviceActorNotificationMsg msg); 34 void onMsg(ToDeviceActorNotificationMsg msg);
37 35
@@ -60,21 +60,12 @@ import java.nio.file.Paths; @@ -60,21 +60,12 @@ import java.nio.file.Paths;
60 @Slf4j 60 @Slf4j
61 public class DefaultSystemDataLoaderService implements SystemDataLoaderService { 61 public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
62 62
63 - private static final String JSON_DIR = "json";  
64 - private static final String SYSTEM_DIR = "system";  
65 - private static final String DEMO_DIR = "demo";  
66 - private static final String WIDGET_BUNDLES_DIR = "widget_bundles";  
67 - private static final String PLUGINS_DIR = "plugins";  
68 - private static final String RULES_DIR = "rules";  
69 - private static final String DASHBOARDS_DIR = "dashboards";  
70 -  
71 private static final ObjectMapper objectMapper = new ObjectMapper(); 63 private static final ObjectMapper objectMapper = new ObjectMapper();
72 - public static final String JSON_EXT = ".json";  
73 public static final String CUSTOMER_CRED = "customer"; 64 public static final String CUSTOMER_CRED = "customer";
74 public static final String DEFAULT_DEVICE_TYPE = "default"; 65 public static final String DEFAULT_DEVICE_TYPE = "default";
75 66
76 - @Value("${install.data_dir}")  
77 - private String dataDir; 67 + @Autowired
  68 + private InstallScripts installScripts;
78 69
79 @Autowired 70 @Autowired
80 private BCryptPasswordEncoder passwordEncoder; 71 private BCryptPasswordEncoder passwordEncoder;
@@ -89,15 +80,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -89,15 +80,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
89 private WidgetsBundleService widgetsBundleService; 80 private WidgetsBundleService widgetsBundleService;
90 81
91 @Autowired 82 @Autowired
92 - private WidgetTypeService widgetTypeService;  
93 -  
94 - @Autowired  
95 - private PluginService pluginService;  
96 -  
97 - @Autowired  
98 - private RuleService ruleService;  
99 -  
100 - @Autowired  
101 private TenantService tenantService; 83 private TenantService tenantService;
102 84
103 @Autowired 85 @Autowired
@@ -109,9 +91,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -109,9 +91,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
109 @Autowired 91 @Autowired
110 private DeviceCredentialsService deviceCredentialsService; 92 private DeviceCredentialsService deviceCredentialsService;
111 93
112 - @Autowired  
113 - private DashboardService dashboardService;  
114 -  
115 @Bean 94 @Bean
116 protected BCryptPasswordEncoder passwordEncoder() { 95 protected BCryptPasswordEncoder passwordEncoder() {
117 return new BCryptPasswordEncoder(); 96 return new BCryptPasswordEncoder();
@@ -147,55 +126,12 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -147,55 +126,12 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
147 } 126 }
148 127
149 @Override 128 @Override
150 - public void loadSystemWidgets() throws Exception {  
151 - Path widgetBundlesDir = Paths.get(dataDir, JSON_DIR, SYSTEM_DIR, WIDGET_BUNDLES_DIR);  
152 - try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(widgetBundlesDir, path -> path.toString().endsWith(JSON_EXT))) {  
153 - dirStream.forEach(  
154 - path -> {  
155 - try {  
156 - JsonNode widgetsBundleDescriptorJson = objectMapper.readTree(path.toFile());  
157 - JsonNode widgetsBundleJson = widgetsBundleDescriptorJson.get("widgetsBundle");  
158 - WidgetsBundle widgetsBundle = objectMapper.treeToValue(widgetsBundleJson, WidgetsBundle.class);  
159 - WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);  
160 - JsonNode widgetTypesArrayJson = widgetsBundleDescriptorJson.get("widgetTypes");  
161 - widgetTypesArrayJson.forEach(  
162 - widgetTypeJson -> {  
163 - try {  
164 - WidgetType widgetType = objectMapper.treeToValue(widgetTypeJson, WidgetType.class);  
165 - widgetType.setBundleAlias(savedWidgetsBundle.getAlias());  
166 - widgetTypeService.saveWidgetType(widgetType);  
167 - } catch (Exception e) {  
168 - log.error("Unable to load widget type from json: [{}]", path.toString());  
169 - throw new RuntimeException("Unable to load widget type from json", e);  
170 - }  
171 - }  
172 - );  
173 - } catch (Exception e) {  
174 - log.error("Unable to load widgets bundle from json: [{}]", path.toString());  
175 - throw new RuntimeException("Unable to load widgets bundle from json", e);  
176 - }  
177 - }  
178 - );  
179 - }  
180 - }  
181 -  
182 - @Override  
183 - public void loadSystemPlugins() throws Exception {  
184 - loadPlugins(Paths.get(dataDir, JSON_DIR, SYSTEM_DIR, PLUGINS_DIR), null);  
185 - }  
186 -  
187 -  
188 - @Override  
189 - public void loadSystemRules() throws Exception {  
190 -// loadRules(Paths.get(dataDir, JSON_DIR, SYSTEM_DIR, RULES_DIR), null);  
191 - }  
192 -  
193 - @Override  
194 public void loadDemoData() throws Exception { 129 public void loadDemoData() throws Exception {
195 Tenant demoTenant = new Tenant(); 130 Tenant demoTenant = new Tenant();
196 demoTenant.setRegion("Global"); 131 demoTenant.setRegion("Global");
197 demoTenant.setTitle("Tenant"); 132 demoTenant.setTitle("Tenant");
198 demoTenant = tenantService.saveTenant(demoTenant); 133 demoTenant = tenantService.saveTenant(demoTenant);
  134 + installScripts.createDefaultRuleChains(demoTenant.getId());
199 createUser(Authority.TENANT_ADMIN, demoTenant.getId(), null, "tenant@thingsboard.org", "tenant"); 135 createUser(Authority.TENANT_ADMIN, demoTenant.getId(), null, "tenant@thingsboard.org", "tenant");
200 136
201 Customer customerA = new Customer(); 137 Customer customerA = new Customer();
@@ -227,9 +163,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -227,9 +163,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
227 createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " + 163 createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " +
228 "Raspberry Pi GPIO control sample application"); 164 "Raspberry Pi GPIO control sample application");
229 165
230 - loadPlugins(Paths.get(dataDir, JSON_DIR, DEMO_DIR, PLUGINS_DIR), demoTenant.getId());  
231 -// loadRules(Paths.get(dataDir, JSON_DIR, DEMO_DIR, RULES_DIR), demoTenant.getId());  
232 - loadDashboards(Paths.get(dataDir, JSON_DIR, DEMO_DIR, DASHBOARDS_DIR), demoTenant.getId(), null); 166 + installScripts.loadDashboards(demoTenant.getId(), null);
233 } 167 }
234 168
235 @Override 169 @Override
@@ -240,6 +174,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -240,6 +174,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
240 } 174 }
241 } 175 }
242 176
  177 + @Override
  178 + public void loadSystemWidgets() throws Exception {
  179 + installScripts.loadSystemWidgets();
  180 + }
  181 +
243 private User createUser(Authority authority, 182 private User createUser(Authority authority,
244 TenantId tenantId, 183 TenantId tenantId,
245 CustomerId customerId, 184 CustomerId customerId,
@@ -282,72 +221,4 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -282,72 +221,4 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
282 return device; 221 return device;
283 } 222 }
284 223
285 - private void loadPlugins(Path pluginsDir, TenantId tenantId) throws Exception{  
286 - try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(pluginsDir, path -> path.toString().endsWith(JSON_EXT))) {  
287 - dirStream.forEach(  
288 - path -> {  
289 - try {  
290 - JsonNode pluginJson = objectMapper.readTree(path.toFile());  
291 - PluginMetaData plugin = objectMapper.treeToValue(pluginJson, PluginMetaData.class);  
292 - plugin.setTenantId(tenantId);  
293 - if (plugin.getState() == ComponentLifecycleState.ACTIVE) {  
294 - plugin.setState(ComponentLifecycleState.SUSPENDED);  
295 - PluginMetaData savedPlugin = pluginService.savePlugin(plugin);  
296 - pluginService.activatePluginById(savedPlugin.getId());  
297 - } else {  
298 - pluginService.savePlugin(plugin);  
299 - }  
300 - } catch (Exception e) {  
301 - log.error("Unable to load plugin from json: [{}]", path.toString());  
302 - throw new RuntimeException("Unable to load plugin from json", e);  
303 - }  
304 - }  
305 - );  
306 - }  
307 - }  
308 -  
309 - private void loadRules(Path rulesDir, TenantId tenantId) throws Exception {  
310 - try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(rulesDir, path -> path.toString().endsWith(JSON_EXT))) {  
311 - dirStream.forEach(  
312 - path -> {  
313 - try {  
314 - JsonNode ruleJson = objectMapper.readTree(path.toFile());  
315 - RuleMetaData rule = objectMapper.treeToValue(ruleJson, RuleMetaData.class);  
316 - rule.setTenantId(tenantId);  
317 - if (rule.getState() == ComponentLifecycleState.ACTIVE) {  
318 - rule.setState(ComponentLifecycleState.SUSPENDED);  
319 - RuleMetaData savedRule = ruleService.saveRule(rule);  
320 - ruleService.activateRuleById(savedRule.getId());  
321 - } else {  
322 - ruleService.saveRule(rule);  
323 - }  
324 - } catch (Exception e) {  
325 - log.error("Unable to load rule from json: [{}]", path.toString());  
326 - throw new RuntimeException("Unable to load rule from json", e);  
327 - }  
328 - }  
329 - );  
330 - }  
331 - }  
332 -  
333 - private void loadDashboards(Path dashboardsDir, TenantId tenantId, CustomerId customerId) throws Exception {  
334 - try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) {  
335 - dirStream.forEach(  
336 - path -> {  
337 - try {  
338 - JsonNode dashboardJson = objectMapper.readTree(path.toFile());  
339 - Dashboard dashboard = objectMapper.treeToValue(dashboardJson, Dashboard.class);  
340 - dashboard.setTenantId(tenantId);  
341 - Dashboard savedDashboard = dashboardService.saveDashboard(dashboard);  
342 - if (customerId != null && !customerId.isNullUid()) {  
343 - dashboardService.assignDashboardToCustomer(savedDashboard.getId(), customerId);  
344 - }  
345 - } catch (Exception e) {  
346 - log.error("Unable to load dashboard from json: [{}]", path.toString());  
347 - throw new RuntimeException("Unable to load dashboard from json", e);  
348 - }  
349 - }  
350 - );  
351 - }  
352 - }  
353 } 224 }
  1 +/**
  2 + * Copyright © 2016-2018 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.service.install;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import lombok.Getter;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.beans.factory.annotation.Value;
  23 +import org.springframework.stereotype.Component;
  24 +import org.springframework.util.StringUtils;
  25 +import org.thingsboard.server.common.data.Dashboard;
  26 +import org.thingsboard.server.common.data.id.CustomerId;
  27 +import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.rule.RuleChain;
  29 +import org.thingsboard.server.common.data.rule.RuleChainMetaData;
  30 +import org.thingsboard.server.common.data.widget.WidgetType;
  31 +import org.thingsboard.server.common.data.widget.WidgetsBundle;
  32 +import org.thingsboard.server.dao.dashboard.DashboardService;
  33 +import org.thingsboard.server.dao.rule.RuleChainService;
  34 +import org.thingsboard.server.dao.widget.WidgetTypeService;
  35 +import org.thingsboard.server.dao.widget.WidgetsBundleService;
  36 +
  37 +import java.io.IOException;
  38 +import java.nio.file.DirectoryStream;
  39 +import java.nio.file.Files;
  40 +import java.nio.file.Path;
  41 +import java.nio.file.Paths;
  42 +
  43 +import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper;
  44 +
  45 +/**
  46 + * Created by ashvayka on 18.04.18.
  47 + */
  48 +@Component
  49 +@Slf4j
  50 +public class InstallScripts {
  51 +
  52 + public static final String APP_DIR = "application";
  53 + public static final String SRC_DIR = "src";
  54 + public static final String MAIN_DIR = "main";
  55 + public static final String DATA_DIR = "data";
  56 + public static final String JSON_DIR = "json";
  57 + public static final String SYSTEM_DIR = "system";
  58 + public static final String TENANT_DIR = "tenant";
  59 + public static final String DEMO_DIR = "demo";
  60 + public static final String RULE_CHAINS_DIR = "rule_chains";
  61 + public static final String WIDGET_BUNDLES_DIR = "widget_bundles";
  62 + public static final String DASHBOARDS_DIR = "dashboards";
  63 +
  64 + public static final String JSON_EXT = ".json";
  65 +
  66 + @Value("${install.data_dir:}")
  67 + private String dataDir;
  68 +
  69 + @Autowired
  70 + private RuleChainService ruleChainService;
  71 +
  72 + @Autowired
  73 + private DashboardService dashboardService;
  74 +
  75 + @Autowired
  76 + private WidgetTypeService widgetTypeService;
  77 +
  78 + @Autowired
  79 + private WidgetsBundleService widgetsBundleService;
  80 +
  81 + public Path getTenantRuleChainsDir() {
  82 + return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR);
  83 + }
  84 +
  85 + public String getDataDir() {
  86 + if (!StringUtils.isEmpty(dataDir)) {
  87 + return dataDir;
  88 + } else {
  89 + String workDir = System.getProperty("user.dir");
  90 + if (workDir.endsWith("application")) {
  91 + return Paths.get(workDir, SRC_DIR, MAIN_DIR, DATA_DIR).toString();
  92 + } else {
  93 + Path dataDirPath = Paths.get(workDir, APP_DIR, SRC_DIR, MAIN_DIR, DATA_DIR);
  94 + if (Files.exists(dataDirPath)) {
  95 + return dataDirPath.toString();
  96 + } else {
  97 + throw new RuntimeException("Not valid working directory: " + workDir + ". Please use either root project directory, application module directory or specify valid \"install.data_dir\" ENV variable to avoid automatic data directory lookup!");
  98 + }
  99 + }
  100 + }
  101 + }
  102 +
  103 + public void createDefaultRuleChains(TenantId tenantId) throws IOException {
  104 + Path tenantChainsDir = getTenantRuleChainsDir();
  105 + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(tenantChainsDir, path -> path.toString().endsWith(InstallScripts.JSON_EXT))) {
  106 + dirStream.forEach(
  107 + path -> {
  108 + try {
  109 + JsonNode ruleChainJson = objectMapper.readTree(path.toFile());
  110 + RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
  111 + RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);
  112 +
  113 + ruleChain.setTenantId(tenantId);
  114 + ruleChain = ruleChainService.saveRuleChain(ruleChain);
  115 +
  116 + ruleChainMetaData.setRuleChainId(ruleChain.getId());
  117 + ruleChainService.saveRuleChainMetaData(ruleChainMetaData);
  118 + } catch (Exception e) {
  119 + log.error("Unable to load rule chain from json: [{}]", path.toString());
  120 + throw new RuntimeException("Unable to load rule chain from json", e);
  121 + }
  122 + }
  123 + );
  124 + }
  125 + }
  126 +
  127 + public void loadSystemWidgets() throws Exception {
  128 + Path widgetBundlesDir = Paths.get(getDataDir(), JSON_DIR, SYSTEM_DIR, WIDGET_BUNDLES_DIR);
  129 + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(widgetBundlesDir, path -> path.toString().endsWith(JSON_EXT))) {
  130 + dirStream.forEach(
  131 + path -> {
  132 + try {
  133 + JsonNode widgetsBundleDescriptorJson = objectMapper.readTree(path.toFile());
  134 + JsonNode widgetsBundleJson = widgetsBundleDescriptorJson.get("widgetsBundle");
  135 + WidgetsBundle widgetsBundle = objectMapper.treeToValue(widgetsBundleJson, WidgetsBundle.class);
  136 + WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
  137 + JsonNode widgetTypesArrayJson = widgetsBundleDescriptorJson.get("widgetTypes");
  138 + widgetTypesArrayJson.forEach(
  139 + widgetTypeJson -> {
  140 + try {
  141 + WidgetType widgetType = objectMapper.treeToValue(widgetTypeJson, WidgetType.class);
  142 + widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
  143 + widgetTypeService.saveWidgetType(widgetType);
  144 + } catch (Exception e) {
  145 + log.error("Unable to load widget type from json: [{}]", path.toString());
  146 + throw new RuntimeException("Unable to load widget type from json", e);
  147 + }
  148 + }
  149 + );
  150 + } catch (Exception e) {
  151 + log.error("Unable to load widgets bundle from json: [{}]", path.toString());
  152 + throw new RuntimeException("Unable to load widgets bundle from json", e);
  153 + }
  154 + }
  155 + );
  156 + }
  157 + }
  158 +
  159 + public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception {
  160 + Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR);
  161 + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) {
  162 + dirStream.forEach(
  163 + path -> {
  164 + try {
  165 + JsonNode dashboardJson = objectMapper.readTree(path.toFile());
  166 + Dashboard dashboard = objectMapper.treeToValue(dashboardJson, Dashboard.class);
  167 + dashboard.setTenantId(tenantId);
  168 + Dashboard savedDashboard = dashboardService.saveDashboard(dashboard);
  169 + if (customerId != null && !customerId.isNullUid()) {
  170 + dashboardService.assignDashboardToCustomer(savedDashboard.getId(), customerId);
  171 + }
  172 + } catch (Exception e) {
  173 + log.error("Unable to load dashboard from json: [{}]", path.toString());
  174 + throw new RuntimeException("Unable to load dashboard from json", e);
  175 + }
  176 + }
  177 + );
  178 + }
  179 + }
  180 +
  181 +
  182 +}
@@ -23,10 +23,6 @@ public interface SystemDataLoaderService { @@ -23,10 +23,6 @@ public interface SystemDataLoaderService {
23 23
24 void loadSystemWidgets() throws Exception; 24 void loadSystemWidgets() throws Exception;
25 25
26 - void loadSystemPlugins() throws Exception;  
27 -  
28 - void loadSystemRules() throws Exception;  
29 -  
30 void loadDemoData() throws Exception; 26 void loadDemoData() throws Exception;
31 27
32 void deleteSystemWidgetBundle(String bundleAlias) throws Exception; 28 void deleteSystemWidgetBundle(String bundleAlias) throws Exception;
  1 +/**
  2 + * Copyright © 2016-2018 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.service.rpc;
  17 +
  18 +import akka.actor.ActorRef;
  19 +import com.fasterxml.jackson.databind.ObjectMapper;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.http.HttpStatus;
  23 +import org.springframework.http.ResponseEntity;
  24 +import org.springframework.stereotype.Service;
  25 +import org.springframework.util.StringUtils;
  26 +import org.springframework.web.context.request.async.DeferredResult;
  27 +import org.thingsboard.server.actors.service.ActorService;
  28 +import org.thingsboard.server.common.data.audit.ActionType;
  29 +import org.thingsboard.server.common.data.id.DeviceId;
  30 +import org.thingsboard.server.common.data.id.EntityId;
  31 +import org.thingsboard.server.common.data.id.UUIDBased;
  32 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
  33 +import org.thingsboard.server.common.msg.cluster.ServerAddress;
  34 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
  35 +import org.thingsboard.server.controller.BaseController;
  36 +import org.thingsboard.server.dao.audit.AuditLogService;
  37 +import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse;
  38 +import org.thingsboard.server.extensions.api.plugins.msg.RpcError;
  39 +import org.thingsboard.server.service.cluster.routing.ClusterRoutingService;
  40 +import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;
  41 +import org.thingsboard.server.service.security.model.SecurityUser;
  42 +
  43 +import javax.annotation.PostConstruct;
  44 +import javax.annotation.PreDestroy;
  45 +import java.io.IOException;
  46 +import java.util.Optional;
  47 +import java.util.UUID;
  48 +import java.util.concurrent.ConcurrentHashMap;
  49 +import java.util.concurrent.ConcurrentMap;
  50 +import java.util.concurrent.Executors;
  51 +import java.util.concurrent.ScheduledExecutorService;
  52 +import java.util.concurrent.TimeUnit;
  53 +import java.util.function.BiConsumer;
  54 +
  55 +/**
  56 + * Created by ashvayka on 27.03.18.
  57 + */
  58 +@Service
  59 +@Slf4j
  60 +public class DefaultDeviceRpcService implements DeviceRpcService {
  61 +
  62 + private static final ObjectMapper jsonMapper = new ObjectMapper();
  63 +
  64 + @Autowired
  65 + private ClusterRoutingService routingService;
  66 +
  67 + @Autowired
  68 + private ClusterRpcService rpcService;
  69 +
  70 + @Autowired
  71 + private ActorService actorService;
  72 +
  73 + @Autowired
  74 + private AuditLogService auditLogService;
  75 +
  76 + private ScheduledExecutorService rpcCallBackExecutor;
  77 +
  78 + private final ConcurrentMap<UUID, LocalRequestMetaData> localRpcRequests = new ConcurrentHashMap<>();
  79 +
  80 +
  81 + @PostConstruct
  82 + public void initExecutor() {
  83 + rpcCallBackExecutor = Executors.newSingleThreadScheduledExecutor();
  84 + }
  85 +
  86 + @PreDestroy
  87 + public void shutdownExecutor() {
  88 + if (rpcCallBackExecutor != null) {
  89 + rpcCallBackExecutor.shutdownNow();
  90 + }
  91 + }
  92 +
  93 + @Override
  94 + public void process(ToDeviceRpcRequest request, LocalRequestMetaData metaData) {
  95 + log.trace("[{}] Processing local rpc call for device [{}]", request.getTenantId(), request.getDeviceId());
  96 + sendRpcRequest(request);
  97 + UUID requestId = request.getId();
  98 + localRpcRequests.put(requestId, metaData);
  99 + long timeout = Math.max(0, request.getExpirationTime() - System.currentTimeMillis());
  100 + log.error("[{}] processing the request: [{}]", this.hashCode(), requestId);
  101 + rpcCallBackExecutor.schedule(() -> {
  102 + log.error("[{}] timeout the request: [{}]", this.hashCode(), requestId);
  103 + LocalRequestMetaData localMetaData = localRpcRequests.remove(requestId);
  104 + if (localMetaData != null) {
  105 + reply(localMetaData, new FromDeviceRpcResponse(requestId, null, RpcError.TIMEOUT));
  106 + }
  107 + }, timeout, TimeUnit.MILLISECONDS);
  108 + }
  109 +
  110 + @Override
  111 + public void process(ToDeviceRpcRequest request, ServerAddress originator) {
  112 +// if (pluginServerAddress.isPresent()) {
  113 +// systemContext.getRpcService().tell(pluginServerAddress.get(), responsePluginMsg);
  114 +// logger.debug("[{}] Rpc command response sent to remote plugin actor [{}]!", deviceId, requestMd.getMsg().getMsg().getId());
  115 +// } else {
  116 +// context.parent().tell(responsePluginMsg, ActorRef.noSender());
  117 +// logger.debug("[{}] Rpc command response sent to local plugin actor [{}]!", deviceId, requestMd.getMsg().getMsg().getId());
  118 +// }
  119 + }
  120 +
  121 + @Override
  122 + public void process(FromDeviceRpcResponse response) {
  123 + log.error("[{}] response the request: [{}]", this.hashCode(), response.getId());
  124 + //TODO: send to another server if needed.
  125 + UUID requestId = response.getId();
  126 + LocalRequestMetaData md = localRpcRequests.remove(requestId);
  127 + if (md != null) {
  128 + log.trace("[{}] Processing local rpc response from device [{}]", requestId, md.getRequest().getDeviceId());
  129 + reply(md, response);
  130 + } else {
  131 + log.trace("[{}] Unknown or stale rpc response received [{}]", requestId, response);
  132 + }
  133 + }
  134 +
  135 + public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response) {
  136 + Optional<RpcError> rpcError = response.getError();
  137 + DeferredResult<ResponseEntity> responseWriter = rpcRequest.getResponseWriter();
  138 + if (rpcError.isPresent()) {
  139 + logRpcCall(rpcRequest, rpcError, null);
  140 + RpcError error = rpcError.get();
  141 + switch (error) {
  142 + case TIMEOUT:
  143 + responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT));
  144 + break;
  145 + case NO_ACTIVE_CONNECTION:
  146 + responseWriter.setResult(new ResponseEntity<>(HttpStatus.CONFLICT));
  147 + break;
  148 + default:
  149 + responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT));
  150 + break;
  151 + }
  152 + } else {
  153 + Optional<String> responseData = response.getResponse();
  154 + if (responseData.isPresent() && !StringUtils.isEmpty(responseData.get())) {
  155 + String data = responseData.get();
  156 + try {
  157 + logRpcCall(rpcRequest, rpcError, null);
  158 + responseWriter.setResult(new ResponseEntity<>(jsonMapper.readTree(data), HttpStatus.OK));
  159 + } catch (IOException e) {
  160 + log.debug("Failed to decode device response: {}", data, e);
  161 + logRpcCall(rpcRequest, rpcError, e);
  162 + responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE));
  163 + }
  164 + } else {
  165 + logRpcCall(rpcRequest, rpcError, null);
  166 + responseWriter.setResult(new ResponseEntity<>(HttpStatus.OK));
  167 + }
  168 + }
  169 + }
  170 +
  171 + private void sendRpcRequest(ToDeviceRpcRequest msg) {
  172 + log.trace("[{}] Forwarding msg {} to device actor!", msg.getDeviceId(), msg);
  173 + ToDeviceRpcRequestMsg rpcMsg = new ToDeviceRpcRequestMsg(msg);
  174 + forward(msg.getDeviceId(), rpcMsg, rpcService::tell);
  175 + }
  176 +
  177 + private void forward(DeviceId deviceId, ToDeviceRpcRequestMsg msg, BiConsumer<ServerAddress, ToDeviceRpcRequestMsg> rpcFunction) {
  178 + Optional<ServerAddress> instance = routingService.resolveById(deviceId);
  179 + if (instance.isPresent()) {
  180 + log.trace("[{}] Forwarding msg {} to remote device actor!", msg.getTenantId(), msg);
  181 + rpcFunction.accept(instance.get(), msg);
  182 + } else {
  183 + log.trace("[{}] Forwarding msg {} to local device actor!", msg.getTenantId(), msg);
  184 + actorService.onMsg(msg);
  185 + }
  186 + }
  187 +
  188 + private void logRpcCall(LocalRequestMetaData rpcRequest, Optional<RpcError> rpcError, Throwable e) {
  189 + logRpcCall(rpcRequest.getUser(), rpcRequest.getRequest().getDeviceId(), rpcRequest.getRequest().getBody(), rpcRequest.getRequest().isOneway(), rpcError, null);
  190 + }
  191 +
  192 + @Override
  193 + public void logRpcCall(SecurityUser user, EntityId entityId, ToDeviceRpcRequestBody body, boolean oneWay, Optional<RpcError> rpcError, Throwable e) {
  194 + String rpcErrorStr = "";
  195 + if (rpcError.isPresent()) {
  196 + rpcErrorStr = "RPC Error: " + rpcError.get().name();
  197 + }
  198 + String method = body.getMethod();
  199 + String params = body.getParams();
  200 +
  201 + auditLogService.logEntityAction(
  202 + user.getTenantId(),
  203 + user.getCustomerId(),
  204 + user.getId(),
  205 + user.getName(),
  206 + (UUIDBased & EntityId) entityId,
  207 + null,
  208 + ActionType.RPC_CALL,
  209 + BaseController.toException(e),
  210 + rpcErrorStr,
  211 + oneWay,
  212 + method,
  213 + params);
  214 + }
  215 +}
application/src/main/java/org/thingsboard/server/service/rpc/DeviceRpcService.java renamed from application/src/test/java/org/thingsboard/server/controller/nosql/RuleControllerNoSqlTest.java
@@ -13,14 +13,28 @@ @@ -13,14 +13,28 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.controller.nosql; 16 +package org.thingsboard.server.service.rpc;
17 17
18 -import org.thingsboard.server.controller.BaseRuleControllerTest;  
19 -import org.thingsboard.server.dao.service.DaoNoSqlTest; 18 +import org.thingsboard.server.common.data.id.EntityId;
  19 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
  20 +import org.thingsboard.server.common.msg.cluster.ServerAddress;
  21 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
  22 +import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse;
  23 +import org.thingsboard.server.extensions.api.plugins.msg.RpcError;
  24 +import org.thingsboard.server.service.security.model.SecurityUser;
  25 +
  26 +import java.util.Optional;
20 27
21 /** 28 /**
22 - * Created by Valerii Sosliuk on 6/28/2017. 29 + * Created by ashvayka on 16.04.18.
23 */ 30 */
24 -@DaoNoSqlTest  
25 -public class RuleControllerNoSqlTest extends BaseRuleControllerTest { 31 +public interface DeviceRpcService {
  32 +
  33 + void process(ToDeviceRpcRequest request, LocalRequestMetaData metaData);
  34 +
  35 + void process(ToDeviceRpcRequest request, ServerAddress originator);
  36 +
  37 + void process(FromDeviceRpcResponse response);
  38 +
  39 + void logRpcCall(SecurityUser user, EntityId entityId, ToDeviceRpcRequestBody body, boolean oneWay, Optional<RpcError> rpcError, Throwable e);
26 } 40 }
application/src/main/java/org/thingsboard/server/service/rpc/LocalRequestMetaData.java renamed from extensions-core/src/main/java/org/thingsboard/server/extensions/core/plugin/rpc/LocalRequestMetaData.java
@@ -13,18 +13,20 @@ @@ -13,18 +13,20 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.extensions.core.plugin.rpc; 16 +package org.thingsboard.server.service.rpc;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import org.springframework.http.ResponseEntity; 19 import org.springframework.http.ResponseEntity;
20 import org.springframework.web.context.request.async.DeferredResult; 20 import org.springframework.web.context.request.async.DeferredResult;
21 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest; 21 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
  22 +import org.thingsboard.server.service.security.model.SecurityUser;
22 23
23 /** 24 /**
24 - * @author Andrew Shvayka 25 + * Created by ashvayka on 16.04.18.
25 */ 26 */
26 @Data 27 @Data
27 public class LocalRequestMetaData { 28 public class LocalRequestMetaData {
28 private final ToDeviceRpcRequest request; 29 private final ToDeviceRpcRequest request;
  30 + private final SecurityUser user;
29 private final DeferredResult<ResponseEntity> responseWriter; 31 private final DeferredResult<ResponseEntity> responseWriter;
30 } 32 }
application/src/main/java/org/thingsboard/server/service/rpc/ToDeviceRpcRequestMsg.java renamed from extensions-api/src/main/java/org/thingsboard/server/extensions/api/plugins/msg/ToDeviceRpcRequestPluginMsg.java
@@ -13,36 +13,33 @@ @@ -13,36 +13,33 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.extensions.api.plugins.msg; 16 +package org.thingsboard.server.service.rpc;
17 17
18 import lombok.Getter; 18 import lombok.Getter;
19 import lombok.RequiredArgsConstructor; 19 import lombok.RequiredArgsConstructor;
20 import lombok.ToString; 20 import lombok.ToString;
21 import org.thingsboard.server.common.data.id.DeviceId; 21 import org.thingsboard.server.common.data.id.DeviceId;
22 -import org.thingsboard.server.common.data.id.PluginId;  
23 import org.thingsboard.server.common.data.id.TenantId; 22 import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.common.msg.MsgType;
24 import org.thingsboard.server.common.msg.cluster.ServerAddress; 24 import org.thingsboard.server.common.msg.cluster.ServerAddress;
  25 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
25 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg; 26 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
26 27
27 import java.util.Optional; 28 import java.util.Optional;
28 29
29 /** 30 /**
30 - * @author Andrew Shvayka 31 + * Created by ashvayka on 16.04.18.
31 */ 32 */
32 @ToString 33 @ToString
33 @RequiredArgsConstructor 34 @RequiredArgsConstructor
34 -public class ToDeviceRpcRequestPluginMsg implements ToDeviceActorNotificationMsg { 35 +public class ToDeviceRpcRequestMsg implements ToDeviceActorNotificationMsg {
35 36
36 private final ServerAddress serverAddress; 37 private final ServerAddress serverAddress;
37 @Getter 38 @Getter
38 - private final PluginId pluginId;  
39 - @Getter  
40 - private final TenantId pluginTenantId;  
41 - @Getter  
42 private final ToDeviceRpcRequest msg; 39 private final ToDeviceRpcRequest msg;
43 40
44 - public ToDeviceRpcRequestPluginMsg(PluginId pluginId, TenantId pluginTenantId, ToDeviceRpcRequest msg) {  
45 - this(null, pluginId, pluginTenantId, msg); 41 + public ToDeviceRpcRequestMsg(ToDeviceRpcRequest msg) {
  42 + this(null, msg);
46 } 43 }
47 44
48 public Optional<ServerAddress> getServerAddress() { 45 public Optional<ServerAddress> getServerAddress() {
@@ -58,5 +55,9 @@ public class ToDeviceRpcRequestPluginMsg implements ToDeviceActorNotificationMsg @@ -58,5 +55,9 @@ public class ToDeviceRpcRequestPluginMsg implements ToDeviceActorNotificationMsg
58 public TenantId getTenantId() { 55 public TenantId getTenantId() {
59 return msg.getTenantId(); 56 return msg.getTenantId();
60 } 57 }
61 -}  
62 58
  59 + @Override
  60 + public MsgType getMsgType() {
  61 + return MsgType.DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG;
  62 + }
  63 +}
@@ -25,6 +25,7 @@ import org.springframework.http.ResponseEntity; @@ -25,6 +25,7 @@ import org.springframework.http.ResponseEntity;
25 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
26 import org.springframework.web.context.request.async.DeferredResult; 26 import org.springframework.web.context.request.async.DeferredResult;
27 import org.thingsboard.server.actors.plugin.ValidationResult; 27 import org.thingsboard.server.actors.plugin.ValidationResult;
  28 +import org.thingsboard.server.common.data.BaseData;
28 import org.thingsboard.server.common.data.Customer; 29 import org.thingsboard.server.common.data.Customer;
29 import org.thingsboard.server.common.data.Device; 30 import org.thingsboard.server.common.data.Device;
30 import org.thingsboard.server.common.data.Tenant; 31 import org.thingsboard.server.common.data.Tenant;
@@ -35,8 +36,10 @@ import org.thingsboard.server.common.data.id.DeviceId; @@ -35,8 +36,10 @@ import org.thingsboard.server.common.data.id.DeviceId;
35 import org.thingsboard.server.common.data.id.EntityId; 36 import org.thingsboard.server.common.data.id.EntityId;
36 import org.thingsboard.server.common.data.id.EntityIdFactory; 37 import org.thingsboard.server.common.data.id.EntityIdFactory;
37 import org.thingsboard.server.common.data.id.RuleChainId; 38 import org.thingsboard.server.common.data.id.RuleChainId;
  39 +import org.thingsboard.server.common.data.id.RuleNodeId;
38 import org.thingsboard.server.common.data.id.TenantId; 40 import org.thingsboard.server.common.data.id.TenantId;
39 import org.thingsboard.server.common.data.rule.RuleChain; 41 import org.thingsboard.server.common.data.rule.RuleChain;
  42 +import org.thingsboard.server.common.data.rule.RuleNode;
40 import org.thingsboard.server.controller.HttpValidationCallback; 43 import org.thingsboard.server.controller.HttpValidationCallback;
41 import org.thingsboard.server.dao.alarm.AlarmService; 44 import org.thingsboard.server.dao.alarm.AlarmService;
42 import org.thingsboard.server.dao.asset.AssetService; 45 import org.thingsboard.server.dao.asset.AssetService;
@@ -140,7 +143,7 @@ public class AccessValidator { @@ -140,7 +143,7 @@ public class AccessValidator {
140 return response; 143 return response;
141 } 144 }
142 145
143 - public <T> void validate(SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) { 146 + public void validate(SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
144 switch (entityId.getEntityType()) { 147 switch (entityId.getEntityType()) {
145 case DEVICE: 148 case DEVICE:
146 validateDevice(currentUser, entityId, callback); 149 validateDevice(currentUser, entityId, callback);
@@ -177,14 +180,14 @@ public class AccessValidator { @@ -177,14 +180,14 @@ public class AccessValidator {
177 } else if (currentUser.isCustomerUser() && !device.getCustomerId().equals(currentUser.getCustomerId())) { 180 } else if (currentUser.isCustomerUser() && !device.getCustomerId().equals(currentUser.getCustomerId())) {
178 return ValidationResult.accessDenied("Device doesn't belong to the current Customer!"); 181 return ValidationResult.accessDenied("Device doesn't belong to the current Customer!");
179 } else { 182 } else {
180 - return ValidationResult.ok(); 183 + return ValidationResult.ok(device);
181 } 184 }
182 } 185 }
183 }), executor); 186 }), executor);
184 } 187 }
185 } 188 }
186 189
187 - private <T> void validateAsset(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) { 190 + private void validateAsset(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
188 if (currentUser.isSystemAdmin()) { 191 if (currentUser.isSystemAdmin()) {
189 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); 192 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
190 } else { 193 } else {
@@ -198,15 +201,14 @@ public class AccessValidator { @@ -198,15 +201,14 @@ public class AccessValidator {
198 } else if (currentUser.isCustomerUser() && !asset.getCustomerId().equals(currentUser.getCustomerId())) { 201 } else if (currentUser.isCustomerUser() && !asset.getCustomerId().equals(currentUser.getCustomerId())) {
199 return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!"); 202 return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!");
200 } else { 203 } else {
201 - return ValidationResult.ok(); 204 + return ValidationResult.ok(asset);
202 } 205 }
203 } 206 }
204 }), executor); 207 }), executor);
205 } 208 }
206 } 209 }
207 210
208 -  
209 - private <T> void validateRuleChain(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) { 211 + private void validateRuleChain(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
210 if (currentUser.isCustomerUser()) { 212 if (currentUser.isCustomerUser()) {
211 callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); 213 callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
212 } else { 214 } else {
@@ -220,14 +222,40 @@ public class AccessValidator { @@ -220,14 +222,40 @@ public class AccessValidator {
220 } else if (currentUser.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) { 222 } else if (currentUser.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) {
221 return ValidationResult.accessDenied("Rule chain is not in system scope!"); 223 return ValidationResult.accessDenied("Rule chain is not in system scope!");
222 } else { 224 } else {
223 - return ValidationResult.ok(); 225 + return ValidationResult.ok(ruleChain);
  226 + }
  227 + }
  228 + }), executor);
  229 + }
  230 + }
  231 +
  232 + private void validateRule(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
  233 + if (currentUser.isCustomerUser()) {
  234 + callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
  235 + } else {
  236 + ListenableFuture<RuleNode> ruleNodeFuture = ruleChainService.findRuleNodeByIdAsync(new RuleNodeId(entityId.getId()));
  237 + Futures.addCallback(ruleNodeFuture, getCallback(callback, ruleNodeTmp -> {
  238 + RuleNode ruleNode = ruleNodeTmp;
  239 + if (ruleNode == null) {
  240 + return ValidationResult.entityNotFound("Rule node with requested id wasn't found!");
  241 + } else if (ruleNode.getRuleChainId() == null) {
  242 + return ValidationResult.entityNotFound("Rule chain with requested node id wasn't found!");
  243 + } else {
  244 + //TODO: make async
  245 + RuleChain ruleChain = ruleChainService.findRuleChainById(ruleNode.getRuleChainId());
  246 + if (currentUser.isTenantAdmin() && !ruleChain.getTenantId().equals(currentUser.getTenantId())) {
  247 + return ValidationResult.accessDenied("Rule chain doesn't belong to the current Tenant!");
  248 + } else if (currentUser.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) {
  249 + return ValidationResult.accessDenied("Rule chain is not in system scope!");
  250 + } else {
  251 + return ValidationResult.ok(ruleNode);
224 } 252 }
225 } 253 }
226 }), executor); 254 }), executor);
227 } 255 }
228 } 256 }
229 257
230 - private <T> void validateCustomer(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) { 258 + private void validateCustomer(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
231 if (currentUser.isSystemAdmin()) { 259 if (currentUser.isSystemAdmin()) {
232 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); 260 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
233 } else { 261 } else {
@@ -241,18 +269,18 @@ public class AccessValidator { @@ -241,18 +269,18 @@ public class AccessValidator {
241 } else if (currentUser.isCustomerUser() && !customer.getId().equals(currentUser.getCustomerId())) { 269 } else if (currentUser.isCustomerUser() && !customer.getId().equals(currentUser.getCustomerId())) {
242 return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!"); 270 return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!");
243 } else { 271 } else {
244 - return ValidationResult.ok(); 272 + return ValidationResult.ok(customer);
245 } 273 }
246 } 274 }
247 }), executor); 275 }), executor);
248 } 276 }
249 } 277 }
250 278
251 - private <T> void validateTenant(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) { 279 + private void validateTenant(final SecurityUser currentUser, EntityId entityId, FutureCallback<ValidationResult> callback) {
252 if (currentUser.isCustomerUser()) { 280 if (currentUser.isCustomerUser()) {
253 callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); 281 callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
254 } else if (currentUser.isSystemAdmin()) { 282 } else if (currentUser.isSystemAdmin()) {
255 - callback.onSuccess(ValidationResult.ok()); 283 + callback.onSuccess(ValidationResult.ok(null));
256 } else { 284 } else {
257 ListenableFuture<Tenant> tenantFuture = tenantService.findTenantByIdAsync(new TenantId(entityId.getId())); 285 ListenableFuture<Tenant> tenantFuture = tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
258 Futures.addCallback(tenantFuture, getCallback(callback, tenant -> { 286 Futures.addCallback(tenantFuture, getCallback(callback, tenant -> {
@@ -261,13 +289,13 @@ public class AccessValidator { @@ -261,13 +289,13 @@ public class AccessValidator {
261 } else if (!tenant.getId().equals(currentUser.getTenantId())) { 289 } else if (!tenant.getId().equals(currentUser.getTenantId())) {
262 return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!"); 290 return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!");
263 } else { 291 } else {
264 - return ValidationResult.ok(); 292 + return ValidationResult.ok(tenant);
265 } 293 }
266 }), executor); 294 }), executor);
267 } 295 }
268 } 296 }
269 297
270 - private <T> FutureCallback<T> getCallback(FutureCallback<ValidationResult> callback, Function<T, ValidationResult> transformer) { 298 + private <T, V> FutureCallback<T> getCallback(FutureCallback<ValidationResult> callback, Function<T, ValidationResult<V>> transformer) {
271 return new FutureCallback<T>() { 299 return new FutureCallback<T>() {
272 @Override 300 @Override
273 public void onSuccess(@Nullable T result) { 301 public void onSuccess(@Nullable T result) {
@@ -61,7 +61,6 @@ message ConnectRpcMessage { @@ -61,7 +61,6 @@ message ConnectRpcMessage {
61 } 61 }
62 62
63 message ToDeviceRpcRequestRpcMessage { 63 message ToDeviceRpcRequestRpcMessage {
64 - PluginAddress address = 1;  
65 Uid deviceTenantId = 2; 64 Uid deviceTenantId = 2;
66 Uid deviceId = 3; 65 Uid deviceId = 3;
67 66
@@ -73,8 +72,6 @@ message ToDeviceRpcRequestRpcMessage { @@ -73,8 +72,6 @@ message ToDeviceRpcRequestRpcMessage {
73 } 72 }
74 73
75 message ToPluginRpcResponseRpcMessage { 74 message ToPluginRpcResponseRpcMessage {
76 - PluginAddress address = 1;  
77 -  
78 Uid msgId = 2; 75 Uid msgId = 2;
79 string response = 3; 76 string response = 3;
80 string error = 4; 77 string error = 4;
@@ -207,18 +207,7 @@ actors: @@ -207,18 +207,7 @@ actors:
207 sync: 207 sync:
208 # Default timeout for processing request using synchronous session (HTTP, CoAP) in milliseconds 208 # Default timeout for processing request using synchronous session (HTTP, CoAP) in milliseconds
209 timeout: "${ACTORS_SESSION_SYNC_TIMEOUT:10000}" 209 timeout: "${ACTORS_SESSION_SYNC_TIMEOUT:10000}"
210 - plugin:  
211 - # Default timeout for termination of the plugin actor after it is stopped  
212 - termination.delay: "${ACTORS_PLUGIN_TERMINATION_DELAY:60000}"  
213 - # Default timeout for processing of particular message by particular plugin  
214 - processing.timeout: "${ACTORS_PLUGIN_TIMEOUT:60000}"  
215 - # Errors for particular actor are persisted once per specified amount of milliseconds  
216 - error_persist_frequency: "${ACTORS_PLUGIN_ERROR_FREQUENCY:3000}"  
217 rule: 210 rule:
218 - # Default timeout for termination of the rule actor after it is stopped  
219 - termination.delay: "${ACTORS_RULE_TERMINATION_DELAY:30000}"  
220 - # Errors for particular actor are persisted once per specified amount of milliseconds  
221 - error_persist_frequency: "${ACTORS_RULE_ERROR_FREQUENCY:3000}"  
222 # Specify thread pool size for database request callbacks executor service 211 # Specify thread pool size for database request callbacks executor service
223 db_callback_thread_pool_size: "${ACTORS_RULE_DB_CALLBACK_THREAD_POOL_SIZE:1}" 212 db_callback_thread_pool_size: "${ACTORS_RULE_DB_CALLBACK_THREAD_POOL_SIZE:1}"
224 # Specify thread pool size for javascript executor service 213 # Specify thread pool size for javascript executor service
@@ -235,6 +224,11 @@ actors: @@ -235,6 +224,11 @@ actors:
235 # Enable/disable actor statistics 224 # Enable/disable actor statistics
236 enabled: "${ACTORS_STATISTICS_ENABLED:true}" 225 enabled: "${ACTORS_STATISTICS_ENABLED:true}"
237 persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}" 226 persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}"
  227 + queue:
  228 + # Enable/disable persistence of un-processed messages to the queue
  229 + enabled: "${ACTORS_QUEUE_ENABLED:true}"
  230 + # Maximum allowed timeout for persistence into the queue
  231 + timeout: "${ACTORS_QUEUE_PERSISTENCE_TIMEOUT:30000}"
238 232
239 cache: 233 cache:
240 # caffeine or redis 234 # caffeine or redis
1 -/**  
2 - * Copyright © 2016-2018 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.actors;  
17 -  
18 -import org.junit.extensions.cpsuite.ClasspathSuite;  
19 -import org.junit.runner.RunWith;  
20 -  
21 -/**  
22 - * @author Andrew Shvayka  
23 - */  
24 -@RunWith(ClasspathSuite.class)  
25 -@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.actors.*Test"})  
26 -public class ActorsTestSuite {  
27 -}  
1 -/**  
2 - * Copyright © 2016-2018 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.actors;  
17 -  
18 -import static org.mockito.Matchers.any;  
19 -import static org.mockito.Mockito.mock;  
20 -import static org.mockito.Mockito.verify;  
21 -import static org.mockito.Mockito.when;  
22 -  
23 -import java.util.*;  
24 -  
25 -import com.google.common.util.concurrent.Futures;  
26 -import org.thingsboard.server.actors.service.DefaultActorService;  
27 -import org.thingsboard.server.common.data.id.*;  
28 -import org.thingsboard.server.common.data.kv.TsKvEntry;  
29 -import org.thingsboard.server.common.data.page.TextPageData;  
30 -import org.thingsboard.server.common.data.plugin.ComponentDescriptor;  
31 -import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;  
32 -import org.thingsboard.server.common.data.plugin.ComponentType;  
33 -import org.thingsboard.server.common.msg.session.*;  
34 -import org.thingsboard.server.dao.attributes.AttributesService;  
35 -import org.thingsboard.server.dao.event.EventService;  
36 -import org.thingsboard.server.gen.discovery.ServerInstanceProtos;  
37 -import org.thingsboard.server.service.cluster.discovery.DiscoveryService;  
38 -import org.thingsboard.server.service.cluster.discovery.ServerInstance;  
39 -import org.thingsboard.server.service.cluster.routing.ClusterRoutingService;  
40 -import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;  
41 -import org.thingsboard.server.service.component.ComponentDiscoveryService;  
42 -import org.thingsboard.server.common.transport.auth.DeviceAuthResult;  
43 -import org.thingsboard.server.common.transport.auth.DeviceAuthService;  
44 -import org.thingsboard.server.common.data.DataConstants;  
45 -import org.thingsboard.server.common.data.Device;  
46 -import org.thingsboard.server.common.data.Tenant;  
47 -import org.thingsboard.server.common.data.kv.BasicTsKvEntry;  
48 -import org.thingsboard.server.common.data.kv.KvEntry;  
49 -import org.thingsboard.server.common.data.kv.StringDataEntry;  
50 -import org.thingsboard.server.common.data.plugin.PluginMetaData;  
51 -import org.thingsboard.server.common.data.rule.RuleMetaData;  
52 -import org.thingsboard.server.common.data.security.DeviceCredentialsFilter;  
53 -import org.thingsboard.server.common.data.security.DeviceTokenCredentials;  
54 -import org.thingsboard.server.common.msg.core.BasicTelemetryUploadRequest;  
55 -import org.thingsboard.server.dao.device.DeviceService;  
56 -import org.thingsboard.server.dao.model.ModelConstants;  
57 -import org.thingsboard.server.dao.plugin.PluginService;  
58 -import org.thingsboard.server.dao.rule.RuleService;  
59 -import org.thingsboard.server.dao.tenant.TenantService;  
60 -import org.thingsboard.server.dao.timeseries.TimeseriesService;  
61 -import org.thingsboard.server.extensions.core.plugin.telemetry.TelemetryStoragePlugin;  
62 -import org.junit.After;  
63 -import org.junit.Before;  
64 -import org.junit.Test;  
65 -import org.mockito.Mockito;  
66 -import org.springframework.test.util.ReflectionTestUtils;  
67 -  
68 -import com.fasterxml.jackson.databind.JsonNode;  
69 -import com.fasterxml.jackson.databind.ObjectMapper;  
70 -  
71 -public class DefaultActorServiceTest {  
72 -  
73 - private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID);  
74 -  
75 - private static final String PLUGIN_ID = "9fb2e951-e298-4acb-913a-db69af8a15f4";  
76 - private static final String FILTERS_CONFIGURATION =  
77 - "[{\"clazz\":\"org.thingsboard.server.extensions.core.filter.MsgTypeFilter\", \"name\":\"TelemetryFilter\", \"configuration\": {\"messageTypes\":[\"POST_TELEMETRY\",\"POST_ATTRIBUTES\",\"GET_ATTRIBUTES\"]}}]";  
78 - private static final String ACTION_CONFIGURATION = "{\"pluginToken\":\"telemetry\", \"clazz\":\"org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction\", \"name\":\"TelemetryMsgConverterAction\", \"configuration\":{}}";  
79 - private static final String PLUGIN_CONFIGURATION = "{}";  
80 - private DefaultActorService actorService;  
81 - private ActorSystemContext actorContext;  
82 -  
83 - private PluginService pluginService;  
84 - private RuleService ruleService;  
85 - private DeviceAuthService deviceAuthService;  
86 - private DeviceService deviceService;  
87 - private TimeseriesService tsService;  
88 - private TenantService tenantService;  
89 - private ClusterRpcService rpcService;  
90 - private DiscoveryService discoveryService;  
91 - private ClusterRoutingService routingService;  
92 - private AttributesService attributesService;  
93 - private ComponentDiscoveryService componentService;  
94 - private EventService eventService;  
95 - private ServerInstance serverInstance;  
96 -  
97 - private RuleMetaData ruleMock;  
98 - private PluginMetaData pluginMock;  
99 - private RuleId ruleId = new RuleId(UUID.randomUUID());  
100 - private PluginId pluginId = new PluginId(UUID.fromString(PLUGIN_ID));  
101 - private TenantId tenantId = new TenantId(UUID.randomUUID());  
102 -  
103 -  
104 - @Before  
105 - public void before() throws Exception {  
106 - actorService = new DefaultActorService();  
107 - actorContext = new ActorSystemContext();  
108 -  
109 - tenantService = mock(TenantService.class);  
110 - pluginService = mock(PluginService.class);  
111 - ruleService = mock(RuleService.class);  
112 - deviceAuthService = mock(DeviceAuthService.class);  
113 - deviceService = mock(DeviceService.class);  
114 - tsService = mock(TimeseriesService.class);  
115 - rpcService = mock(ClusterRpcService.class);  
116 - discoveryService = mock(DiscoveryService.class);  
117 - routingService = mock(ClusterRoutingService.class);  
118 - attributesService = mock(AttributesService.class);  
119 - componentService = mock(ComponentDiscoveryService.class);  
120 - eventService = mock(EventService.class);  
121 - serverInstance = new ServerInstance(ServerInstanceProtos.ServerInfo.newBuilder().setHost("localhost").setPort(8080).build());  
122 -  
123 - ReflectionTestUtils.setField(actorService, "actorContext", actorContext);  
124 - ReflectionTestUtils.setField(actorService, "rpcService", rpcService);  
125 - ReflectionTestUtils.setField(actorService, "discoveryService", discoveryService);  
126 -  
127 - ReflectionTestUtils.setField(actorContext, "syncSessionTimeout", 10000L);  
128 - ReflectionTestUtils.setField(actorContext, "pluginActorTerminationDelay", 10000L);  
129 - ReflectionTestUtils.setField(actorContext, "pluginErrorPersistFrequency", 10000L);  
130 - ReflectionTestUtils.setField(actorContext, "ruleActorTerminationDelay", 10000L);  
131 - ReflectionTestUtils.setField(actorContext, "ruleErrorPersistFrequency", 10000L);  
132 - ReflectionTestUtils.setField(actorContext, "pluginProcessingTimeout", 60000L);  
133 - ReflectionTestUtils.setField(actorContext, "tenantService", tenantService);  
134 - ReflectionTestUtils.setField(actorContext, "pluginService", pluginService);  
135 - ReflectionTestUtils.setField(actorContext, "ruleService", ruleService);  
136 - ReflectionTestUtils.setField(actorContext, "deviceAuthService", deviceAuthService);  
137 - ReflectionTestUtils.setField(actorContext, "deviceService", deviceService);  
138 - ReflectionTestUtils.setField(actorContext, "tsService", tsService);  
139 - ReflectionTestUtils.setField(actorContext, "rpcService", rpcService);  
140 - ReflectionTestUtils.setField(actorContext, "discoveryService", discoveryService);  
141 - ReflectionTestUtils.setField(actorContext, "tsService", tsService);  
142 - ReflectionTestUtils.setField(actorContext, "routingService", routingService);  
143 - ReflectionTestUtils.setField(actorContext, "attributesService", attributesService);  
144 - ReflectionTestUtils.setField(actorContext, "componentService", componentService);  
145 - ReflectionTestUtils.setField(actorContext, "eventService", eventService);  
146 -  
147 -  
148 - when(routingService.resolveById((EntityId) any())).thenReturn(Optional.empty());  
149 -  
150 - when(discoveryService.getCurrentServer()).thenReturn(serverInstance);  
151 -  
152 - ruleMock = mock(RuleMetaData.class);  
153 - when(ruleMock.getId()).thenReturn(ruleId);  
154 - when(ruleMock.getState()).thenReturn(ComponentLifecycleState.ACTIVE);  
155 - when(ruleMock.getPluginToken()).thenReturn("telemetry");  
156 - TextPageData<RuleMetaData> systemRules = new TextPageData<>(Collections.emptyList(), null, false);  
157 - TextPageData<RuleMetaData> tenantRules = new TextPageData<>(Collections.singletonList(ruleMock), null, false);  
158 - when(ruleService.findSystemRules(any())).thenReturn(systemRules);  
159 - when(ruleService.findTenantRules(any(), any())).thenReturn(tenantRules);  
160 - when(ruleService.findRuleById(ruleId)).thenReturn(ruleMock);  
161 -  
162 - pluginMock = mock(PluginMetaData.class);  
163 - when(pluginMock.getTenantId()).thenReturn(SYSTEM_TENANT);  
164 - when(pluginMock.getId()).thenReturn(pluginId);  
165 - when(pluginMock.getState()).thenReturn(ComponentLifecycleState.ACTIVE);  
166 - TextPageData<PluginMetaData> systemPlugins = new TextPageData<>(Collections.singletonList(pluginMock), null, false);  
167 - TextPageData<PluginMetaData> tenantPlugins = new TextPageData<>(Collections.emptyList(), null, false);  
168 - when(pluginService.findSystemPlugins(any())).thenReturn(systemPlugins);  
169 - when(pluginService.findTenantPlugins(any(), any())).thenReturn(tenantPlugins);  
170 - when(pluginService.findPluginByApiToken("telemetry")).thenReturn(pluginMock);  
171 - when(pluginService.findPluginById(pluginId)).thenReturn(pluginMock);  
172 -  
173 - TextPageData<Tenant> tenants = new TextPageData<>(Collections.emptyList(), null, false);  
174 - when(tenantService.findTenants(any())).thenReturn(tenants);  
175 - }  
176 -  
177 - private void initActorSystem() {  
178 - actorService.initActorSystem();  
179 - }  
180 -  
181 - @After  
182 - public void after() {  
183 - actorService.stopActorSystem();  
184 - }  
185 -  
186 - @Test  
187 - public void testBasicPostWithSyncSession() throws Exception {  
188 - SessionContext ssnCtx = mock(SessionContext.class);  
189 - KvEntry entry1 = new StringDataEntry("key1", "value1");  
190 - KvEntry entry2 = new StringDataEntry("key2", "value2");  
191 - BasicTelemetryUploadRequest telemetry = new BasicTelemetryUploadRequest();  
192 - long ts = 42;  
193 - telemetry.add(ts, entry1);  
194 - telemetry.add(ts, entry2);  
195 - BasicAdaptorToSessionActorMsg msg = new BasicAdaptorToSessionActorMsg(ssnCtx, telemetry);  
196 -  
197 - DeviceId deviceId = new DeviceId(UUID.randomUUID());  
198 -  
199 - DeviceCredentialsFilter filter = new DeviceTokenCredentials("token1");  
200 - Device device = mock(Device.class);  
201 -  
202 - when(device.getId()).thenReturn(deviceId);  
203 - when(device.getTenantId()).thenReturn(tenantId);  
204 - when(ssnCtx.getSessionId()).thenReturn(new DummySessionID("session1"));  
205 - when(ssnCtx.getSessionType()).thenReturn(SessionType.SYNC);  
206 - when(deviceAuthService.process(filter)).thenReturn(DeviceAuthResult.of(deviceId));  
207 - when(deviceService.findDeviceById(deviceId)).thenReturn(device);  
208 -  
209 - ObjectMapper ruleMapper = new ObjectMapper();  
210 - when(ruleMock.getFilters()).thenReturn(ruleMapper.readTree(FILTERS_CONFIGURATION));  
211 - when(ruleMock.getAction()).thenReturn(ruleMapper.readTree(ACTION_CONFIGURATION));  
212 -  
213 - ComponentDescriptor filterComp = new ComponentDescriptor();  
214 - filterComp.setClazz("org.thingsboard.server.extensions.core.filter.MsgTypeFilter");  
215 - filterComp.setType(ComponentType.FILTER);  
216 - when(componentService.getComponent("org.thingsboard.server.extensions.core.filter.MsgTypeFilter"))  
217 - .thenReturn(Optional.of(filterComp));  
218 -  
219 - ComponentDescriptor actionComp = new ComponentDescriptor();  
220 - actionComp.setClazz("org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction");  
221 - actionComp.setType(ComponentType.ACTION);  
222 - when(componentService.getComponent("org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction"))  
223 - .thenReturn(Optional.of(actionComp));  
224 -  
225 - ObjectMapper pluginMapper = new ObjectMapper();  
226 - JsonNode pluginAdditionalInfo = pluginMapper.readTree(PLUGIN_CONFIGURATION);  
227 - when(pluginMock.getConfiguration()).thenReturn(pluginAdditionalInfo);  
228 - when(pluginMock.getClazz()).thenReturn(TelemetryStoragePlugin.class.getName());  
229 -  
230 - when(attributesService.findAll(deviceId, DataConstants.CLIENT_SCOPE)).thenReturn(Futures.immediateFuture(Collections.emptyList()));  
231 - when(attributesService.findAll(deviceId, DataConstants.SHARED_SCOPE)).thenReturn(Futures.immediateFuture(Collections.emptyList()));  
232 - when(attributesService.findAll(deviceId, DataConstants.SERVER_SCOPE)).thenReturn(Futures.immediateFuture(Collections.emptyList()));  
233 -  
234 - initActorSystem();  
235 - Thread.sleep(1000);  
236 - actorService.process(new BasicToDeviceActorSessionMsg(device, msg));  
237 -  
238 - // Check that device data was saved to DB;  
239 - List<TsKvEntry> expected = new ArrayList<>();  
240 - expected.add(new BasicTsKvEntry(ts, entry1));  
241 - expected.add(new BasicTsKvEntry(ts, entry2));  
242 - verify(tsService, Mockito.timeout(5000)).save(deviceId, expected, 0L);  
243 - }  
244 -  
245 -}  
1 -/**  
2 - * Copyright © 2016-2018 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.actors;  
17 -  
18 -import org.thingsboard.server.common.data.id.SessionId;  
19 -  
20 -public class DummySessionID implements SessionId {  
21 -  
22 - @Override  
23 - public String toString() {  
24 - return id;  
25 - }  
26 -  
27 - private final String id;  
28 -  
29 - public DummySessionID(String id) {  
30 - this.id = id;  
31 - }  
32 -  
33 - @Override  
34 - public String toUidStr() {  
35 - return id;  
36 - }  
37 -  
38 - @Override  
39 - public int hashCode() {  
40 - final int prime = 31;  
41 - int result = 1;  
42 - result = prime * result + ((id == null) ? 0 : id.hashCode());  
43 - return result;  
44 - }  
45 -  
46 - @Override  
47 - public boolean equals(Object obj) {  
48 - if (this == obj)  
49 - return true;  
50 - if (obj == null)  
51 - return false;  
52 - if (getClass() != obj.getClass())  
53 - return false;  
54 - DummySessionID other = (DummySessionID) obj;  
55 - if (id == null) {  
56 - if (other.id != null)  
57 - return false;  
58 - } else if (!id.equals(other.id))  
59 - return false;  
60 - return true;  
61 - }  
62 -  
63 -}  
@@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
18 import com.fasterxml.jackson.core.type.TypeReference; 18 import com.fasterxml.jackson.core.type.TypeReference;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import org.springframework.beans.factory.annotation.Autowired;
19 import org.thingsboard.server.common.data.DataConstants; 21 import org.thingsboard.server.common.data.DataConstants;
20 import org.thingsboard.server.common.data.Event; 22 import org.thingsboard.server.common.data.Event;
21 import org.thingsboard.server.common.data.id.EntityId; 23 import org.thingsboard.server.common.data.id.EntityId;
@@ -25,12 +27,18 @@ import org.thingsboard.server.common.data.page.TimePageData; @@ -25,12 +27,18 @@ import org.thingsboard.server.common.data.page.TimePageData;
25 import org.thingsboard.server.common.data.page.TimePageLink; 27 import org.thingsboard.server.common.data.page.TimePageLink;
26 import org.thingsboard.server.common.data.rule.RuleChain; 28 import org.thingsboard.server.common.data.rule.RuleChain;
27 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 29 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
  30 +import org.thingsboard.server.dao.rule.RuleChainService;
  31 +
  32 +import java.io.IOException;
28 33
29 /** 34 /**
30 * Created by ashvayka on 20.03.18. 35 * Created by ashvayka on 20.03.18.
31 */ 36 */
32 public class AbstractRuleEngineControllerTest extends AbstractControllerTest { 37 public class AbstractRuleEngineControllerTest extends AbstractControllerTest {
33 38
  39 + @Autowired
  40 + protected RuleChainService ruleChainService;
  41 +
34 protected RuleChain saveRuleChain(RuleChain ruleChain) throws Exception { 42 protected RuleChain saveRuleChain(RuleChain ruleChain) throws Exception {
35 return doPost("/api/ruleChain", ruleChain, RuleChain.class); 43 return doPost("/api/ruleChain", ruleChain, RuleChain.class);
36 } 44 }
@@ -53,4 +61,13 @@ public class AbstractRuleEngineControllerTest extends AbstractControllerTest { @@ -53,4 +61,13 @@ public class AbstractRuleEngineControllerTest extends AbstractControllerTest {
53 new TypeReference<TimePageData<Event>>() { 61 new TypeReference<TimePageData<Event>>() {
54 }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG_RULE_NODE, tenantId.getId()); 62 }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG_RULE_NODE, tenantId.getId());
55 } 63 }
  64 +
  65 + protected JsonNode getMetadata(Event outEvent) {
  66 + String metaDataStr = outEvent.getBody().get("metadata").asText();
  67 + try {
  68 + return mapper.readTree(metaDataStr);
  69 + } catch (IOException e) {
  70 + throw new RuntimeException(e);
  71 + }
  72 + }
56 } 73 }
@@ -20,6 +20,7 @@ import org.junit.After; @@ -20,6 +20,7 @@ import org.junit.After;
20 import org.junit.Assert; 20 import org.junit.Assert;
21 import org.junit.Before; 21 import org.junit.Before;
22 import org.junit.Test; 22 import org.junit.Test;
  23 +import org.thingsboard.rule.engine.filter.TbJsFilterNode;
23 import org.thingsboard.server.common.data.Tenant; 24 import org.thingsboard.server.common.data.Tenant;
24 import org.thingsboard.server.common.data.User; 25 import org.thingsboard.server.common.data.User;
25 import org.thingsboard.server.common.data.plugin.ComponentDescriptor; 26 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
@@ -35,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @@ -35,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
35 36
36 public abstract class BaseComponentDescriptorControllerTest extends AbstractControllerTest { 37 public abstract class BaseComponentDescriptorControllerTest extends AbstractControllerTest {
37 38
38 - private static final int AMOUNT_OF_DEFAULT_PLUGINS_DESCRIPTORS = 5; 39 + private static final int AMOUNT_OF_DEFAULT_FILTER_NODES = 3;
39 private Tenant savedTenant; 40 private Tenant savedTenant;
40 private User tenantAdmin; 41 private User tenantAdmin;
41 42
@@ -69,38 +70,28 @@ public abstract class BaseComponentDescriptorControllerTest extends AbstractCont @@ -69,38 +70,28 @@ public abstract class BaseComponentDescriptorControllerTest extends AbstractCont
69 @Test 70 @Test
70 public void testGetByClazz() throws Exception { 71 public void testGetByClazz() throws Exception {
71 ComponentDescriptor descriptor = 72 ComponentDescriptor descriptor =
72 - doGet("/api/component/" + TelemetryStoragePlugin.class.getName(), ComponentDescriptor.class); 73 + doGet("/api/component/" + TbJsFilterNode.class.getName(), ComponentDescriptor.class);
73 74
74 Assert.assertNotNull(descriptor); 75 Assert.assertNotNull(descriptor);
75 Assert.assertNotNull(descriptor.getId()); 76 Assert.assertNotNull(descriptor.getId());
76 Assert.assertNotNull(descriptor.getName()); 77 Assert.assertNotNull(descriptor.getName());
77 Assert.assertEquals(ComponentScope.TENANT, descriptor.getScope()); 78 Assert.assertEquals(ComponentScope.TENANT, descriptor.getScope());
78 - Assert.assertEquals(ComponentType.PLUGIN, descriptor.getType()); 79 + Assert.assertEquals(ComponentType.FILTER, descriptor.getType());
79 Assert.assertEquals(descriptor.getClazz(), descriptor.getClazz()); 80 Assert.assertEquals(descriptor.getClazz(), descriptor.getClazz());
80 } 81 }
81 82
82 @Test 83 @Test
83 public void testGetByType() throws Exception { 84 public void testGetByType() throws Exception {
84 List<ComponentDescriptor> descriptors = readResponse( 85 List<ComponentDescriptor> descriptors = readResponse(
85 - doGet("/api/components/" + ComponentType.PLUGIN).andExpect(status().isOk()), new TypeReference<List<ComponentDescriptor>>() { 86 + doGet("/api/components/" + ComponentType.FILTER).andExpect(status().isOk()), new TypeReference<List<ComponentDescriptor>>() {
86 }); 87 });
87 88
88 Assert.assertNotNull(descriptors); 89 Assert.assertNotNull(descriptors);
89 - Assert.assertEquals(AMOUNT_OF_DEFAULT_PLUGINS_DESCRIPTORS, descriptors.size()); 90 + Assert.assertEquals(AMOUNT_OF_DEFAULT_FILTER_NODES, descriptors.size());
90 91
91 for (ComponentType type : ComponentType.values()) { 92 for (ComponentType type : ComponentType.values()) {
92 doGet("/api/components/" + type).andExpect(status().isOk()); 93 doGet("/api/components/" + type).andExpect(status().isOk());
93 } 94 }
94 } 95 }
95 96
96 - @Test  
97 - public void testGetActionsByType() throws Exception {  
98 - List<ComponentDescriptor> descriptors = readResponse(  
99 - doGet("/api/components/actions/" + TelemetryStoragePlugin.class.getName()).andExpect(status().isOk()), new TypeReference<List<ComponentDescriptor>>() {  
100 - });  
101 -  
102 - Assert.assertNotNull(descriptors);  
103 - Assert.assertEquals(1, descriptors.size());  
104 - Assert.assertEquals(TelemetryPluginAction.class.getName(), descriptors.get(0).getClazz());  
105 - }  
106 } 97 }
1 -/**  
2 - * Copyright © 2016-2018 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.controller;  
17 -  
18 -import com.fasterxml.jackson.core.type.TypeReference;  
19 -import com.fasterxml.jackson.databind.ObjectMapper;  
20 -import org.junit.After;  
21 -import org.junit.Assert;  
22 -import org.junit.Before;  
23 -import org.junit.Test;  
24 -import org.thingsboard.server.common.data.Tenant;  
25 -import org.thingsboard.server.common.data.User;  
26 -import org.thingsboard.server.common.data.page.TextPageData;  
27 -import org.thingsboard.server.common.data.page.TextPageLink;  
28 -import org.thingsboard.server.common.data.plugin.PluginMetaData;  
29 -import org.thingsboard.server.common.data.rule.RuleMetaData;  
30 -import org.thingsboard.server.common.data.security.Authority;  
31 -import org.thingsboard.server.extensions.core.plugin.telemetry.TelemetryStoragePlugin;  
32 -  
33 -import java.util.ArrayList;  
34 -import java.util.Collections;  
35 -import java.util.List;  
36 -import java.util.stream.Collectors;  
37 -  
38 -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;  
39 -  
40 -public abstract class BasePluginControllerTest extends AbstractControllerTest {  
41 -  
42 - private IdComparator<PluginMetaData> idComparator = new IdComparator<>();  
43 -  
44 - private final ObjectMapper mapper = new ObjectMapper();  
45 - private Tenant savedTenant;  
46 - private User tenantAdmin;  
47 -  
48 - @Before  
49 - public void beforeTest() throws Exception {  
50 - loginSysAdmin();  
51 -  
52 - Tenant tenant = new Tenant();  
53 - tenant.setTitle("My tenant");  
54 - savedTenant = doPost("/api/tenant", tenant, Tenant.class);  
55 - Assert.assertNotNull(savedTenant);  
56 -  
57 - tenantAdmin = new User();  
58 - tenantAdmin.setAuthority(Authority.TENANT_ADMIN);  
59 - tenantAdmin.setTenantId(savedTenant.getId());  
60 - tenantAdmin.setEmail("tenant2@thingsboard.org");  
61 - tenantAdmin.setFirstName("Joe");  
62 - tenantAdmin.setLastName("Downs");  
63 -  
64 - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");  
65 - }  
66 -  
67 - @After  
68 - public void afterTest() throws Exception {  
69 - loginSysAdmin();  
70 -  
71 - doDelete("/api/tenant/" + savedTenant.getId().getId().toString())  
72 - .andExpect(status().isOk());  
73 - }  
74 -  
75 - @Test  
76 - public void testSavePlugin() throws Exception {  
77 - PluginMetaData plugin = new PluginMetaData();  
78 - doPost("/api/plugin", plugin).andExpect(status().isBadRequest());  
79 - plugin.setName("My plugin");  
80 - doPost("/api/plugin", plugin).andExpect(status().isBadRequest());  
81 - plugin.setApiToken("myplugin");  
82 - doPost("/api/plugin", plugin).andExpect(status().isBadRequest());  
83 - plugin.setConfiguration(mapper.readTree("{}"));  
84 - doPost("/api/plugin", plugin).andExpect(status().isBadRequest());  
85 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
86 - PluginMetaData savedPlugin = doPost("/api/plugin", plugin, PluginMetaData.class);  
87 -  
88 - Assert.assertNotNull(savedPlugin);  
89 - Assert.assertNotNull(savedPlugin.getId());  
90 - Assert.assertTrue(savedPlugin.getCreatedTime() > 0);  
91 - Assert.assertEquals(savedTenant.getId(), savedPlugin.getTenantId());  
92 - }  
93 -  
94 - @Test  
95 - public void testFindPluginById() throws Exception {  
96 - PluginMetaData plugin = new PluginMetaData();  
97 - plugin.setName("My plugin");  
98 - plugin.setApiToken("myplugin");  
99 - plugin.setConfiguration(mapper.readTree("{}"));  
100 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
101 -  
102 - PluginMetaData savedPlugin = doPost("/api/plugin", plugin, PluginMetaData.class);  
103 - PluginMetaData foundPlugin = doGet("/api/plugin/" + savedPlugin.getId().getId().toString(), PluginMetaData.class);  
104 - Assert.assertNotNull(foundPlugin);  
105 - Assert.assertEquals(savedPlugin, foundPlugin);  
106 - }  
107 -  
108 - @Test  
109 - public void testActivatePlugin() throws Exception {  
110 - PluginMetaData plugin = new PluginMetaData();  
111 - plugin.setName("My plugin");  
112 - plugin.setApiToken("myplugin");  
113 - plugin.setConfiguration(mapper.readTree("{}"));  
114 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
115 -  
116 - PluginMetaData savedPlugin = doPost("/api/plugin", plugin, PluginMetaData.class);  
117 -  
118 - doPost("/api/plugin/" + savedPlugin.getId().getId().toString() + "/activate").andExpect(status().isOk());  
119 - }  
120 -  
121 - @Test  
122 - public void testSuspendPlugin() throws Exception {  
123 - PluginMetaData plugin = new PluginMetaData();  
124 - plugin.setName("My plugin");  
125 - plugin.setApiToken("myplugin");  
126 - plugin.setConfiguration(mapper.readTree("{}"));  
127 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
128 -  
129 - PluginMetaData savedPlugin = doPost("/api/plugin", plugin, PluginMetaData.class);  
130 -  
131 - doPost("/api/plugin/" + savedPlugin.getId().getId().toString() + "/activate").andExpect(status().isOk());  
132 -  
133 - RuleMetaData rule = BaseRuleControllerTest.createRuleMetaData(savedPlugin);  
134 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
135 - doPost("/api/rule/" + savedRule.getId().getId().toString() + "/activate").andExpect(status().isOk());  
136 -  
137 - doPost("/api/plugin/" + savedPlugin.getId().getId().toString() + "/suspend").andExpect(status().isBadRequest());  
138 -  
139 - doPost("/api/rule/" + savedRule.getId().getId().toString() + "/suspend").andExpect(status().isOk());  
140 -  
141 - doPost("/api/plugin/" + savedPlugin.getId().getId().toString() + "/suspend").andExpect(status().isOk());  
142 - }  
143 -  
144 - @Test  
145 - public void testDeletePluginById() throws Exception {  
146 - PluginMetaData plugin = new PluginMetaData();  
147 - plugin.setName("My plugin");  
148 - plugin.setApiToken("myplugin");  
149 - plugin.setConfiguration(mapper.readTree("{}"));  
150 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
151 -  
152 - PluginMetaData savedPlugin = doPost("/api/plugin", plugin, PluginMetaData.class);  
153 -  
154 - RuleMetaData rule = BaseRuleControllerTest.createRuleMetaData(savedPlugin);  
155 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
156 -  
157 - doDelete("/api/plugin/" + savedPlugin.getId().getId()).andExpect(status().isBadRequest());  
158 -  
159 - doDelete("/api/rule/" + savedRule.getId().getId()).andExpect(status().isOk());  
160 -  
161 - doDelete("/api/plugin/" + savedPlugin.getId().getId()).andExpect(status().isOk());  
162 - doGet("/api/plugin/" + savedPlugin.getId().getId().toString()).andExpect(status().isNotFound());  
163 - }  
164 -  
165 - @Test  
166 - public void testFindPluginByToken() throws Exception {  
167 - PluginMetaData plugin = new PluginMetaData();  
168 - plugin.setName("My plugin");  
169 - plugin.setApiToken("myplugin");  
170 - plugin.setConfiguration(mapper.readTree("{}"));  
171 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
172 -  
173 - PluginMetaData savedPlugin = doPost("/api/plugin", plugin, PluginMetaData.class);  
174 - PluginMetaData foundPlugin = doGet("/api/plugin/token/" + "myplugin", PluginMetaData.class);  
175 - Assert.assertNotNull(foundPlugin);  
176 - Assert.assertEquals(savedPlugin, foundPlugin);  
177 - }  
178 -  
179 - @Test  
180 - public void testFindCurrentTenantPlugins() throws Exception {  
181 - List<PluginMetaData> plugins = testPluginsCreation("/api/plugin");  
182 - for (PluginMetaData plugin : plugins) {  
183 - doDelete("/api/plugin/" + plugin.getId().getId()).andExpect(status().isOk());  
184 - }  
185 - }  
186 -  
187 - @Test  
188 - public void testFindSystemPlugins() throws Exception {  
189 - loginSysAdmin();  
190 - List<PluginMetaData> plugins = testPluginsCreation("/api/plugin/system");  
191 - for (PluginMetaData plugin : plugins) {  
192 - doDelete("/api/plugin/" + plugin.getId().getId()).andExpect(status().isOk());  
193 - }  
194 - }  
195 -  
196 - private List<PluginMetaData> testPluginsCreation(String url) throws Exception {  
197 - List<PluginMetaData> plugins = new ArrayList<>();  
198 - for (int i = 0; i < 111; i++) {  
199 - PluginMetaData plugin = new PluginMetaData();  
200 - plugin.setName("My plugin");  
201 - plugin.setApiToken("myplugin" + i);  
202 - plugin.setConfiguration(mapper.readTree("{}"));  
203 - plugin.setClazz(TelemetryStoragePlugin.class.getName());  
204 - plugins.add(doPost("/api/plugin", plugin, PluginMetaData.class));  
205 - }  
206 -  
207 - List<PluginMetaData> loadedPlugins = new ArrayList<>();  
208 - TextPageLink pageLink = new TextPageLink(23);  
209 - TextPageData<PluginMetaData> pageData;  
210 - do {  
211 - pageData = doGetTypedWithPageLink(url + "?",  
212 - new TypeReference<TextPageData<PluginMetaData>>() {  
213 - }, pageLink);  
214 - loadedPlugins.addAll(pageData.getData());  
215 - if (pageData.hasNext()) {  
216 - pageLink = pageData.getNextPageLink();  
217 - }  
218 - } while (pageData.hasNext());  
219 -  
220 - loadedPlugins = loadedPlugins.stream()  
221 - .filter(p -> !p.getName().equals("System Telemetry Plugin"))  
222 - .filter(p -> !p.getName().equals("Mail Sender Plugin"))  
223 - .filter(p -> !p.getName().equals("System RPC Plugin"))  
224 - .collect(Collectors.toList());  
225 -  
226 - Collections.sort(plugins, idComparator);  
227 - Collections.sort(loadedPlugins, idComparator);  
228 -  
229 - Assert.assertEquals(plugins, loadedPlugins);  
230 - return loadedPlugins;  
231 - }  
232 -}  
1 -/**  
2 - * Copyright © 2016-2018 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.controller;  
17 -  
18 -import com.fasterxml.jackson.core.type.TypeReference;  
19 -import com.fasterxml.jackson.databind.ObjectMapper;  
20 -import org.junit.After;  
21 -import org.junit.Assert;  
22 -import org.junit.Before;  
23 -import org.junit.Test;  
24 -import org.thingsboard.server.common.data.Tenant;  
25 -import org.thingsboard.server.common.data.User;  
26 -import org.thingsboard.server.common.data.page.TextPageData;  
27 -import org.thingsboard.server.common.data.page.TextPageLink;  
28 -import org.thingsboard.server.common.data.plugin.PluginMetaData;  
29 -import org.thingsboard.server.common.data.rule.RuleMetaData;  
30 -import org.thingsboard.server.common.data.security.Authority;  
31 -import org.thingsboard.server.extensions.core.plugin.telemetry.TelemetryStoragePlugin;  
32 -  
33 -import java.io.IOException;  
34 -import java.util.ArrayList;  
35 -import java.util.Collections;  
36 -import java.util.List;  
37 -import java.util.stream.Collectors;  
38 -  
39 -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;  
40 -  
41 -public abstract class BaseRuleControllerTest extends AbstractControllerTest {  
42 -  
43 - private IdComparator<RuleMetaData> idComparator = new IdComparator<>();  
44 -  
45 - private static final ObjectMapper mapper = new ObjectMapper();  
46 - private Tenant savedTenant;  
47 - private User tenantAdmin;  
48 - private PluginMetaData sysPlugin;  
49 - private PluginMetaData tenantPlugin;  
50 -  
51 - @Before  
52 - public void beforeTest() throws Exception {  
53 - loginSysAdmin();  
54 -  
55 - sysPlugin = new PluginMetaData();  
56 - sysPlugin.setName("Sys plugin");  
57 - sysPlugin.setApiToken("sysplugin");  
58 - sysPlugin.setConfiguration(mapper.readTree("{}"));  
59 - sysPlugin.setClazz(TelemetryStoragePlugin.class.getName());  
60 - sysPlugin = doPost("/api/plugin", sysPlugin, PluginMetaData.class);  
61 -  
62 - Tenant tenant = new Tenant();  
63 - tenant.setTitle("My tenant");  
64 - savedTenant = doPost("/api/tenant", tenant, Tenant.class);  
65 - Assert.assertNotNull(savedTenant);  
66 -  
67 - tenantAdmin = new User();  
68 - tenantAdmin.setAuthority(Authority.TENANT_ADMIN);  
69 - tenantAdmin.setTenantId(savedTenant.getId());  
70 - tenantAdmin.setEmail("tenant2@thingsboard.org");  
71 - tenantAdmin.setFirstName("Joe");  
72 - tenantAdmin.setLastName("Downs");  
73 -  
74 - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");  
75 -  
76 - tenantPlugin = new PluginMetaData();  
77 - tenantPlugin.setName("My plugin");  
78 - tenantPlugin.setApiToken("myplugin");  
79 - tenantPlugin.setConfiguration(mapper.readTree("{}"));  
80 - tenantPlugin.setClazz(TelemetryStoragePlugin.class.getName());  
81 - tenantPlugin = doPost("/api/plugin", tenantPlugin, PluginMetaData.class);  
82 - }  
83 -  
84 - @After  
85 - public void afterTest() throws Exception {  
86 - loginSysAdmin();  
87 -  
88 - doDelete("/api/tenant/" + savedTenant.getId().getId().toString())  
89 - .andExpect(status().isOk());  
90 -  
91 - doDelete("/api/plugin/" + sysPlugin.getId().getId()).andExpect(status().isOk());  
92 - }  
93 -  
94 - @Test  
95 - public void testSaveRule() throws Exception {  
96 - RuleMetaData rule = new RuleMetaData();  
97 - doPost("/api/rule", rule).andExpect(status().isBadRequest());  
98 - rule.setName("My Rule");  
99 - doPost("/api/rule", rule).andExpect(status().isBadRequest());  
100 - rule.setPluginToken(tenantPlugin.getApiToken());  
101 - doPost("/api/rule", rule).andExpect(status().isBadRequest());  
102 - rule.setFilters(mapper.readTree("[{\"clazz\":\"org.thingsboard.server.extensions.core.filter.MsgTypeFilter\", " +  
103 - "\"name\":\"TelemetryFilter\", " +  
104 - "\"configuration\": {\"messageTypes\":[\"POST_TELEMETRY\",\"POST_ATTRIBUTES\",\"GET_ATTRIBUTES\"]}}]"));  
105 - doPost("/api/rule", rule).andExpect(status().isBadRequest());  
106 - rule.setAction(mapper.readTree("{\"clazz\":\"org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction\", \"name\":\"TelemetryMsgConverterAction\", \"configuration\":{\"timeUnit\":\"DAYS\", \"ttlValue\":1}}"));  
107 -  
108 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
109 - Assert.assertNotNull(savedRule);  
110 - Assert.assertNotNull(savedRule.getId());  
111 - Assert.assertTrue(savedRule.getCreatedTime() > 0);  
112 - Assert.assertEquals(savedTenant.getId(), savedRule.getTenantId());  
113 - }  
114 -  
115 - @Test  
116 - public void testFindRuleById() throws Exception {  
117 - RuleMetaData rule = createRuleMetaData(tenantPlugin);  
118 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
119 -  
120 - RuleMetaData foundRule = doGet("/api/rule/" + savedRule.getId().getId().toString(), RuleMetaData.class);  
121 - Assert.assertNotNull(foundRule);  
122 - Assert.assertEquals(savedRule, foundRule);  
123 - }  
124 -  
125 - @Test  
126 - public void testFindRuleByPluginToken() throws Exception {  
127 - RuleMetaData rule = createRuleMetaData(tenantPlugin);  
128 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
129 -  
130 - List<RuleMetaData> foundRules = doGetTyped("/api/rule/token/" + savedRule.getPluginToken(),  
131 - new TypeReference<List<RuleMetaData>>() {  
132 - });  
133 - Assert.assertNotNull(foundRules);  
134 - Assert.assertEquals(1, foundRules.size());  
135 - Assert.assertEquals(savedRule, foundRules.get(0));  
136 - }  
137 -  
138 - @Test  
139 - public void testActivateRule() throws Exception {  
140 - RuleMetaData rule = createRuleMetaData(tenantPlugin);  
141 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
142 -  
143 - doPost("/api/rule/" + savedRule.getId().getId().toString() + "/activate").andExpect(status().isBadRequest());  
144 -  
145 - doPost("/api/plugin/" + tenantPlugin.getId().getId().toString() + "/activate").andExpect(status().isOk());  
146 -  
147 - doPost("/api/rule/" + savedRule.getId().getId().toString() + "/activate").andExpect(status().isOk());  
148 - }  
149 -  
150 - @Test  
151 - public void testSuspendRule() throws Exception {  
152 - RuleMetaData rule = createRuleMetaData(tenantPlugin);  
153 - RuleMetaData savedRule = doPost("/api/rule", rule, RuleMetaData.class);  
154 -  
155 - doPost("/api/plugin/" + tenantPlugin.getId().getId().toString() + "/activate").andExpect(status().isOk());  
156 - doPost("/api/rule/" + savedRule.getId().getId().toString() + "/activate").andExpect(status().isOk());  
157 - doPost("/api/rule/" + savedRule.getId().getId().toString() + "/suspend").andExpect(status().isOk());  
158 - }  
159 -  
160 - @Test  
161 - public void testFindSystemRules() throws Exception {  
162 - loginSysAdmin();  
163 - List<RuleMetaData> rules = testRulesCreation("/api/rule/system", sysPlugin);  
164 - for (RuleMetaData rule : rules) {  
165 - doDelete("/api/rule/" + rule.getId().getId()).andExpect(status().isOk());  
166 - }  
167 - loginTenantAdmin();  
168 - }  
169 -  
170 - @Test  
171 - public void testFindCurrentTenantPlugins() throws Exception {  
172 - List<RuleMetaData> rules = testRulesCreation("/api/rule", tenantPlugin);  
173 - for (RuleMetaData rule : rules) {  
174 - doDelete("/api/rule/" + rule.getId().getId()).andExpect(status().isOk());  
175 - }  
176 - }  
177 -  
178 - @Test  
179 - public void testFindTenantPlugins() throws Exception {  
180 - List<RuleMetaData> rules = testRulesCreation("/api/rule", tenantPlugin);  
181 - loginSysAdmin();  
182 - List<RuleMetaData> loadedRules = new ArrayList<>();  
183 - TextPageLink pageLink = new TextPageLink(3);  
184 - TextPageData<RuleMetaData> pageData;  
185 - do {  
186 - pageData = doGetTypedWithPageLink("/api/rule/tenant/" + savedTenant.getId().getId().toString() + "?",  
187 - new TypeReference<TextPageData<RuleMetaData>>() {  
188 - }, pageLink);  
189 - loadedRules.addAll(pageData.getData());  
190 - if (pageData.hasNext()) {  
191 - pageLink = pageData.getNextPageLink();  
192 - }  
193 - } while (pageData.hasNext());  
194 -  
195 - Collections.sort(rules, idComparator);  
196 - Collections.sort(loadedRules, idComparator);  
197 -  
198 - Assert.assertEquals(rules, loadedRules);  
199 -  
200 - for (RuleMetaData rule : rules) {  
201 - doDelete("/api/rule/" + rule.getId().getId()).andExpect(status().isOk());  
202 - }  
203 - }  
204 -  
205 - private List<RuleMetaData> testRulesCreation(String url, PluginMetaData plugin) throws Exception {  
206 - List<RuleMetaData> rules = new ArrayList<>();  
207 - for (int i = 0; i < 6; i++) {  
208 - RuleMetaData rule = createRuleMetaData(plugin);  
209 - rule.setPluginToken(plugin.getApiToken());  
210 - rule.setName(rule.getName() + i);  
211 - rules.add(doPost("/api/rule", rule, RuleMetaData.class));  
212 - }  
213 -  
214 - List<RuleMetaData> loadedRules = new ArrayList<>();  
215 - TextPageLink pageLink = new TextPageLink(3);  
216 - TextPageData<RuleMetaData> pageData;  
217 - do {  
218 - pageData = doGetTypedWithPageLink(url + "?",  
219 - new TypeReference<TextPageData<RuleMetaData>>() {  
220 - }, pageLink);  
221 - loadedRules.addAll(pageData.getData());  
222 - if (pageData.hasNext()) {  
223 - pageLink = pageData.getNextPageLink();  
224 - }  
225 - } while (pageData.hasNext());  
226 -  
227 - loadedRules = loadedRules.stream().filter(p -> !p.getName().equals("System Telemetry Rule")).collect(Collectors.toList());  
228 -  
229 - Collections.sort(rules, idComparator);  
230 - Collections.sort(loadedRules, idComparator);  
231 -  
232 - Assert.assertEquals(rules, loadedRules);  
233 - return loadedRules;  
234 - }  
235 -  
236 - public static RuleMetaData createRuleMetaData(PluginMetaData plugin) throws IOException {  
237 - RuleMetaData rule = new RuleMetaData();  
238 - rule.setName("My Rule");  
239 - rule.setPluginToken(plugin.getApiToken());  
240 - rule.setFilters(mapper.readTree("[{\"clazz\":\"org.thingsboard.server.extensions.core.filter.MsgTypeFilter\", " +  
241 - "\"name\":\"TelemetryFilter\", " +  
242 - "\"configuration\": {\"messageTypes\":[\"POST_TELEMETRY\",\"POST_ATTRIBUTES\",\"GET_ATTRIBUTES\"]}}]"));  
243 - rule.setAction(mapper.readTree("{\"clazz\":\"org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction\", \"name\":\"TelemetryMsgConverterAction\", " +  
244 - "\"configuration\":{\"timeUnit\":\"DAYS\", \"ttlValue\":1}}"));  
245 - return rule;  
246 - }  
247 -}  
@@ -80,6 +80,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC @@ -80,6 +80,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC
80 } 80 }
81 } 81 }
82 82
  83 + @Ignore
83 @Test 84 @Test
84 public void testServerMqttOneWayRpc() throws Exception { 85 public void testServerMqttOneWayRpc() throws Exception {
85 Device device = new Device(); 86 Device device = new Device();
@@ -106,6 +107,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC @@ -106,6 +107,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC
106 Assert.assertTrue(StringUtils.isEmpty(result)); 107 Assert.assertTrue(StringUtils.isEmpty(result));
107 } 108 }
108 109
  110 + @Ignore
109 @Test 111 @Test
110 public void testServerMqttOneWayRpcDeviceOffline() throws Exception { 112 public void testServerMqttOneWayRpcDeviceOffline() throws Exception {
111 Device device = new Device(); 113 Device device = new Device();
@@ -24,7 +24,8 @@ import java.util.Arrays; @@ -24,7 +24,8 @@ import java.util.Arrays;
24 24
25 @RunWith(ClasspathSuite.class) 25 @RunWith(ClasspathSuite.class)
26 @ClasspathSuite.ClassnameFilters({ 26 @ClasspathSuite.ClassnameFilters({
27 - "org.thingsboard.server.rules.flow.*Test"}) 27 + "org.thingsboard.server.rules.flow.*Test",
  28 + "org.thingsboard.server.rules.lifecycle.*Test"})
28 public class RuleEngineSqlTestSuite { 29 public class RuleEngineSqlTestSuite {
29 30
30 @ClassRule 31 @ClassRule
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.rules.flow; 16 package org.thingsboard.server.rules.flow;
17 17
18 import com.datastax.driver.core.utils.UUIDs; 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import com.fasterxml.jackson.databind.JsonNode;
19 import lombok.Data; 20 import lombok.Data;
20 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
21 import org.junit.After; 22 import org.junit.After;
@@ -28,6 +29,7 @@ import org.thingsboard.server.actors.service.ActorService; @@ -28,6 +29,7 @@ import org.thingsboard.server.actors.service.ActorService;
28 import org.thingsboard.server.common.data.*; 29 import org.thingsboard.server.common.data.*;
29 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; 30 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
30 import org.thingsboard.server.common.data.kv.StringDataEntry; 31 import org.thingsboard.server.common.data.kv.StringDataEntry;
  32 +import org.thingsboard.server.common.data.page.TextPageLink;
31 import org.thingsboard.server.common.data.page.TimePageData; 33 import org.thingsboard.server.common.data.page.TimePageData;
32 import org.thingsboard.server.common.data.rule.RuleChain; 34 import org.thingsboard.server.common.data.rule.RuleChain;
33 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 35 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
@@ -40,6 +42,7 @@ import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; @@ -40,6 +42,7 @@ import org.thingsboard.server.controller.AbstractRuleEngineControllerTest;
40 import org.thingsboard.server.dao.attributes.AttributesService; 42 import org.thingsboard.server.dao.attributes.AttributesService;
41 import org.thingsboard.server.dao.rule.RuleChainService; 43 import org.thingsboard.server.dao.rule.RuleChainService;
42 44
  45 +import java.io.IOException;
43 import java.util.Arrays; 46 import java.util.Arrays;
44 import java.util.Collections; 47 import java.util.Collections;
45 48
@@ -60,9 +63,6 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule @@ -60,9 +63,6 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
60 @Autowired 63 @Autowired
61 protected AttributesService attributesService; 64 protected AttributesService attributesService;
62 65
63 - @Autowired  
64 - protected RuleChainService ruleChainService;  
65 -  
66 @Before 66 @Before
67 public void beforeTest() throws Exception { 67 public void beforeTest() throws Exception {
68 loginSysAdmin(); 68 loginSysAdmin();
@@ -71,6 +71,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule @@ -71,6 +71,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
71 tenant.setTitle("My tenant"); 71 tenant.setTitle("My tenant");
72 savedTenant = doPost("/api/tenant", tenant, Tenant.class); 72 savedTenant = doPost("/api/tenant", tenant, Tenant.class);
73 Assert.assertNotNull(savedTenant); 73 Assert.assertNotNull(savedTenant);
  74 + ruleChainService.deleteRuleChainsByTenantId(savedTenant.getId());
74 75
75 tenantAdmin = new User(); 76 tenantAdmin = new User();
76 tenantAdmin.setAuthority(Authority.TENANT_ADMIN); 77 tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
@@ -166,7 +167,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule @@ -166,7 +167,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
166 Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId()); 167 Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId());
167 Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); 168 Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText());
168 169
169 - Assert.assertEquals("serverAttributeValue1", outEvent.getBody().get("metadata").get("ss.serverAttributeKey1").asText()); 170 + Assert.assertEquals("serverAttributeValue1", getMetadata(outEvent).get("ss_serverAttributeKey1").asText());
170 171
171 RuleChain finalRuleChain = ruleChain; 172 RuleChain finalRuleChain = ruleChain;
172 RuleNode lastRuleNode = metaData.getNodes().stream().filter(node -> !node.getId().equals(finalRuleChain.getFirstRuleNodeId())).findFirst().get(); 173 RuleNode lastRuleNode = metaData.getNodes().stream().filter(node -> !node.getId().equals(finalRuleChain.getFirstRuleNodeId())).findFirst().get();
@@ -183,8 +184,8 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule @@ -183,8 +184,8 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
183 Assert.assertEquals(lastRuleNode.getId(), outEvent.getEntityId()); 184 Assert.assertEquals(lastRuleNode.getId(), outEvent.getEntityId());
184 Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); 185 Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText());
185 186
186 - Assert.assertEquals("serverAttributeValue1", outEvent.getBody().get("metadata").get("ss.serverAttributeKey1").asText());  
187 - Assert.assertEquals("serverAttributeValue2", outEvent.getBody().get("metadata").get("ss.serverAttributeKey2").asText()); 187 + Assert.assertEquals("serverAttributeValue1", getMetadata(outEvent).get("ss_serverAttributeKey1").asText());
  188 + Assert.assertEquals("serverAttributeValue2", getMetadata(outEvent).get("ss_serverAttributeKey2").asText());
188 } 189 }
189 190
190 } 191 }
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.rules.lifecycle; 16 package org.thingsboard.server.rules.lifecycle;
17 17
18 import com.datastax.driver.core.utils.UUIDs; 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import com.fasterxml.jackson.databind.JsonNode;
19 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
20 import org.junit.After; 21 import org.junit.After;
21 import org.junit.Assert; 22 import org.junit.Assert;
@@ -42,6 +43,7 @@ import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; @@ -42,6 +43,7 @@ import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
42 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; 43 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest;
43 import org.thingsboard.server.dao.attributes.AttributesService; 44 import org.thingsboard.server.dao.attributes.AttributesService;
44 45
  46 +import java.io.IOException;
45 import java.util.Collections; 47 import java.util.Collections;
46 48
47 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 49 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -69,6 +71,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac @@ -69,6 +71,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac
69 tenant.setTitle("My tenant"); 71 tenant.setTitle("My tenant");
70 savedTenant = doPost("/api/tenant", tenant, Tenant.class); 72 savedTenant = doPost("/api/tenant", tenant, Tenant.class);
71 Assert.assertNotNull(savedTenant); 73 Assert.assertNotNull(savedTenant);
  74 + ruleChainService.deleteRuleChainsByTenantId(savedTenant.getId());
72 75
73 tenantAdmin = new User(); 76 tenantAdmin = new User();
74 tenantAdmin.setAuthority(Authority.TENANT_ADMIN); 77 tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
@@ -152,7 +155,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac @@ -152,7 +155,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac
152 Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId()); 155 Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId());
153 Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText()); 156 Assert.assertEquals(device.getId().getId().toString(), outEvent.getBody().get("entityId").asText());
154 157
155 - Assert.assertEquals("serverAttributeValue", outEvent.getBody().get("metadata").get("ss.serverAttributeKey").asText()); 158 + Assert.assertEquals("serverAttributeValue", getMetadata(outEvent).get("ss_serverAttributeKey").asText());
156 } 159 }
157 160
158 } 161 }
@@ -35,5 +35,4 @@ public class SystemSqlTestSuite { @@ -35,5 +35,4 @@ public class SystemSqlTestSuite {
35 "sql/drop-all-tables.sql", 35 "sql/drop-all-tables.sql",
36 "sql-test.properties"); 36 "sql-test.properties");
37 37
38 -  
39 } 38 }
common/data/src/main/java/org/thingsboard/server/common/data/rpc/RpcRequest.java renamed from extensions-core/src/main/java/org/thingsboard/server/extensions/core/plugin/rpc/cmd/RpcRequest.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.extensions.core.plugin.rpc.cmd; 16 +package org.thingsboard.server.common.data.rpc;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 19
common/data/src/main/java/org/thingsboard/server/common/data/rpc/ToDeviceRpcRequestBody.java renamed from extensions-api/src/main/java/org/thingsboard/server/extensions/api/plugins/msg/ToDeviceRpcRequestBody.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.extensions.api.plugins.msg; 16 +package org.thingsboard.server.common.data.rpc;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 19
@@ -22,6 +22,7 @@ import lombok.EqualsAndHashCode; @@ -22,6 +22,7 @@ import lombok.EqualsAndHashCode;
22 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
23 import org.thingsboard.server.common.data.HasName; 23 import org.thingsboard.server.common.data.HasName;
24 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; 24 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
  25 +import org.thingsboard.server.common.data.id.RuleChainId;
25 import org.thingsboard.server.common.data.id.RuleNodeId; 26 import org.thingsboard.server.common.data.id.RuleNodeId;
26 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
27 28
@@ -32,6 +33,7 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl @@ -32,6 +33,7 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
32 33
33 private static final long serialVersionUID = -5656679015121235465L; 34 private static final long serialVersionUID = -5656679015121235465L;
34 35
  36 + private RuleChainId ruleChainId;
35 private String type; 37 private String type;
36 private String name; 38 private String name;
37 private boolean debugMode; 39 private boolean debugMode;
@@ -49,8 +51,10 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl @@ -49,8 +51,10 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
49 51
50 public RuleNode(RuleNode ruleNode) { 52 public RuleNode(RuleNode ruleNode) {
51 super(ruleNode); 53 super(ruleNode);
  54 + this.ruleChainId = ruleNode.getRuleChainId();
52 this.type = ruleNode.getType(); 55 this.type = ruleNode.getType();
53 this.name = ruleNode.getName(); 56 this.name = ruleNode.getName();
  57 + this.debugMode = ruleNode.isDebugMode();
54 this.setConfiguration(ruleNode.getConfiguration()); 58 this.setConfiguration(ruleNode.getConfiguration());
55 } 59 }
56 60
@@ -18,27 +18,30 @@ package org.thingsboard.server.common.msg; @@ -18,27 +18,30 @@ package org.thingsboard.server.common.msg;
18 /** 18 /**
19 * Created by ashvayka on 15.03.18. 19 * Created by ashvayka on 15.03.18.
20 */ 20 */
  21 +//TODO: add all "See" references
21 public enum MsgType { 22 public enum MsgType {
22 23
23 /** 24 /**
  25 + * ADDED/UPDATED/DELETED events for server nodes.
  26 + *
  27 + * See {@link org.thingsboard.server.common.msg.cluster.ClusterEventMsg}
  28 + */
  29 + CLUSTER_EVENT_MSG,
  30 +
  31 + /**
24 * ADDED/UPDATED/DELETED events for main entities. 32 * ADDED/UPDATED/DELETED events for main entities.
25 * 33 *
26 - * @See {@link org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg} 34 + * See {@link org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg}
27 */ 35 */
28 COMPONENT_LIFE_CYCLE_MSG, 36 COMPONENT_LIFE_CYCLE_MSG,
29 37
30 /** 38 /**
31 * Misc messages from the REST API/SERVICE layer to the new rule engine. 39 * Misc messages from the REST API/SERVICE layer to the new rule engine.
32 * 40 *
33 - * @See {@link org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg} 41 + * See {@link org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg}
34 */ 42 */
35 SERVICE_TO_RULE_ENGINE_MSG, 43 SERVICE_TO_RULE_ENGINE_MSG,
36 44
37 -  
38 - SESSION_TO_DEVICE_ACTOR_MSG,  
39 - DEVICE_ACTOR_TO_SESSION_MSG,  
40 -  
41 -  
42 /** 45 /**
43 * Message that is sent by RuleChainActor to RuleActor with command to process TbMsg. 46 * Message that is sent by RuleChainActor to RuleActor with command to process TbMsg.
44 */ 47 */
@@ -59,4 +62,31 @@ public enum MsgType { @@ -59,4 +62,31 @@ public enum MsgType {
59 */ 62 */
60 RULE_TO_SELF_MSG, 63 RULE_TO_SELF_MSG,
61 64
  65 + /**
  66 + * Message that is sent by Session Actor to Device Actor. Represents messages from the device itself.
  67 + */
  68 + DEVICE_SESSION_TO_DEVICE_ACTOR_MSG,
  69 +
  70 + DEVICE_ATTRIBUTES_UPDATE_TO_DEVICE_ACTOR_MSG,
  71 +
  72 + DEVICE_CREDENTIALS_UPDATE_TO_DEVICE_ACTOR_MSG,
  73 +
  74 + DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG,
  75 +
  76 + DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG,
  77 +
  78 + DEVICE_ACTOR_RPC_TIMEOUT_MSG,
  79 +
  80 + DEVICE_ACTOR_QUEUE_TIMEOUT_MSG,
  81 +
  82 + /**
  83 + * Message that is sent from the Device Actor to Rule Engine. Requires acknowledgement
  84 + */
  85 + DEVICE_ACTOR_TO_RULE_ENGINE_MSG,
  86 +
  87 + /**
  88 + * Message that is sent from Rule Engine to the Device Actor when message is successfully pushed to queue.
  89 + */
  90 + RULE_ENGINE_QUEUE_PUT_ACK_MSG;
  91 +
62 } 92 }
@@ -31,10 +31,10 @@ import java.util.concurrent.ConcurrentHashMap; @@ -31,10 +31,10 @@ import java.util.concurrent.ConcurrentHashMap;
31 @NoArgsConstructor 31 @NoArgsConstructor
32 public final class TbMsgMetaData implements Serializable { 32 public final class TbMsgMetaData implements Serializable {
33 33
34 - private Map<String, String> data = new ConcurrentHashMap<>(); 34 + private final Map<String, String> data = new ConcurrentHashMap<>();
35 35
36 public TbMsgMetaData(Map<String, String> data) { 36 public TbMsgMetaData(Map<String, String> data) {
37 - this.data = data; 37 + this.data.putAll(data);
38 } 38 }
39 39
40 public String getValue(String key) { 40 public String getValue(String key) {
@@ -16,14 +16,20 @@ @@ -16,14 +16,20 @@
16 package org.thingsboard.server.common.msg.cluster; 16 package org.thingsboard.server.common.msg.cluster;
17 17
18 import lombok.Data; 18 import lombok.Data;
  19 +import org.thingsboard.server.common.msg.MsgType;
  20 +import org.thingsboard.server.common.msg.TbActorMsg;
19 21
20 /** 22 /**
21 * @author Andrew Shvayka 23 * @author Andrew Shvayka
22 */ 24 */
23 @Data 25 @Data
24 -public final class ClusterEventMsg { 26 +public final class ClusterEventMsg implements TbActorMsg {
25 27
26 private final ServerAddress serverAddress; 28 private final ServerAddress serverAddress;
27 private final boolean added; 29 private final boolean added;
28 30
  31 + @Override
  32 + public MsgType getMsgType() {
  33 + return MsgType.CLUSTER_EVENT_MSG;
  34 + }
29 } 35 }
@@ -16,14 +16,14 @@ @@ -16,14 +16,14 @@
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 import org.thingsboard.server.common.msg.session.FromDeviceMsg; 18 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
19 -import org.thingsboard.server.common.msg.session.MsgType; 19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
20 20
21 /** 21 /**
22 * @author Andrew Shvayka 22 * @author Andrew Shvayka
23 */ 23 */
24 public class AttributesSubscribeMsg implements FromDeviceMsg { 24 public class AttributesSubscribeMsg implements FromDeviceMsg {
25 @Override 25 @Override
26 - public MsgType getMsgType() {  
27 - return MsgType.SUBSCRIBE_ATTRIBUTES_REQUEST; 26 + public SessionMsgType getMsgType() {
  27 + return SessionMsgType.SUBSCRIBE_ATTRIBUTES_REQUEST;
28 } 28 }
29 } 29 }
@@ -16,14 +16,15 @@ @@ -16,14 +16,15 @@
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 import org.thingsboard.server.common.msg.session.FromDeviceMsg; 18 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
19 -import org.thingsboard.server.common.msg.session.MsgType; 19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
20 21
21 /** 22 /**
22 * @author Andrew Shvayka 23 * @author Andrew Shvayka
23 */ 24 */
24 public class AttributesUnsubscribeMsg implements FromDeviceMsg { 25 public class AttributesUnsubscribeMsg implements FromDeviceMsg {
25 @Override 26 @Override
26 - public MsgType getMsgType() {  
27 - return MsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST; 27 + public SessionMsgType getMsgType() {
  28 + return SessionMsgType.UNSUBSCRIBE_ATTRIBUTES_REQUEST;
28 } 29 }
29 } 30 }
@@ -17,7 +17,8 @@ package org.thingsboard.server.common.msg.core; @@ -17,7 +17,8 @@ package org.thingsboard.server.common.msg.core;
17 17
18 import lombok.ToString; 18 import lombok.ToString;
19 import org.thingsboard.server.common.msg.kv.AttributesKVMsg; 19 import org.thingsboard.server.common.msg.kv.AttributesKVMsg;
20 -import org.thingsboard.server.common.msg.session.MsgType; 20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  21 +import org.thingsboard.server.common.msg.session.SessionMsgType;
21 import org.thingsboard.server.common.msg.session.ToDeviceMsg; 22 import org.thingsboard.server.common.msg.session.ToDeviceMsg;
22 23
23 @ToString 24 @ToString
@@ -36,9 +37,8 @@ public class AttributesUpdateNotification implements ToDeviceMsg { @@ -36,9 +37,8 @@ public class AttributesUpdateNotification implements ToDeviceMsg {
36 return true; 37 return true;
37 } 38 }
38 39
39 - @Override  
40 - public MsgType getMsgType() {  
41 - return MsgType.ATTRIBUTES_UPDATE_NOTIFICATION; 40 + public SessionMsgType getSessionMsgType() {
  41 + return SessionMsgType.ATTRIBUTES_UPDATE_NOTIFICATION;
42 } 42 }
43 43
44 public AttributesKVMsg getData() { 44 public AttributesKVMsg getData() {
common/message/src/main/java/org/thingsboard/server/common/msg/core/AttributesUpdateRequest.java renamed from common/message/src/main/java/org/thingsboard/server/common/msg/core/UpdateAttributesRequest.java
@@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; @@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
21 import org.thingsboard.server.common.msg.session.FromDeviceMsg; 21 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
22 import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg; 22 import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg;
23 23
24 -public interface UpdateAttributesRequest extends FromDeviceRequestMsg { 24 +public interface AttributesUpdateRequest extends FromDeviceRequestMsg {
25 25
26 Set<AttributeKvEntry> getAttributes(); 26 Set<AttributeKvEntry> getAttributes();
27 27
common/message/src/main/java/org/thingsboard/server/common/msg/core/BasicAttributesUpdateRequest.java renamed from common/message/src/main/java/org/thingsboard/server/common/msg/core/BasicUpdateAttributesRequest.java
@@ -20,19 +20,19 @@ import java.util.LinkedHashSet; @@ -20,19 +20,19 @@ import java.util.LinkedHashSet;
20 import java.util.Set; 20 import java.util.Set;
21 21
22 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 22 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
23 -import org.thingsboard.server.common.msg.session.MsgType; 23 +import org.thingsboard.server.common.msg.session.SessionMsgType;
24 24
25 -public class BasicUpdateAttributesRequest extends BasicRequest implements UpdateAttributesRequest { 25 +public class BasicAttributesUpdateRequest extends BasicRequest implements AttributesUpdateRequest {
26 26
27 private static final long serialVersionUID = 1L; 27 private static final long serialVersionUID = 1L;
28 28
29 private final Set<AttributeKvEntry> data; 29 private final Set<AttributeKvEntry> data;
30 30
31 - public BasicUpdateAttributesRequest() { 31 + public BasicAttributesUpdateRequest() {
32 this(DEFAULT_REQUEST_ID); 32 this(DEFAULT_REQUEST_ID);
33 } 33 }
34 34
35 - public BasicUpdateAttributesRequest(Integer requestId) { 35 + public BasicAttributesUpdateRequest(Integer requestId) {
36 super(requestId); 36 super(requestId);
37 this.data = new LinkedHashSet<>(); 37 this.data = new LinkedHashSet<>();
38 } 38 }
@@ -46,8 +46,8 @@ public class BasicUpdateAttributesRequest extends BasicRequest implements Update @@ -46,8 +46,8 @@ public class BasicUpdateAttributesRequest extends BasicRequest implements Update
46 } 46 }
47 47
48 @Override 48 @Override
49 - public MsgType getMsgType() {  
50 - return MsgType.POST_ATTRIBUTES_REQUEST; 49 + public SessionMsgType getMsgType() {
  50 + return SessionMsgType.POST_ATTRIBUTES_REQUEST;
51 } 51 }
52 52
53 @Override 53 @Override
@@ -57,7 +57,7 @@ public class BasicUpdateAttributesRequest extends BasicRequest implements Update @@ -57,7 +57,7 @@ public class BasicUpdateAttributesRequest extends BasicRequest implements Update
57 57
58 @Override 58 @Override
59 public String toString() { 59 public String toString() {
60 - return "BasicUpdateAttributesRequest [data=" + data + "]"; 60 + return "BasicAttributesUpdateRequest [data=" + data + "]";
61 } 61 }
62 62
63 } 63 }
@@ -15,26 +15,27 @@ @@ -15,26 +15,27 @@
15 */ 15 */
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 -import org.thingsboard.server.common.msg.session.MsgType; 18 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
19 20
20 public class BasicCommandAckResponse extends BasicResponseMsg<Integer> implements StatusCodeResponse { 21 public class BasicCommandAckResponse extends BasicResponseMsg<Integer> implements StatusCodeResponse {
21 22
22 private static final long serialVersionUID = 1L; 23 private static final long serialVersionUID = 1L;
23 24
24 - public static BasicCommandAckResponse onSuccess(MsgType requestMsgType, Integer requestId) { 25 + public static BasicCommandAckResponse onSuccess(SessionMsgType requestMsgType, Integer requestId) {
25 return BasicCommandAckResponse.onSuccess(requestMsgType, requestId, 200); 26 return BasicCommandAckResponse.onSuccess(requestMsgType, requestId, 200);
26 } 27 }
27 28
28 - public static BasicCommandAckResponse onSuccess(MsgType requestMsgType, Integer requestId, Integer code) { 29 + public static BasicCommandAckResponse onSuccess(SessionMsgType requestMsgType, Integer requestId, Integer code) {
29 return new BasicCommandAckResponse(requestMsgType, requestId, true, null, code); 30 return new BasicCommandAckResponse(requestMsgType, requestId, true, null, code);
30 } 31 }
31 32
32 - public static BasicCommandAckResponse onError(MsgType requestMsgType, Integer requestId, Exception error) { 33 + public static BasicCommandAckResponse onError(SessionMsgType requestMsgType, Integer requestId, Exception error) {
33 return new BasicCommandAckResponse(requestMsgType, requestId, false, error, null); 34 return new BasicCommandAckResponse(requestMsgType, requestId, false, error, null);
34 } 35 }
35 36
36 - private BasicCommandAckResponse(MsgType requestMsgType, Integer requestId, boolean success, Exception error, Integer code) {  
37 - super(requestMsgType, requestId, MsgType.TO_DEVICE_RPC_RESPONSE_ACK, success, error, code); 37 + private BasicCommandAckResponse(SessionMsgType requestMsgType, Integer requestId, boolean success, Exception error, Integer code) {
  38 + super(requestMsgType, requestId, SessionMsgType.TO_DEVICE_RPC_RESPONSE_ACK, success, error, code);
38 } 39 }
39 40
40 @Override 41 @Override
@@ -16,7 +16,8 @@ @@ -16,7 +16,8 @@
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 import lombok.ToString; 18 import lombok.ToString;
19 -import org.thingsboard.server.common.msg.session.MsgType; 19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
20 21
21 import java.util.Collections; 22 import java.util.Collections;
22 import java.util.Optional; 23 import java.util.Optional;
@@ -41,8 +42,8 @@ public class BasicGetAttributesRequest extends BasicRequest implements GetAttrib @@ -41,8 +42,8 @@ public class BasicGetAttributesRequest extends BasicRequest implements GetAttrib
41 } 42 }
42 43
43 @Override 44 @Override
44 - public MsgType getMsgType() {  
45 - return MsgType.GET_ATTRIBUTES_REQUEST; 45 + public SessionMsgType getMsgType() {
  46 + return SessionMsgType.GET_ATTRIBUTES_REQUEST;
46 } 47 }
47 48
48 @Override 49 @Override
@@ -17,23 +17,24 @@ package org.thingsboard.server.common.msg.core; @@ -17,23 +17,24 @@ package org.thingsboard.server.common.msg.core;
17 17
18 import lombok.ToString; 18 import lombok.ToString;
19 import org.thingsboard.server.common.msg.kv.AttributesKVMsg; 19 import org.thingsboard.server.common.msg.kv.AttributesKVMsg;
20 -import org.thingsboard.server.common.msg.session.MsgType; 20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  21 +import org.thingsboard.server.common.msg.session.SessionMsgType;
21 22
22 @ToString 23 @ToString
23 public class BasicGetAttributesResponse extends BasicResponseMsg<AttributesKVMsg> implements GetAttributesResponse { 24 public class BasicGetAttributesResponse extends BasicResponseMsg<AttributesKVMsg> implements GetAttributesResponse {
24 25
25 private static final long serialVersionUID = 1L; 26 private static final long serialVersionUID = 1L;
26 27
27 - public static BasicGetAttributesResponse onSuccess(MsgType requestMsgType, int requestId, AttributesKVMsg code) { 28 + public static BasicGetAttributesResponse onSuccess(SessionMsgType requestMsgType, int requestId, AttributesKVMsg code) {
28 return new BasicGetAttributesResponse(requestMsgType, requestId, true, null, code); 29 return new BasicGetAttributesResponse(requestMsgType, requestId, true, null, code);
29 } 30 }
30 31
31 - public static BasicGetAttributesResponse onError(MsgType requestMsgType, int requestId, Exception error) { 32 + public static BasicGetAttributesResponse onError(SessionMsgType requestMsgType, int requestId, Exception error) {
32 return new BasicGetAttributesResponse(requestMsgType, requestId, false, error, null); 33 return new BasicGetAttributesResponse(requestMsgType, requestId, false, error, null);
33 } 34 }
34 35
35 - private BasicGetAttributesResponse(MsgType requestMsgType, int requestId, boolean success, Exception error, AttributesKVMsg code) {  
36 - super(requestMsgType, requestId, MsgType.GET_ATTRIBUTES_RESPONSE, success, error, code); 36 + private BasicGetAttributesResponse(SessionMsgType requestMsgType, int requestId, boolean success, Exception error, AttributesKVMsg code) {
  37 + super(requestMsgType, requestId, SessionMsgType.GET_ATTRIBUTES_RESPONSE, success, error, code);
37 } 38 }
38 39
39 } 40 }
@@ -18,32 +18,33 @@ package org.thingsboard.server.common.msg.core; @@ -18,32 +18,33 @@ package org.thingsboard.server.common.msg.core;
18 import java.io.Serializable; 18 import java.io.Serializable;
19 import java.util.Optional; 19 import java.util.Optional;
20 20
21 -import org.thingsboard.server.common.msg.session.MsgType; 21 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  22 +import org.thingsboard.server.common.msg.session.SessionMsgType;
22 23
23 24
24 public class BasicResponseMsg<T extends Serializable> implements ResponseMsg<T> { 25 public class BasicResponseMsg<T extends Serializable> implements ResponseMsg<T> {
25 26
26 private static final long serialVersionUID = 1L; 27 private static final long serialVersionUID = 1L;
27 28
28 - private final MsgType requestMsgType; 29 + private final SessionMsgType requestMsgType;
29 private final Integer requestId; 30 private final Integer requestId;
30 - private final MsgType msgType; 31 + private final SessionMsgType sessionMsgType;
31 private final boolean success; 32 private final boolean success;
32 private final T data; 33 private final T data;
33 private final Exception error; 34 private final Exception error;
34 35
35 - protected BasicResponseMsg(MsgType requestMsgType, Integer requestId, MsgType msgType, boolean success, Exception error, T data) { 36 + protected BasicResponseMsg(SessionMsgType requestMsgType, Integer requestId, SessionMsgType sessionMsgType, boolean success, Exception error, T data) {
36 super(); 37 super();
37 this.requestMsgType = requestMsgType; 38 this.requestMsgType = requestMsgType;
38 this.requestId = requestId; 39 this.requestId = requestId;
39 - this.msgType = msgType; 40 + this.sessionMsgType = sessionMsgType;
40 this.success = success; 41 this.success = success;
41 this.error = error; 42 this.error = error;
42 this.data = data; 43 this.data = data;
43 } 44 }
44 45
45 @Override 46 @Override
46 - public MsgType getRequestMsgType() { 47 + public SessionMsgType getRequestMsgType() {
47 return requestMsgType; 48 return requestMsgType;
48 } 49 }
49 50
@@ -72,8 +73,7 @@ public class BasicResponseMsg<T extends Serializable> implements ResponseMsg<T> @@ -72,8 +73,7 @@ public class BasicResponseMsg<T extends Serializable> implements ResponseMsg<T>
72 return "BasicResponseMsg [success=" + success + ", data=" + data + ", error=" + error + "]"; 73 return "BasicResponseMsg [success=" + success + ", data=" + data + ", error=" + error + "]";
73 } 74 }
74 75
75 - @Override  
76 - public MsgType getMsgType() {  
77 - return msgType; 76 + public SessionMsgType getSessionMsgType() {
  77 + return sessionMsgType;
78 } 78 }
79 } 79 }
@@ -16,26 +16,27 @@ @@ -16,26 +16,27 @@
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 import lombok.ToString; 18 import lombok.ToString;
19 -import org.thingsboard.server.common.msg.session.MsgType; 19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
20 21
21 @ToString 22 @ToString
22 public class BasicStatusCodeResponse extends BasicResponseMsg<Integer> implements StatusCodeResponse { 23 public class BasicStatusCodeResponse extends BasicResponseMsg<Integer> implements StatusCodeResponse {
23 24
24 private static final long serialVersionUID = 1L; 25 private static final long serialVersionUID = 1L;
25 26
26 - public static BasicStatusCodeResponse onSuccess(MsgType requestMsgType, Integer requestId) { 27 + public static BasicStatusCodeResponse onSuccess(SessionMsgType requestMsgType, Integer requestId) {
27 return BasicStatusCodeResponse.onSuccess(requestMsgType, requestId, 0); 28 return BasicStatusCodeResponse.onSuccess(requestMsgType, requestId, 0);
28 } 29 }
29 30
30 - public static BasicStatusCodeResponse onSuccess(MsgType requestMsgType, Integer requestId, Integer code) { 31 + public static BasicStatusCodeResponse onSuccess(SessionMsgType requestMsgType, Integer requestId, Integer code) {
31 return new BasicStatusCodeResponse(requestMsgType, requestId, true, null, code); 32 return new BasicStatusCodeResponse(requestMsgType, requestId, true, null, code);
32 } 33 }
33 34
34 - public static BasicStatusCodeResponse onError(MsgType requestMsgType, Integer requestId, Exception error) { 35 + public static BasicStatusCodeResponse onError(SessionMsgType requestMsgType, Integer requestId, Exception error) {
35 return new BasicStatusCodeResponse(requestMsgType, requestId, false, error, null); 36 return new BasicStatusCodeResponse(requestMsgType, requestId, false, error, null);
36 } 37 }
37 38
38 - private BasicStatusCodeResponse(MsgType requestMsgType, Integer requestId, boolean success, Exception error, Integer code) {  
39 - super(requestMsgType, requestId, MsgType.STATUS_CODE_RESPONSE, success, error, code); 39 + private BasicStatusCodeResponse(SessionMsgType requestMsgType, Integer requestId, boolean success, Exception error, Integer code) {
  40 + super(requestMsgType, requestId, SessionMsgType.STATUS_CODE_RESPONSE, success, error, code);
40 } 41 }
41 } 42 }
@@ -21,7 +21,8 @@ import java.util.List; @@ -21,7 +21,8 @@ import java.util.List;
21 import java.util.Map; 21 import java.util.Map;
22 22
23 import org.thingsboard.server.common.data.kv.KvEntry; 23 import org.thingsboard.server.common.data.kv.KvEntry;
24 -import org.thingsboard.server.common.msg.session.MsgType; 24 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  25 +import org.thingsboard.server.common.msg.session.SessionMsgType;
25 26
26 public class BasicTelemetryUploadRequest extends BasicRequest implements TelemetryUploadRequest { 27 public class BasicTelemetryUploadRequest extends BasicRequest implements TelemetryUploadRequest {
27 28
@@ -48,8 +49,8 @@ public class BasicTelemetryUploadRequest extends BasicRequest implements Telemet @@ -48,8 +49,8 @@ public class BasicTelemetryUploadRequest extends BasicRequest implements Telemet
48 } 49 }
49 50
50 @Override 51 @Override
51 - public MsgType getMsgType() {  
52 - return MsgType.POST_TELEMETRY_REQUEST; 52 + public SessionMsgType getMsgType() {
  53 + return SessionMsgType.POST_TELEMETRY_REQUEST;
53 } 54 }
54 55
55 @Override 56 @Override
@@ -18,12 +18,12 @@ package org.thingsboard.server.common.msg.core; @@ -18,12 +18,12 @@ package org.thingsboard.server.common.msg.core;
18 import java.io.Serializable; 18 import java.io.Serializable;
19 import java.util.Optional; 19 import java.util.Optional;
20 20
21 -import org.thingsboard.server.common.msg.session.MsgType; 21 +import org.thingsboard.server.common.msg.session.SessionMsgType;
22 import org.thingsboard.server.common.msg.session.ToDeviceMsg; 22 import org.thingsboard.server.common.msg.session.ToDeviceMsg;
23 23
24 public interface ResponseMsg<T extends Serializable> extends ToDeviceMsg { 24 public interface ResponseMsg<T extends Serializable> extends ToDeviceMsg {
25 25
26 - MsgType getRequestMsgType(); 26 + SessionMsgType getRequestMsgType();
27 27
28 Integer getRequestId(); 28 Integer getRequestId();
29 29
@@ -16,14 +16,15 @@ @@ -16,14 +16,15 @@
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 import org.thingsboard.server.common.msg.session.FromDeviceMsg; 18 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
19 -import org.thingsboard.server.common.msg.session.MsgType; 19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
20 21
21 /** 22 /**
22 * @author Andrew Shvayka 23 * @author Andrew Shvayka
23 */ 24 */
24 public class RpcSubscribeMsg implements FromDeviceMsg { 25 public class RpcSubscribeMsg implements FromDeviceMsg {
25 @Override 26 @Override
26 - public MsgType getMsgType() {  
27 - return MsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST; 27 + public SessionMsgType getMsgType() {
  28 + return SessionMsgType.SUBSCRIBE_RPC_COMMANDS_REQUEST;
28 } 29 }
29 } 30 }
@@ -16,14 +16,15 @@ @@ -16,14 +16,15 @@
16 package org.thingsboard.server.common.msg.core; 16 package org.thingsboard.server.common.msg.core;
17 17
18 import org.thingsboard.server.common.msg.session.FromDeviceMsg; 18 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
19 -import org.thingsboard.server.common.msg.session.MsgType; 19 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  20 +import org.thingsboard.server.common.msg.session.SessionMsgType;
20 21
21 /** 22 /**
22 * @author Andrew Shvayka 23 * @author Andrew Shvayka
23 */ 24 */
24 public class RpcUnsubscribeMsg implements FromDeviceMsg { 25 public class RpcUnsubscribeMsg implements FromDeviceMsg {
25 @Override 26 @Override
26 - public MsgType getMsgType() {  
27 - return MsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST; 27 + public SessionMsgType getMsgType() {
  28 + return SessionMsgType.UNSUBSCRIBE_RPC_COMMANDS_REQUEST;
28 } 29 }
29 } 30 }
@@ -21,7 +21,7 @@ package org.thingsboard.server.common.msg.core; @@ -21,7 +21,7 @@ package org.thingsboard.server.common.msg.core;
21 21
22 public enum RuleEngineError { 22 public enum RuleEngineError {
23 23
24 - NO_RULES, NO_ACTIVE_RULES, NO_FILTERS_MATCHED, NO_REQUEST_FROM_ACTIONS, NO_TWO_WAY_ACTIONS, NO_RESPONSE_FROM_ACTIONS, PLUGIN_TIMEOUT(true); 24 + QUEUE_PUT_TIMEOUT(true), SERVER_ERROR(true);
25 25
26 private final boolean critical; 26 private final boolean critical;
27 27