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 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 18 export LOG_FILENAME=${pkg.name}.out
19 19 export LOADER_PATH=${pkg.installFolder}/conf,${pkg.installFolder}/extensions
20 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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
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   -}
\ No newline at end of file
  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 61 import org.thingsboard.server.service.component.ComponentDiscoveryService;
62 62 import org.thingsboard.server.service.executors.DbCallbackExecutorService;
63 63 import org.thingsboard.server.service.mail.MailExecutorService;
  64 +import org.thingsboard.server.service.rpc.DeviceRpcService;
64 65 import org.thingsboard.server.service.script.JsExecutorService;
65 66 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
66 67
... ... @@ -163,6 +164,10 @@ public class ActorSystemContext {
163 164
164 165 @Autowired
165 166 @Getter
  167 + private DeviceRpcService deviceRpcService;
  168 +
  169 + @Autowired
  170 + @Getter
166 171 @Setter
167 172 private PluginWebSocketMsgEndpoint wsMsgEndpoint;
168 173
... ... @@ -186,17 +191,13 @@ public class ActorSystemContext {
186 191 @Getter
187 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 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 199 @Getter
199   - private long pluginErrorPersistFrequency;
  200 + private long queuePersistenceTimeout;
200 201
201 202 @Value("${actors.rule.chain.error_persist_frequency}")
202 203 @Getter
... ... @@ -206,14 +207,6 @@ public class ActorSystemContext {
206 207 @Getter
207 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 210 @Value("${actors.statistics.enabled}")
218 211 @Getter
219 212 private boolean statisticsEnabled;
... ...
... ... @@ -29,13 +29,12 @@ import org.thingsboard.server.actors.shared.plugin.SystemPluginManager;
29 29 import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager;
30 30 import org.thingsboard.server.actors.tenant.TenantActor;
31 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 32 import org.thingsboard.server.common.data.id.TenantId;
35 33 import org.thingsboard.server.common.data.page.PageDataIterable;
36 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 38 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
40 39 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
41 40 import org.thingsboard.server.dao.model.ModelConstants;
... ... @@ -90,12 +89,22 @@ public class AppActor extends RuleChainManagerActor {
90 89 @Override
91 90 protected boolean process(TbActorMsg msg) {
92 91 switch (msg.getMsgType()) {
  92 + case CLUSTER_EVENT_MSG:
  93 + broadcast(msg);
  94 + break;
93 95 case COMPONENT_LIFE_CYCLE_MSG:
94 96 onComponentLifecycleMsg((ComponentLifecycleMsg) msg);
95 97 break;
96 98 case SERVICE_TO_RULE_ENGINE_MSG:
97 99 onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg);
98 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 108 default:
100 109 return false;
101 110 }
... ... @@ -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 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 128 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
156 129 ActorRef target;
157 130 if (SYSTEM_TENANT.equals(msg.getTenantId())) {
... ... @@ -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 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 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 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 24 import org.thingsboard.server.common.data.id.TenantId;
25 25 import org.thingsboard.server.common.msg.TbActorMsg;
26 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 30 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
29   -import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg;
30 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 35 public class DeviceActor extends ContextAwareActor {
36 36
37 37 private final LoggingAdapter logger = Logging.getLogger(getContext().system(), this);
38 38
39   - private final TenantId tenantId;
40   - private final DeviceId deviceId;
41 39 private final DeviceActorMessageProcessor processor;
42 40
43 41 private DeviceActor(ActorSystemContext systemContext, TenantId tenantId, DeviceId deviceId) {
44 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 46 @Override
51 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 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 59 processor.processCredentialsUpdate();
70   - } else if (msg instanceof DeviceNameOrTypeUpdateMsg){
  60 + break;
  61 + case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG:
71 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 82 public static class ActorCreator extends ContextBasedCreator<DeviceActor> {
... ...
... ... @@ -18,29 +18,75 @@ package org.thingsboard.server.actors.device;
18 18 import akka.actor.ActorContext;
19 19 import akka.actor.ActorRef;
20 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 28 import org.thingsboard.server.actors.ActorSystemContext;
22 29 import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor;
23 30 import org.thingsboard.server.common.data.DataConstants;
24 31 import org.thingsboard.server.common.data.Device;
25 32 import org.thingsboard.server.common.data.id.DeviceId;
26 33 import org.thingsboard.server.common.data.id.SessionId;
  34 +import org.thingsboard.server.common.data.id.TenantId;
27 35 import org.thingsboard.server.common.data.kv.AttributeKey;
28 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 42 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
30 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 62 import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg;
  63 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
34 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 68 import org.thingsboard.server.common.msg.session.SessionType;
37 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 72 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
40 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 90 import java.util.concurrent.ExecutionException;
45 91 import java.util.concurrent.TimeoutException;
46 92 import java.util.function.Consumer;
... ... @@ -52,46 +98,43 @@ import java.util.stream.Collectors;
52 98 */
53 99 public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
54 100
  101 + private final TenantId tenantId;
55 102 private final DeviceId deviceId;
56 103 private final Map<SessionId, SessionInfo> sessions;
57 104 private final Map<SessionId, SessionInfo> attributeSubscriptions;
58 105 private final Map<SessionId, SessionInfo> rpcSubscriptions;
59   -
60 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 111 private int rpcSeq = 0;
63 112 private String deviceName;
64 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 117 super(systemContext, logger);
  118 + this.tenantId = tenantId;
69 119 this.deviceId = deviceId;
70 120 this.sessions = new HashMap<>();
71 121 this.attributeSubscriptions = new HashMap<>();
72 122 this.rpcSubscriptions = new HashMap<>();
73 123 this.rpcPendingMap = new HashMap<>();
  124 + this.pendingMsgs = new HashMap<>();
74 125 initAttributes();
75 126 }
76 127
77 128 private void initAttributes() {
78   - //TODO: add invalidation of deviceType cache.
79 129 Device device = systemContext.getDeviceService().findDeviceById(deviceId);
80 130 this.deviceName = device.getName();
81 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 138 ToDeviceRpcRequest request = msg.getMsg();
96 139 ToDeviceRpcRequestBody body = request.getBody();
97 140 ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg(
... ... @@ -118,9 +161,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
118 161 syncSessionSet.forEach(rpcSubscriptions::remove);
119 162
120 163 if (request.isOneway() && sent) {
121   - ToPluginRpcResponseDeviceMsg responsePluginMsg = toPluginRpcResponseMsg(msg, (String) null);
122   - context.parent().tell(responsePluginMsg, ActorRef.noSender());
123 164 logger.debug("[{}] Rpc command response sent [{}]!", deviceId, request.getId());
  165 + systemContext.getDeviceRpcService().process(new FromDeviceRpcResponse(msg.getMsg().getId(), null, null));
124 166 } else {
125 167 registerPendingRpcRequest(context, msg, sent, rpcRequest, timeout);
126 168 }
... ... @@ -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 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 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 184 ToDeviceRpcRequestMetadata requestMd = rpcPendingMap.remove(msg.getId());
143 185 if (requestMd != null) {
144 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 233 ToDeviceRpcRequestBody body = request.getBody();
174 234 if (request.isOneway()) {
175 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 238 ToDeviceRpcRequestMsg rpcRequest = new ToDeviceRpcRequestMsg(
180 239 entry.getKey(),
... ... @@ -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 249 processSubscriptionCommands(context, msg);
191 250 processRpcResponses(context, msg);
192 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 361 void processAttributesUpdate(ActorContext context, DeviceAttributesEventNotificationMsg msg) {
196   - refreshAttributes(msg);
197 362 if (attributeSubscriptions.size() > 0) {
198 363 ToDeviceMsg notification = null;
199 364 if (msg.isDeleted()) {
... ... @@ -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 392 SessionId sessionId = msg.getSessionId();
241 393 FromDeviceMsg inMsg = msg.getPayload();
242   - if (inMsg.getMsgType() == MsgType.TO_DEVICE_RPC_RESPONSE) {
  394 + if (inMsg.getMsgType() == SessionMsgType.TO_DEVICE_RPC_RESPONSE) {
243 395 logger.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId);
244 396 ToDeviceRpcResponseMsg responseMsg = (ToDeviceRpcResponseMsg) inMsg;
245 397 ToDeviceRpcRequestMetadata requestMd = rpcPendingMap.remove(responseMsg.getRequestId());
246 398 boolean success = requestMd != null;
247 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 401 } else {
258 402 logger.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
259 403 }
260 404 if (msg.getSessionType() == SessionType.SYNC) {
261 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 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 414 if (!msg.isAdded()) {
271 415 logger.debug("[{}] Clearing attributes/rpc subscription for server [{}]", deviceId, msg.getServerAddress());
272 416 Predicate<Map.Entry<SessionId, SessionInfo>> filter = e -> e.getValue().getServer()
... ... @@ -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 424 SessionId sessionId = msg.getSessionId();
313 425 SessionType sessionType = msg.getSessionType();
314 426 FromDeviceMsg inMsg = msg.getPayload();
315   - if (inMsg.getMsgType() == MsgType.SUBSCRIBE_ATTRIBUTES_REQUEST) {
  427 + if (inMsg.getMsgType() == SessionMsgType.SUBSCRIBE_ATTRIBUTES_REQUEST) {
316 428 logger.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId);
317 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 431 logger.debug("[{}] Canceling attributes subscription for session [{}]", deviceId, sessionId);
320 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 434 logger.debug("[{}] Registering rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType);
323 435 rpcSubscriptions.put(sessionId, new SessionInfo(sessionType, msg.getServerAddress()));
324 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 438 logger.debug("[{}] Canceling rpc subscription for session [{}][{}]", deviceId, sessionId, sessionType);
327 439 rpcSubscriptions.remove(sessionId);
328 440 }
329 441 }
330 442
331   - private void processSessionStateMsgs(ToDeviceActorMsg msg) {
  443 + private void processSessionStateMsgs(DeviceToDeviceActorMsg msg) {
332 444 SessionId sessionId = msg.getSessionId();
333 445 FromDeviceMsg inMsg = msg.getPayload();
334 446 if (inMsg instanceof SessionOpenMsg) {
... ... @@ -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 468 sessions.forEach((k, v) -> {
367 469 sendMsgToSessionActor(new BasicToDeviceSessionActorMsg(new SessionCloseNotification(), k), v.getServer());
368 470 });
... ... @@ -370,8 +472,12 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
370 472 rpcSubscriptions.clear();
371 473 }
372 474
373   - public void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) {
  475 + void processNameOrTypeUpdate(DeviceNameOrTypeUpdateMsg msg) {
374 476 this.deviceName = msg.getDeviceName();
375 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 13 * See the License for the specific language governing permissions and
14 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 13 * See the License for the specific language governing permissions and
14 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 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 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 13 * See the License for the specific language governing permissions and
14 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 16 package org.thingsboard.server.actors.device;
17 17
18 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 22 * @author Andrew Shvayka
23 23 */
24 24 @Data
25 25 public class ToDeviceRpcRequestMetadata {
26   - private final ToDeviceRpcRequestPluginMsg msg;
  26 + private final ToDeviceRpcRequestMsg msg;
27 27 private final boolean sent;
28 28 }
... ...
... ... @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.id.TenantId;
26 26 import org.thingsboard.server.common.msg.TbActorMsg;
27 27 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
28 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 30 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg;
31 31 import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg;
32 32 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
... ... @@ -153,6 +153,7 @@ public class PluginActor extends ComponentActor<PluginId, PluginActorMessageProc
153 153
154 154 @Override
155 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 30 import org.thingsboard.server.common.msg.cluster.ServerAddress;
31 31 import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse;
32 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 35 import org.thingsboard.server.extensions.api.plugins.Plugin;
35 36 import org.thingsboard.server.extensions.api.plugins.PluginInitializationException;
36 37 import org.thingsboard.server.extensions.api.plugins.msg.FromDeviceRpcResponse;
37 38 import org.thingsboard.server.extensions.api.plugins.msg.ResponsePluginToRuleMsg;
38 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 41 import org.thingsboard.server.extensions.api.plugins.rest.PluginRestMsg;
41 42 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
42 43 import org.thingsboard.server.extensions.api.plugins.ws.msg.PluginWebsocketMsg;
... ... @@ -108,7 +109,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId>
108 109 } catch (Exception ex) {
109 110 logger.debug("[{}] Failed to process RuleToPlugin msg: [{}] [{}]", tenantId, msg.getMsg(), ex);
110 111 RuleToPluginMsg ruleMsg = msg.getMsg();
111   - MsgType responceMsgType = MsgType.RULE_ENGINE_ERROR;
  112 + SessionMsgType responceMsgType = SessionMsgType.RULE_ENGINE_ERROR;
112 113 Integer requestId = 0;
113 114 if (ruleMsg.getPayload() instanceof FromDeviceRequestMsg) {
114 115 requestId = ((FromDeviceRequestMsg) ruleMsg.getPayload()).getRequestId();
... ... @@ -216,7 +217,7 @@ public class PluginActorMessageProcessor extends ComponentMsgProcessor<PluginId>
216 217 @Override
217 218 public void onStop(ActorContext context) {
218 219 onStop();
219   - scheduleMsgWithDelay(context, new PluginTerminationMsg(entityId), systemContext.getPluginActorTerminationDelay());
  220 +// scheduleMsgWithDelay(context, new PluginTerminationMsg(entityId), systemContext.getPluginActorTerminationDelay());
220 221 }
221 222
222 223 private void onStop() {
... ...
... ... @@ -36,9 +36,12 @@ import org.thingsboard.server.common.data.page.TextPageLink;
36 36 import org.thingsboard.server.common.data.plugin.PluginMetaData;
37 37 import org.thingsboard.server.common.data.relation.EntityRelation;
38 38 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
  39 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
39 40 import org.thingsboard.server.common.data.rule.RuleChain;
40 41 import org.thingsboard.server.common.data.rule.RuleMetaData;
41 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 45 import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotificationMsg;
43 46 import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext;
44 47 import org.thingsboard.server.extensions.api.plugins.PluginCallback;
... ... @@ -348,7 +351,7 @@ public final class PluginProcessingContext implements PluginContext {
348 351 throw new IllegalStateException("Not Implemented!");
349 352 }
350 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 369 } else if (ctx.isCustomerUser() && !device.getCustomerId().equals(ctx.getCustomerId())) {
367 370 return ValidationResult.accessDenied("Device doesn't belong to the current Customer!");
368 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 390 } else if (ctx.isCustomerUser() && !asset.getCustomerId().equals(ctx.getCustomerId())) {
388 391 return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!");
389 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 411 } else if (ctx.isSystemAdmin() && !rule.getTenantId().isNullUid()) {
409 412 return ValidationResult.accessDenied("Rule is not in system scope!");
410 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 432 } else if (ctx.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) {
430 433 return ValidationResult.accessDenied("Rule chain is not in system scope!");
431 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 454 } else if (ctx.isSystemAdmin() && !plugin.getTenantId().isNullUid()) {
452 455 return ValidationResult.accessDenied("Plugin is not in system scope!");
453 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 475 } else if (ctx.isCustomerUser() && !customer.getId().equals(ctx.getCustomerId())) {
473 476 return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!");
474 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 486 if (ctx.isCustomerUser()) {
484 487 callback.onSuccess(this, ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
485 488 } else if (ctx.isSystemAdmin()) {
486   - callback.onSuccess(this, ValidationResult.ok());
  489 + callback.onSuccess(this, ValidationResult.ok(null));
487 490 } else {
488 491 ListenableFuture<Tenant> tenantFuture = pluginCtx.tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
489 492 Futures.addCallback(tenantFuture, getCallback(callback, tenant -> {
... ... @@ -492,7 +495,7 @@ public final class PluginProcessingContext implements PluginContext {
492 495 } else if (!tenant.getId().equals(ctx.getTenantId())) {
493 496 return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!");
494 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 18 import akka.actor.ActorRef;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.thingsboard.server.actors.ActorSystemContext;
21   -import org.thingsboard.server.common.data.Device;
22 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 23 import org.thingsboard.server.common.data.id.TenantId;
25 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 27 import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
27   -import org.thingsboard.server.common.data.id.PluginId;
28 28 import org.thingsboard.server.dao.asset.AssetService;
29 29 import org.thingsboard.server.dao.attributes.AttributesService;
30 30 import org.thingsboard.server.dao.audit.AuditLogService;
... ... @@ -37,9 +37,6 @@ import org.thingsboard.server.dao.rule.RuleService;
37 37 import org.thingsboard.server.dao.tenant.TenantService;
38 38 import org.thingsboard.server.dao.timeseries.TimeseriesService;
39 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 40 import org.thingsboard.server.service.cluster.routing.ClusterRoutingService;
44 41 import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;
45 42 import scala.concurrent.duration.Duration;
... ... @@ -108,8 +105,8 @@ public final class SharedPluginProcessingContext {
108 105
109 106 public void sendRpcRequest(ToDeviceRpcRequest msg) {
110 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 112 private <T> void forward(DeviceId deviceId, T msg, BiConsumer<ServerAddress, T> rpcFunction) {
... ...
... ... @@ -20,29 +20,30 @@ import lombok.Data;
20 20
21 21 @Data
22 22 @AllArgsConstructor
23   -public class ValidationResult {
  23 +public class ValidationResult<V> {
24 24
25 25 private final ValidationResultCode resultCode;
26 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 24 import org.thingsboard.server.common.data.id.DeviceId;
25 25 import org.thingsboard.server.common.data.id.PluginId;
26 26 import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
27 28 import org.thingsboard.server.common.msg.cluster.ServerAddress;
28 29 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
29 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 33 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
32 34 import org.thingsboard.server.extensions.api.plugins.msg.*;
33 35 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
... ... @@ -35,6 +37,7 @@ import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg;
35 37 import org.thingsboard.server.gen.cluster.ClusterAPIProtos;
36 38 import org.thingsboard.server.service.cluster.rpc.GrpcSession;
37 39 import org.thingsboard.server.service.cluster.rpc.GrpcSessionListener;
  40 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
38 41
39 42 import java.io.Serializable;
40 43 import java.util.UUID;
... ... @@ -83,7 +86,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
83 86 @Override
84 87 public void onToDeviceActorRpcMsg(GrpcSession session, ClusterAPIProtos.ToDeviceActorRpcMessage msg) {
85 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 92 @Override
... ... @@ -139,28 +142,20 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
139 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 146 TenantId deviceTenantId = new TenantId(toUUID(msg.getDeviceTenantId()));
148 147 DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId()));
149 148
150 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 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 156 RpcError error = !StringUtils.isEmpty(msg.getError()) ? RpcError.valueOf(msg.getError()) : null;
162 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 161 @SuppressWarnings("unchecked")
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.actors.ruleChain;
18 18 import akka.actor.OneForOneStrategy;
19 19 import akka.actor.SupervisorStrategy;
20 20 import org.thingsboard.server.actors.ActorSystemContext;
  21 +import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg;
21 22 import org.thingsboard.server.actors.service.ComponentActor;
22 23 import org.thingsboard.server.actors.service.ContextBasedCreator;
23 24 import org.thingsboard.server.common.data.id.RuleChainId;
... ... @@ -44,6 +45,9 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe
44 45 case SERVICE_TO_RULE_ENGINE_MSG:
45 46 processor.onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg);
46 47 break;
  48 + case DEVICE_ACTOR_TO_RULE_ENGINE_MSG:
  49 + processor.onDeviceActorToRuleEngineMsg((DeviceActorToRuleEngineMsg) msg);
  50 + break;
47 51 case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG:
48 52 processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg);
49 53 break;
... ...
... ... @@ -20,6 +20,8 @@ import akka.actor.ActorRef;
20 20 import akka.actor.Props;
21 21 import akka.event.LoggingAdapter;
22 22 import org.thingsboard.server.actors.ActorSystemContext;
  23 +import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg;
  24 +import org.thingsboard.server.actors.device.RuleEngineQueuePutAckMsg;
23 25 import org.thingsboard.server.actors.service.DefaultActorService;
24 26 import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
25 27 import org.thingsboard.server.common.data.EntityType;
... ... @@ -58,6 +60,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
58 60
59 61 private RuleNodeId firstId;
60 62 private RuleNodeCtx firstNode;
  63 + private boolean started;
61 64
62 65 RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext
63 66 , LoggingAdapter logger, ActorRef parent, ActorRef self) {
... ... @@ -71,14 +74,19 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
71 74
72 75 @Override
73 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 92 @Override
... ... @@ -113,6 +121,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
113 121 nodeActors.clear();
114 122 nodeRoutes.clear();
115 123 context.stop(self);
  124 + started = false;
116 125 }
117 126
118 127 @Override
... ... @@ -157,6 +166,14 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
157 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 177 void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) {
161 178 checkActive();
162 179 RuleNodeId originator = envelope.getOriginator();
... ... @@ -191,5 +208,4 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
191 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 public abstract class RuleChainManagerActor extends ContextAwareActor {
32 32
33 33 protected final RuleChainManager ruleChainManager;
34   - protected final PluginManager pluginManager;
35 34 protected final RuleChainService ruleChainService;
36 35
37 36 public RuleChainManagerActor(ActorSystemContext systemContext, RuleChainManager ruleChainManager, PluginManager pluginManager) {
38 37 super(systemContext);
39 38 this.ruleChainManager = ruleChainManager;
40   - this.pluginManager = pluginManager;
41 39 this.ruleChainService = systemContext.getRuleChainService();
42 40 }
43 41
44 42 protected void initRuleChains() {
45   - pluginManager.init(this.context());
46 43 ruleChainManager.init(this.context());
47 44 }
48 45
49 46 protected ActorRef getEntityActorRef(EntityId entityId) {
50 47 ActorRef target = null;
51 48 switch (entityId.getEntityType()) {
52   - case PLUGIN:
53   - target = pluginManager.getOrCreateActor(this.context(), (PluginId) entityId);
54   - break;
55 49 case RULE_CHAIN:
56 50 target = ruleChainManager.getOrCreateActor(this.context(), (RuleChainId) entityId);
57 51 break;
58 52 }
59 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 39 import org.thingsboard.server.common.msg.core.ToDeviceSessionActorMsg;
40 40 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
41 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 43 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
44 44 import org.thingsboard.server.extensions.api.device.DeviceCredentialsUpdateNotificationMsg;
45 45 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
... ... @@ -156,7 +156,7 @@ public class DefaultActorService implements ActorService {
156 156 }
157 157
158 158 @Override
159   - public void onMsg(ToDeviceActorMsg msg) {
  159 + public void onMsg(DeviceToDeviceActorMsg msg) {
160 160 log.trace("Processing device rpc msg: {}", msg);
161 161 appActor.tell(msg, ActorRef.noSender());
162 162 }
... ...
... ... @@ -22,12 +22,11 @@ import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
22 22 import org.thingsboard.server.common.msg.cluster.ServerAddress;
23 23 import org.thingsboard.server.common.msg.core.*;
24 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 26 import org.thingsboard.server.common.msg.session.*;
27 27
28 28 import akka.actor.ActorContext;
29 29 import akka.event.LoggingAdapter;
30   -import org.thingsboard.server.common.msg.session.ctrl.*;
31 30 import org.thingsboard.server.common.msg.session.ex.SessionException;
32 31
33 32 import java.util.HashMap;
... ... @@ -37,7 +36,7 @@ import java.util.Optional;
37 36 class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor {
38 37
39 38 private boolean firstMsg = true;
40   - private Map<Integer, ToDeviceActorMsg> pendingMap = new HashMap<>();
  39 + private Map<Integer, DeviceToDeviceActorMsg> pendingMap = new HashMap<>();
41 40 private Optional<ServerAddress> currentTargetServer;
42 41 private boolean subscribedToAttributeUpdates;
43 42 private boolean subscribedToRpcCommands;
... ... @@ -53,7 +52,7 @@ class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor {
53 52 toDeviceMsg(new SessionOpenMsg()).ifPresent(m -> forwardToAppActor(ctx, m));
54 53 firstMsg = false;
55 54 }
56   - ToDeviceActorMsg pendingMsg = toDeviceMsg(msg);
  55 + DeviceToDeviceActorMsg pendingMsg = toDeviceMsg(msg);
57 56 FromDeviceMsg fromDeviceMsg = pendingMsg.getPayload();
58 57 switch (fromDeviceMsg.getMsgType()) {
59 58 case POST_TELEMETRY_REQUEST:
... ... @@ -86,8 +85,8 @@ class ASyncMsgProcessor extends AbstractSessionActorMsgProcessor {
86 85 @Override
87 86 public void processToDeviceMsg(ActorContext context, ToDeviceMsg msg) {
88 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 90 case STATUS_CODE_RESPONSE:
92 91 case GET_ATTRIBUTES_RESPONSE:
93 92 ResponseMsg responseMsg = (ResponseMsg) msg;
... ...
... ... @@ -22,8 +22,8 @@ import org.thingsboard.server.common.data.id.DeviceId;
22 22 import org.thingsboard.server.common.data.id.SessionId;
23 23 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
24 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 27 import org.thingsboard.server.common.msg.session.*;
28 28 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
29 29
... ... @@ -37,7 +37,7 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
37 37
38 38 protected final SessionId sessionId;
39 39 protected SessionContext sessionCtx;
40   - protected ToDeviceActorMsg toDeviceActorMsgPrototype;
  40 + protected DeviceToDeviceActorMsg deviceToDeviceActorMsgPrototype;
41 41
42 42 protected AbstractSessionActorMsgProcessor(ActorSystemContext ctx, LoggingAdapter logger, SessionId sessionId) {
43 43 super(ctx, logger);
... ... @@ -64,29 +64,29 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
64 64
65 65 protected void updateSessionCtx(ToDeviceActorSessionMsg msg, SessionType type) {
66 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 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 78 } else {
79 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 84 Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(toForward.getDeviceId());
85 85 forwardToAppActor(ctx, toForward, address);
86 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 90 Optional<ServerAddress> newAddress = systemContext.getRoutingService().resolveById(toForward.getDeviceId());
91 91 if (!newAddress.equals(oldAddress)) {
92 92 if (newAddress.isPresent()) {
... ... @@ -99,7 +99,7 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
99 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 103 if (address.isPresent()) {
104 104 systemContext.getRpcService().tell(address.get(),
105 105 toForward.toOtherAddress(systemContext.getRoutingService().getCurrentServer()));
... ... @@ -114,6 +114,6 @@ abstract class AbstractSessionActorMsgProcessor extends AbstractContextAwareMsgP
114 114 }
115 115
116 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 20 import org.thingsboard.server.common.data.id.SessionId;
21 21 import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
22 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 24 import org.thingsboard.server.common.msg.session.*;
25 25 import org.thingsboard.server.common.msg.session.ToDeviceActorSessionMsg;
26 26 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
... ... @@ -32,7 +32,7 @@ import akka.event.LoggingAdapter;
32 32 import java.util.Optional;
33 33
34 34 class SyncMsgProcessor extends AbstractSessionActorMsgProcessor {
35   - private ToDeviceActorMsg pendingMsg;
  35 + private DeviceToDeviceActorMsg pendingMsg;
36 36 private Optional<ServerAddress> currentTargetServer;
37 37 private boolean pendingResponse;
38 38
... ...
... ... @@ -17,10 +17,9 @@ package org.thingsboard.server.actors.tenant;
17 17
18 18 import akka.actor.ActorRef;
19 19 import akka.actor.Props;
20   -import akka.event.Logging;
21   -import akka.event.LoggingAdapter;
22 20 import org.thingsboard.server.actors.ActorSystemContext;
23 21 import org.thingsboard.server.actors.device.DeviceActor;
  22 +import org.thingsboard.server.actors.device.DeviceActorToRuleEngineMsg;
24 23 import org.thingsboard.server.actors.plugin.PluginTerminationMsg;
25 24 import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor;
26 25 import org.thingsboard.server.actors.service.ContextBasedCreator;
... ... @@ -30,7 +29,8 @@ import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager;
30 29 import org.thingsboard.server.common.data.id.DeviceId;
31 30 import org.thingsboard.server.common.data.id.TenantId;
32 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 34 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
35 35 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
36 36 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
... ... @@ -64,63 +64,47 @@ public class TenantActor extends RuleChainManagerActor {
64 64 @Override
65 65 protected boolean process(TbActorMsg msg) {
66 66 switch (msg.getMsgType()) {
  67 + case CLUSTER_EVENT_MSG:
  68 + broadcast(msg);
  69 + break;
67 70 case COMPONENT_LIFE_CYCLE_MSG:
68 71 onComponentLifecycleMsg((ComponentLifecycleMsg) msg);
69 72 break;
70 73 case SERVICE_TO_RULE_ENGINE_MSG:
71 74 onServiceToRuleEngineMsg((ServiceToRuleEngineMsg) msg);
72 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 86 default:
74 87 return false;
75 88 }
76 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 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 110 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
... ... @@ -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 119 private ActorRef getOrCreateDeviceActor(DeviceId deviceId) {
141 120 return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId))
142 121 .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), deviceId.toString()));
... ...
... ... @@ -606,7 +606,7 @@ public abstract class BaseController {
606 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 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 15 */
16 16 package org.thingsboard.server.controller;
17 17
  18 +import lombok.extern.slf4j.Slf4j;
18 19 import org.springframework.beans.factory.annotation.Autowired;
19 20 import org.springframework.http.HttpStatus;
20 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 30 import org.thingsboard.server.common.data.Tenant;
  31 +import org.thingsboard.server.common.data.exception.ThingsboardException;
23 32 import org.thingsboard.server.common.data.id.TenantId;
24 33 import org.thingsboard.server.common.data.page.TextPageData;
25 34 import org.thingsboard.server.common.data.page.TextPageLink;
26 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 38 @RestController
30 39 @RequestMapping("/api")
  40 +@Slf4j
31 41 public class TenantController extends BaseController {
32   -
  42 +
  43 + @Autowired
  44 + private InstallScripts installScripts;
  45 +
33 46 @Autowired
34 47 private TenantService tenantService;
35 48
... ... @@ -49,10 +62,15 @@ public class TenantController extends BaseController {
49 62
50 63 @PreAuthorize("hasAuthority('SYS_ADMIN')")
51 64 @RequestMapping(value = "/tenant", method = RequestMethod.POST)
52   - @ResponseBody
  65 + @ResponseBody
53 66 public Tenant saveTenant(@RequestBody Tenant tenant) throws ThingsboardException {
54 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 74 } catch (Exception e) {
57 75 throw handleException(e);
58 76 }
... ... @@ -72,7 +90,7 @@ public class TenantController extends BaseController {
72 90 }
73 91
74 92 @PreAuthorize("hasAuthority('SYS_ADMIN')")
75   - @RequestMapping(value = "/tenants", params = { "limit" }, method = RequestMethod.GET)
  93 + @RequestMapping(value = "/tenants", params = {"limit"}, method = RequestMethod.GET)
76 94 @ResponseBody
77 95 public TextPageData<Tenant> getTenants(@RequestParam int limit,
78 96 @RequestParam(required = false) String textSearch,
... ... @@ -85,5 +103,5 @@ public class TenantController extends BaseController {
85 103 throw handleException(e);
86 104 }
87 105 }
88   -
  106 +
89 107 }
... ...
... ... @@ -131,8 +131,8 @@ public class ThingsboardInstallService {
131 131 systemDataLoaderService.createSysAdmin();
132 132 systemDataLoaderService.createAdminSettings();
133 133 systemDataLoaderService.loadSystemWidgets();
134   - systemDataLoaderService.loadSystemPlugins();
135   - systemDataLoaderService.loadSystemRules();
  134 +// systemDataLoaderService.loadSystemPlugins();
  135 +// systemDataLoaderService.loadSystemRules();
136 136
137 137 if (loadDemo) {
138 138 log.info("Loading demo data...");
... ...
... ... @@ -19,7 +19,6 @@ import com.google.protobuf.ByteString;
19 19 import io.grpc.Server;
20 20 import io.grpc.ServerBuilder;
21 21 import io.grpc.stub.StreamObserver;
22   -import lombok.Setter;
23 22 import lombok.extern.slf4j.Slf4j;
24 23 import org.springframework.beans.factory.annotation.Autowired;
25 24 import org.springframework.stereotype.Service;
... ... @@ -27,29 +26,24 @@ import org.springframework.util.SerializationUtils;
27 26 import org.thingsboard.server.actors.rpc.RpcBroadcastMsg;
28 27 import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg;
29 28 import org.thingsboard.server.actors.rpc.RpcSessionTellMsg;
30   -import org.thingsboard.server.actors.service.ActorService;
31 29 import org.thingsboard.server.common.data.id.EntityId;
32 30 import org.thingsboard.server.common.msg.cluster.ServerAddress;
33 31 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
34 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 34 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
37 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 37 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg;
41 38 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
42 39 import org.thingsboard.server.gen.cluster.ClusterAPIProtos;
43 40 import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc;
44   -import org.thingsboard.server.service.cluster.discovery.DiscoveryService;
45 41 import org.thingsboard.server.service.cluster.discovery.ServerInstance;
46 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 45 import javax.annotation.PreDestroy;
51 46 import java.io.IOException;
52   -import java.util.Set;
53 47 import java.util.UUID;
54 48 import java.util.concurrent.ConcurrentHashMap;
55 49 import java.util.concurrent.ConcurrentMap;
... ... @@ -124,7 +118,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
124 118 }
125 119
126 120 @Override
127   - public void tell(ServerAddress serverAddress, ToDeviceActorMsg toForward) {
  121 + public void tell(ServerAddress serverAddress, DeviceToDeviceActorMsg toForward) {
128 122 ClusterAPIProtos.ToRpcServerMessage msg = ClusterAPIProtos.ToRpcServerMessage.newBuilder()
129 123 .setToDeviceActorRpcMsg(toProtoMsg(toForward)).build();
130 124 tell(serverAddress, msg);
... ... @@ -138,7 +132,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
138 132 }
139 133
140 134 @Override
141   - public void tell(ServerAddress serverAddress, ToDeviceRpcRequestPluginMsg toForward) {
  135 + public void tell(ServerAddress serverAddress, ToDeviceRpcRequestMsg toForward) {
142 136 ClusterAPIProtos.ToRpcServerMessage msg = ClusterAPIProtos.ToRpcServerMessage.newBuilder()
143 137 .setToDeviceRpcRequestRpcMsg(toProtoMsg(toForward)).build();
144 138 tell(serverAddress, msg);
... ... @@ -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 188 return ClusterAPIProtos.ToDeviceActorRpcMessage.newBuilder().setData(
195 189 ByteString.copyFrom(SerializationUtils.serialize(msg))
196 190 ).build();
... ... @@ -202,15 +196,10 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
202 196 ).build();
203 197 }
204 198
205   - private static ClusterAPIProtos.ToDeviceRpcRequestRpcMessage toProtoMsg(ToDeviceRpcRequestPluginMsg msg) {
  199 + private static ClusterAPIProtos.ToDeviceRpcRequestRpcMessage toProtoMsg(ToDeviceRpcRequestMsg msg) {
206 200 ClusterAPIProtos.ToDeviceRpcRequestRpcMessage.Builder builder = ClusterAPIProtos.ToDeviceRpcRequestRpcMessage.newBuilder();
207 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 203 builder.setDeviceTenantId(toUid(msg.getTenantId()));
215 204 builder.setDeviceId(toUid(msg.getDeviceId()));
216 205
... ... @@ -227,11 +216,6 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI
227 216 ClusterAPIProtos.ToPluginRpcResponseRpcMessage.Builder builder = ClusterAPIProtos.ToPluginRpcResponseRpcMessage.newBuilder();
228 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 219 builder.setMsgId(toUid(request.getId()));
236 220 request.getResponse().ifPresent(builder::setResponse);
237 221 request.getError().ifPresent(e -> builder.setError(e.name()));
... ...
... ... @@ -19,12 +19,12 @@ import io.grpc.stub.StreamObserver;
19 19 import org.thingsboard.server.common.msg.cluster.ServerAddress;
20 20 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
21 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 23 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
24   -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequestPluginMsg;
25 24 import org.thingsboard.server.extensions.api.plugins.msg.ToPluginRpcResponseDeviceMsg;
26 25 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
27 26 import org.thingsboard.server.gen.cluster.ClusterAPIProtos;
  27 +import org.thingsboard.server.service.rpc.ToDeviceRpcRequestMsg;
28 28
29 29 import java.util.UUID;
30 30
... ... @@ -35,13 +35,13 @@ public interface ClusterRpcService {
35 35
36 36 void init(RpcMsgListener listener);
37 37
38   - void tell(ServerAddress serverAddress, ToDeviceActorMsg toForward);
  38 + void tell(ServerAddress serverAddress, DeviceToDeviceActorMsg toForward);
39 39
40 40 void tell(ServerAddress serverAddress, ToDeviceSessionActorMsg toForward);
41 41
42 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 46 void tell(ServerAddress serverAddress, ToPluginRpcResponseDeviceMsg toForward);
47 47
... ... @@ -50,4 +50,5 @@ public interface ClusterRpcService {
50 50 void broadcast(ToAllNodesMsg msg);
51 51
52 52 void onSessionCreated(UUID msgUid, StreamObserver<ClusterAPIProtos.ToRpcServerMessage> inputStream);
  53 +
53 54 }
... ...
... ... @@ -20,18 +20,16 @@ import org.thingsboard.server.actors.rpc.RpcSessionCreateRequestMsg;
20 20 import org.thingsboard.server.actors.rpc.RpcSessionTellMsg;
21 21 import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg;
22 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 24 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
25 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 28 * @author Andrew Shvayka
31 29 */
32 30 public interface RpcMsgListener {
33 31
34   - void onMsg(ToDeviceActorMsg msg);
  32 + void onMsg(DeviceToDeviceActorMsg msg);
35 33
36 34 void onMsg(ToDeviceActorNotificationMsg msg);
37 35
... ...
... ... @@ -60,21 +60,12 @@ import java.nio.file.Paths;
60 60 @Slf4j
61 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 63 private static final ObjectMapper objectMapper = new ObjectMapper();
72   - public static final String JSON_EXT = ".json";
73 64 public static final String CUSTOMER_CRED = "customer";
74 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 70 @Autowired
80 71 private BCryptPasswordEncoder passwordEncoder;
... ... @@ -89,15 +80,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
89 80 private WidgetsBundleService widgetsBundleService;
90 81
91 82 @Autowired
92   - private WidgetTypeService widgetTypeService;
93   -
94   - @Autowired
95   - private PluginService pluginService;
96   -
97   - @Autowired
98   - private RuleService ruleService;
99   -
100   - @Autowired
101 83 private TenantService tenantService;
102 84
103 85 @Autowired
... ... @@ -109,9 +91,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
109 91 @Autowired
110 92 private DeviceCredentialsService deviceCredentialsService;
111 93
112   - @Autowired
113   - private DashboardService dashboardService;
114   -
115 94 @Bean
116 95 protected BCryptPasswordEncoder passwordEncoder() {
117 96 return new BCryptPasswordEncoder();
... ... @@ -147,55 +126,12 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
147 126 }
148 127
149 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 129 public void loadDemoData() throws Exception {
195 130 Tenant demoTenant = new Tenant();
196 131 demoTenant.setRegion("Global");
197 132 demoTenant.setTitle("Tenant");
198 133 demoTenant = tenantService.saveTenant(demoTenant);
  134 + installScripts.createDefaultRuleChains(demoTenant.getId());
199 135 createUser(Authority.TENANT_ADMIN, demoTenant.getId(), null, "tenant@thingsboard.org", "tenant");
200 136
201 137 Customer customerA = new Customer();
... ... @@ -227,9 +163,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
227 163 createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " +
228 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 169 @Override
... ... @@ -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 182 private User createUser(Authority authority,
244 183 TenantId tenantId,
245 184 CustomerId customerId,
... ... @@ -282,72 +221,4 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
282 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 23
24 24 void loadSystemWidgets() throws Exception;
25 25
26   - void loadSystemPlugins() throws Exception;
27   -
28   - void loadSystemRules() throws Exception;
29   -
30 26 void loadDemoData() throws Exception;
31 27
32 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 13 * See the License for the specific language governing permissions and
14 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 19 import org.springframework.http.ResponseEntity;
20 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 27 @Data
27 28 public class LocalRequestMetaData {
28 29 private final ToDeviceRpcRequest request;
  30 + private final SecurityUser user;
29 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Getter;
19 19 import lombok.RequiredArgsConstructor;
20 20 import lombok.ToString;
21 21 import org.thingsboard.server.common.data.id.DeviceId;
22   -import org.thingsboard.server.common.data.id.PluginId;
23 22 import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.common.msg.MsgType;
24 24 import org.thingsboard.server.common.msg.cluster.ServerAddress;
  25 +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
25 26 import org.thingsboard.server.extensions.api.device.ToDeviceActorNotificationMsg;
26 27
27 28 import java.util.Optional;
28 29
29 30 /**
30   - * @author Andrew Shvayka
  31 + * Created by ashvayka on 16.04.18.
31 32 */
32 33 @ToString
33 34 @RequiredArgsConstructor
34   -public class ToDeviceRpcRequestPluginMsg implements ToDeviceActorNotificationMsg {
  35 +public class ToDeviceRpcRequestMsg implements ToDeviceActorNotificationMsg {
35 36
36 37 private final ServerAddress serverAddress;
37 38 @Getter
38   - private final PluginId pluginId;
39   - @Getter
40   - private final TenantId pluginTenantId;
41   - @Getter
42 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 45 public Optional<ServerAddress> getServerAddress() {
... ... @@ -58,5 +55,9 @@ public class ToDeviceRpcRequestPluginMsg implements ToDeviceActorNotificationMsg
58 55 public TenantId getTenantId() {
59 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 25 import org.springframework.stereotype.Component;
26 26 import org.springframework.web.context.request.async.DeferredResult;
27 27 import org.thingsboard.server.actors.plugin.ValidationResult;
  28 +import org.thingsboard.server.common.data.BaseData;
28 29 import org.thingsboard.server.common.data.Customer;
29 30 import org.thingsboard.server.common.data.Device;
30 31 import org.thingsboard.server.common.data.Tenant;
... ... @@ -35,8 +36,10 @@ import org.thingsboard.server.common.data.id.DeviceId;
35 36 import org.thingsboard.server.common.data.id.EntityId;
36 37 import org.thingsboard.server.common.data.id.EntityIdFactory;
37 38 import org.thingsboard.server.common.data.id.RuleChainId;
  39 +import org.thingsboard.server.common.data.id.RuleNodeId;
38 40 import org.thingsboard.server.common.data.id.TenantId;
39 41 import org.thingsboard.server.common.data.rule.RuleChain;
  42 +import org.thingsboard.server.common.data.rule.RuleNode;
40 43 import org.thingsboard.server.controller.HttpValidationCallback;
41 44 import org.thingsboard.server.dao.alarm.AlarmService;
42 45 import org.thingsboard.server.dao.asset.AssetService;
... ... @@ -140,7 +143,7 @@ public class AccessValidator {
140 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 147 switch (entityId.getEntityType()) {
145 148 case DEVICE:
146 149 validateDevice(currentUser, entityId, callback);
... ... @@ -177,14 +180,14 @@ public class AccessValidator {
177 180 } else if (currentUser.isCustomerUser() && !device.getCustomerId().equals(currentUser.getCustomerId())) {
178 181 return ValidationResult.accessDenied("Device doesn't belong to the current Customer!");
179 182 } else {
180   - return ValidationResult.ok();
  183 + return ValidationResult.ok(device);
181 184 }
182 185 }
183 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 191 if (currentUser.isSystemAdmin()) {
189 192 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
190 193 } else {
... ... @@ -198,15 +201,14 @@ public class AccessValidator {
198 201 } else if (currentUser.isCustomerUser() && !asset.getCustomerId().equals(currentUser.getCustomerId())) {
199 202 return ValidationResult.accessDenied("Asset doesn't belong to the current Customer!");
200 203 } else {
201   - return ValidationResult.ok();
  204 + return ValidationResult.ok(asset);
202 205 }
203 206 }
204 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 212 if (currentUser.isCustomerUser()) {
211 213 callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
212 214 } else {
... ... @@ -220,14 +222,40 @@ public class AccessValidator {
220 222 } else if (currentUser.isSystemAdmin() && !ruleChain.getTenantId().isNullUid()) {
221 223 return ValidationResult.accessDenied("Rule chain is not in system scope!");
222 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 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 259 if (currentUser.isSystemAdmin()) {
232 260 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
233 261 } else {
... ... @@ -241,18 +269,18 @@ public class AccessValidator {
241 269 } else if (currentUser.isCustomerUser() && !customer.getId().equals(currentUser.getCustomerId())) {
242 270 return ValidationResult.accessDenied("Customer doesn't relate to the currently authorized customer user!");
243 271 } else {
244   - return ValidationResult.ok();
  272 + return ValidationResult.ok(customer);
245 273 }
246 274 }
247 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 280 if (currentUser.isCustomerUser()) {
253 281 callback.onSuccess(ValidationResult.accessDenied(CUSTOMER_USER_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
254 282 } else if (currentUser.isSystemAdmin()) {
255   - callback.onSuccess(ValidationResult.ok());
  283 + callback.onSuccess(ValidationResult.ok(null));
256 284 } else {
257 285 ListenableFuture<Tenant> tenantFuture = tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
258 286 Futures.addCallback(tenantFuture, getCallback(callback, tenant -> {
... ... @@ -261,13 +289,13 @@ public class AccessValidator {
261 289 } else if (!tenant.getId().equals(currentUser.getTenantId())) {
262 290 return ValidationResult.accessDenied("Tenant doesn't relate to the currently authorized user!");
263 291 } else {
264   - return ValidationResult.ok();
  292 + return ValidationResult.ok(tenant);
265 293 }
266 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 299 return new FutureCallback<T>() {
272 300 @Override
273 301 public void onSuccess(@Nullable T result) {
... ...
... ... @@ -61,7 +61,6 @@ message ConnectRpcMessage {
61 61 }
62 62
63 63 message ToDeviceRpcRequestRpcMessage {
64   - PluginAddress address = 1;
65 64 Uid deviceTenantId = 2;
66 65 Uid deviceId = 3;
67 66
... ... @@ -73,8 +72,6 @@ message ToDeviceRpcRequestRpcMessage {
73 72 }
74 73
75 74 message ToPluginRpcResponseRpcMessage {
76   - PluginAddress address = 1;
77   -
78 75 Uid msgId = 2;
79 76 string response = 3;
80 77 string error = 4;
... ...
... ... @@ -207,18 +207,7 @@ actors:
207 207 sync:
208 208 # Default timeout for processing request using synchronous session (HTTP, CoAP) in milliseconds
209 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 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 211 # Specify thread pool size for database request callbacks executor service
223 212 db_callback_thread_pool_size: "${ACTORS_RULE_DB_CALLBACK_THREAD_POOL_SIZE:1}"
224 213 # Specify thread pool size for javascript executor service
... ... @@ -235,6 +224,11 @@ actors:
235 224 # Enable/disable actor statistics
236 225 enabled: "${ACTORS_STATISTICS_ENABLED:true}"
237 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 233 cache:
240 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 16 package org.thingsboard.server.controller;
17 17
18 18 import com.fasterxml.jackson.core.type.TypeReference;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import org.springframework.beans.factory.annotation.Autowired;
19 21 import org.thingsboard.server.common.data.DataConstants;
20 22 import org.thingsboard.server.common.data.Event;
21 23 import org.thingsboard.server.common.data.id.EntityId;
... ... @@ -25,12 +27,18 @@ import org.thingsboard.server.common.data.page.TimePageData;
25 27 import org.thingsboard.server.common.data.page.TimePageLink;
26 28 import org.thingsboard.server.common.data.rule.RuleChain;
27 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 35 * Created by ashvayka on 20.03.18.
31 36 */
32 37 public class AbstractRuleEngineControllerTest extends AbstractControllerTest {
33 38
  39 + @Autowired
  40 + protected RuleChainService ruleChainService;
  41 +
34 42 protected RuleChain saveRuleChain(RuleChain ruleChain) throws Exception {
35 43 return doPost("/api/ruleChain", ruleChain, RuleChain.class);
36 44 }
... ... @@ -53,4 +61,13 @@ public class AbstractRuleEngineControllerTest extends AbstractControllerTest {
53 61 new TypeReference<TimePageData<Event>>() {
54 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 20 import org.junit.Assert;
21 21 import org.junit.Before;
22 22 import org.junit.Test;
  23 +import org.thingsboard.rule.engine.filter.TbJsFilterNode;
23 24 import org.thingsboard.server.common.data.Tenant;
24 25 import org.thingsboard.server.common.data.User;
25 26 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
... ... @@ -35,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
35 36
36 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 40 private Tenant savedTenant;
40 41 private User tenantAdmin;
41 42
... ... @@ -69,38 +70,28 @@ public abstract class BaseComponentDescriptorControllerTest extends AbstractCont
69 70 @Test
70 71 public void testGetByClazz() throws Exception {
71 72 ComponentDescriptor descriptor =
72   - doGet("/api/component/" + TelemetryStoragePlugin.class.getName(), ComponentDescriptor.class);
  73 + doGet("/api/component/" + TbJsFilterNode.class.getName(), ComponentDescriptor.class);
73 74
74 75 Assert.assertNotNull(descriptor);
75 76 Assert.assertNotNull(descriptor.getId());
76 77 Assert.assertNotNull(descriptor.getName());
77 78 Assert.assertEquals(ComponentScope.TENANT, descriptor.getScope());
78   - Assert.assertEquals(ComponentType.PLUGIN, descriptor.getType());
  79 + Assert.assertEquals(ComponentType.FILTER, descriptor.getType());
79 80 Assert.assertEquals(descriptor.getClazz(), descriptor.getClazz());
80 81 }
81 82
82 83 @Test
83 84 public void testGetByType() throws Exception {
84 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 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 92 for (ComponentType type : ComponentType.values()) {
92 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 80 }
81 81 }
82 82
  83 + @Ignore
83 84 @Test
84 85 public void testServerMqttOneWayRpc() throws Exception {
85 86 Device device = new Device();
... ... @@ -106,6 +107,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC
106 107 Assert.assertTrue(StringUtils.isEmpty(result));
107 108 }
108 109
  110 + @Ignore
109 111 @Test
110 112 public void testServerMqttOneWayRpcDeviceOffline() throws Exception {
111 113 Device device = new Device();
... ...
... ... @@ -24,7 +24,8 @@ import java.util.Arrays;
24 24
25 25 @RunWith(ClasspathSuite.class)
26 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 29 public class RuleEngineSqlTestSuite {
29 30
30 31 @ClassRule
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.rules.flow;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import com.fasterxml.jackson.databind.JsonNode;
19 20 import lombok.Data;
20 21 import lombok.extern.slf4j.Slf4j;
21 22 import org.junit.After;
... ... @@ -28,6 +29,7 @@ import org.thingsboard.server.actors.service.ActorService;
28 29 import org.thingsboard.server.common.data.*;
29 30 import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
30 31 import org.thingsboard.server.common.data.kv.StringDataEntry;
  32 +import org.thingsboard.server.common.data.page.TextPageLink;
31 33 import org.thingsboard.server.common.data.page.TimePageData;
32 34 import org.thingsboard.server.common.data.rule.RuleChain;
33 35 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
... ... @@ -40,6 +42,7 @@ import org.thingsboard.server.controller.AbstractRuleEngineControllerTest;
40 42 import org.thingsboard.server.dao.attributes.AttributesService;
41 43 import org.thingsboard.server.dao.rule.RuleChainService;
42 44
  45 +import java.io.IOException;
43 46 import java.util.Arrays;
44 47 import java.util.Collections;
45 48
... ... @@ -60,9 +63,6 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
60 63 @Autowired
61 64 protected AttributesService attributesService;
62 65
63   - @Autowired
64   - protected RuleChainService ruleChainService;
65   -
66 66 @Before
67 67 public void beforeTest() throws Exception {
68 68 loginSysAdmin();
... ... @@ -71,6 +71,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
71 71 tenant.setTitle("My tenant");
72 72 savedTenant = doPost("/api/tenant", tenant, Tenant.class);
73 73 Assert.assertNotNull(savedTenant);
  74 + ruleChainService.deleteRuleChainsByTenantId(savedTenant.getId());
74 75
75 76 tenantAdmin = new User();
76 77 tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
... ... @@ -166,7 +167,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule
166 167 Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId());
167 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 172 RuleChain finalRuleChain = ruleChain;
172 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 184 Assert.assertEquals(lastRuleNode.getId(), outEvent.getEntityId());
184 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 16 package org.thingsboard.server.rules.lifecycle;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import com.fasterxml.jackson.databind.JsonNode;
19 20 import lombok.extern.slf4j.Slf4j;
20 21 import org.junit.After;
21 22 import org.junit.Assert;
... ... @@ -42,6 +43,7 @@ import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
42 43 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest;
43 44 import org.thingsboard.server.dao.attributes.AttributesService;
44 45
  46 +import java.io.IOException;
45 47 import java.util.Collections;
46 48
47 49 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
... ... @@ -69,6 +71,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac
69 71 tenant.setTitle("My tenant");
70 72 savedTenant = doPost("/api/tenant", tenant, Tenant.class);
71 73 Assert.assertNotNull(savedTenant);
  74 + ruleChainService.deleteRuleChainsByTenantId(savedTenant.getId());
72 75
73 76 tenantAdmin = new User();
74 77 tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
... ... @@ -152,7 +155,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac
152 155 Assert.assertEquals(ruleChain.getFirstRuleNodeId(), outEvent.getEntityId());
153 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 35 "sql/drop-all-tables.sql",
36 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 13 * See the License for the specific language governing permissions and
14 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 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 19
... ...
... ... @@ -22,6 +22,7 @@ import lombok.EqualsAndHashCode;
22 22 import lombok.extern.slf4j.Slf4j;
23 23 import org.thingsboard.server.common.data.HasName;
24 24 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
  25 +import org.thingsboard.server.common.data.id.RuleChainId;
25 26 import org.thingsboard.server.common.data.id.RuleNodeId;
26 27 import org.thingsboard.server.common.data.id.TenantId;
27 28
... ... @@ -32,6 +33,7 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
32 33
33 34 private static final long serialVersionUID = -5656679015121235465L;
34 35
  36 + private RuleChainId ruleChainId;
35 37 private String type;
36 38 private String name;
37 39 private boolean debugMode;
... ... @@ -49,8 +51,10 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
49 51
50 52 public RuleNode(RuleNode ruleNode) {
51 53 super(ruleNode);
  54 + this.ruleChainId = ruleNode.getRuleChainId();
52 55 this.type = ruleNode.getType();
53 56 this.name = ruleNode.getName();
  57 + this.debugMode = ruleNode.isDebugMode();
54 58 this.setConfiguration(ruleNode.getConfiguration());
55 59 }
56 60
... ...
... ... @@ -18,27 +18,30 @@ package org.thingsboard.server.common.msg;
18 18 /**
19 19 * Created by ashvayka on 15.03.18.
20 20 */
  21 +//TODO: add all "See" references
21 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 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 36 COMPONENT_LIFE_CYCLE_MSG,
29 37
30 38 /**
31 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 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 46 * Message that is sent by RuleChainActor to RuleActor with command to process TbMsg.
44 47 */
... ... @@ -59,4 +62,31 @@ public enum MsgType {
59 62 */
60 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 31 @NoArgsConstructor
32 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 36 public TbMsgMetaData(Map<String, String> data) {
37   - this.data = data;
  37 + this.data.putAll(data);
38 38 }
39 39
40 40 public String getValue(String key) {
... ...
... ... @@ -16,14 +16,20 @@
16 16 package org.thingsboard.server.common.msg.cluster;
17 17
18 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 23 * @author Andrew Shvayka
22 24 */
23 25 @Data
24   -public final class ClusterEventMsg {
  26 +public final class ClusterEventMsg implements TbActorMsg {
25 27
26 28 private final ServerAddress serverAddress;
27 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 16 package org.thingsboard.server.common.msg.core;
17 17
18 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 22 * @author Andrew Shvayka
23 23 */
24 24 public class AttributesSubscribeMsg implements FromDeviceMsg {
25 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 16 package org.thingsboard.server.common.msg.core;
17 17
18 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 23 * @author Andrew Shvayka
23 24 */
24 25 public class AttributesUnsubscribeMsg implements FromDeviceMsg {
25 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 17
18 18 import lombok.ToString;
19 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 import org.thingsboard.server.common.msg.session.ToDeviceMsg;
22 23
23 24 @ToString
... ... @@ -36,9 +37,8 @@ public class AttributesUpdateNotification implements ToDeviceMsg {
36 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 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 21 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
22 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 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 20 import java.util.Set;
21 21
22 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 27 private static final long serialVersionUID = 1L;
28 28
29 29 private final Set<AttributeKvEntry> data;
30 30
31   - public BasicUpdateAttributesRequest() {
  31 + public BasicAttributesUpdateRequest() {
32 32 this(DEFAULT_REQUEST_ID);
33 33 }
34 34
35   - public BasicUpdateAttributesRequest(Integer requestId) {
  35 + public BasicAttributesUpdateRequest(Integer requestId) {
36 36 super(requestId);
37 37 this.data = new LinkedHashSet<>();
38 38 }
... ... @@ -46,8 +46,8 @@ public class BasicUpdateAttributesRequest extends BasicRequest implements Update
46 46 }
47 47
48 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 53 @Override
... ... @@ -57,7 +57,7 @@ public class BasicUpdateAttributesRequest extends BasicRequest implements Update
57 57
58 58 @Override
59 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 15 */
16 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 21 public class BasicCommandAckResponse extends BasicResponseMsg<Integer> implements StatusCodeResponse {
21 22
22 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 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 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 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 41 @Override
... ...
... ... @@ -16,7 +16,8 @@
16 16 package org.thingsboard.server.common.msg.core;
17 17
18 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 22 import java.util.Collections;
22 23 import java.util.Optional;
... ... @@ -41,8 +42,8 @@ public class BasicGetAttributesRequest extends BasicRequest implements GetAttrib
41 42 }
42 43
43 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 49 @Override
... ...
... ... @@ -17,23 +17,24 @@ package org.thingsboard.server.common.msg.core;
17 17
18 18 import lombok.ToString;
19 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 23 @ToString
23 24 public class BasicGetAttributesResponse extends BasicResponseMsg<AttributesKVMsg> implements GetAttributesResponse {
24 25
25 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 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 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 18 import java.io.Serializable;
19 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 25 public class BasicResponseMsg<T extends Serializable> implements ResponseMsg<T> {
25 26
26 27 private static final long serialVersionUID = 1L;
27 28
28   - private final MsgType requestMsgType;
  29 + private final SessionMsgType requestMsgType;
29 30 private final Integer requestId;
30   - private final MsgType msgType;
  31 + private final SessionMsgType sessionMsgType;
31 32 private final boolean success;
32 33 private final T data;
33 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 37 super();
37 38 this.requestMsgType = requestMsgType;
38 39 this.requestId = requestId;
39   - this.msgType = msgType;
  40 + this.sessionMsgType = sessionMsgType;
40 41 this.success = success;
41 42 this.error = error;
42 43 this.data = data;
43 44 }
44 45
45 46 @Override
46   - public MsgType getRequestMsgType() {
  47 + public SessionMsgType getRequestMsgType() {
47 48 return requestMsgType;
48 49 }
49 50
... ... @@ -72,8 +73,7 @@ public class BasicResponseMsg<T extends Serializable> implements ResponseMsg<T>
72 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 16 package org.thingsboard.server.common.msg.core;
17 17
18 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 22 @ToString
22 23 public class BasicStatusCodeResponse extends BasicResponseMsg<Integer> implements StatusCodeResponse {
23 24
24 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 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 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 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 21 import java.util.Map;
22 22
23 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 27 public class BasicTelemetryUploadRequest extends BasicRequest implements TelemetryUploadRequest {
27 28
... ... @@ -48,8 +49,8 @@ public class BasicTelemetryUploadRequest extends BasicRequest implements Telemet
48 49 }
49 50
50 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 56 @Override
... ...
... ... @@ -18,12 +18,12 @@ package org.thingsboard.server.common.msg.core;
18 18 import java.io.Serializable;
19 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 22 import org.thingsboard.server.common.msg.session.ToDeviceMsg;
23 23
24 24 public interface ResponseMsg<T extends Serializable> extends ToDeviceMsg {
25 25
26   - MsgType getRequestMsgType();
  26 + SessionMsgType getRequestMsgType();
27 27
28 28 Integer getRequestId();
29 29
... ...
... ... @@ -16,14 +16,15 @@
16 16 package org.thingsboard.server.common.msg.core;
17 17
18 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 23 * @author Andrew Shvayka
23 24 */
24 25 public class RpcSubscribeMsg implements FromDeviceMsg {
25 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 16 package org.thingsboard.server.common.msg.core;
17 17
18 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 23 * @author Andrew Shvayka
23 24 */
24 25 public class RpcUnsubscribeMsg implements FromDeviceMsg {
25 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 21
22 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 26 private final boolean critical;
27 27
... ...