Showing
26 changed files
with
532 additions
and
164 deletions
@@ -233,21 +233,6 @@ public class ActorSystemContext { | @@ -233,21 +233,6 @@ public class ActorSystemContext { | ||
233 | @Getter | 233 | @Getter |
234 | private final Config config; | 234 | private final Config config; |
235 | 235 | ||
236 | - @Getter | ||
237 | - private ExecutorService tsCallBackExecutor; | ||
238 | - | ||
239 | - @PostConstruct | ||
240 | - public void initExecutor() { | ||
241 | - tsCallBackExecutor = Executors.newSingleThreadExecutor(); | ||
242 | - } | ||
243 | - | ||
244 | - @PreDestroy | ||
245 | - public void shutdownExecutor() { | ||
246 | - if (tsCallBackExecutor != null) { | ||
247 | - tsCallBackExecutor.shutdownNow(); | ||
248 | - } | ||
249 | - } | ||
250 | - | ||
251 | public ActorSystemContext() { | 236 | public ActorSystemContext() { |
252 | config = ConfigFactory.parseResources(AKKA_CONF_FILE_NAME).withFallback(ConfigFactory.load()); | 237 | config = ConfigFactory.parseResources(AKKA_CONF_FILE_NAME).withFallback(ConfigFactory.load()); |
253 | } | 238 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | 3 | + * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with 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 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * <p> | 7 | + * |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -17,16 +17,10 @@ package org.thingsboard.server.actors.ruleChain; | @@ -17,16 +17,10 @@ package org.thingsboard.server.actors.ruleChain; | ||
17 | 17 | ||
18 | import akka.actor.ActorRef; | 18 | import akka.actor.ActorRef; |
19 | import com.google.common.base.Function; | 19 | import com.google.common.base.Function; |
20 | -import com.google.common.util.concurrent.FutureCallback; | ||
21 | -import com.google.common.util.concurrent.Futures; | ||
22 | -import com.google.common.util.concurrent.ListenableFuture; | ||
23 | import org.thingsboard.rule.engine.api.ListeningExecutor; | 20 | import org.thingsboard.rule.engine.api.ListeningExecutor; |
24 | import org.thingsboard.rule.engine.api.TbContext; | 21 | import org.thingsboard.rule.engine.api.TbContext; |
25 | import org.thingsboard.server.actors.ActorSystemContext; | 22 | import org.thingsboard.server.actors.ActorSystemContext; |
26 | -import org.thingsboard.server.common.data.id.EntityId; | ||
27 | import org.thingsboard.server.common.data.id.RuleNodeId; | 23 | import org.thingsboard.server.common.data.id.RuleNodeId; |
28 | -import org.thingsboard.server.common.data.kv.AttributeKvEntry; | ||
29 | -import org.thingsboard.server.common.data.kv.TsKvEntry; | ||
30 | import org.thingsboard.server.common.msg.TbMsg; | 24 | import org.thingsboard.server.common.msg.TbMsg; |
31 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 25 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
32 | import org.thingsboard.server.dao.alarm.AlarmService; | 26 | import org.thingsboard.server.dao.alarm.AlarmService; |
@@ -41,7 +35,6 @@ import org.thingsboard.server.dao.timeseries.TimeseriesService; | @@ -41,7 +35,6 @@ import org.thingsboard.server.dao.timeseries.TimeseriesService; | ||
41 | import org.thingsboard.server.dao.user.UserService; | 35 | import org.thingsboard.server.dao.user.UserService; |
42 | import scala.concurrent.duration.Duration; | 36 | import scala.concurrent.duration.Duration; |
43 | 37 | ||
44 | -import javax.annotation.Nullable; | ||
45 | import java.util.List; | 38 | import java.util.List; |
46 | import java.util.Set; | 39 | import java.util.Set; |
47 | import java.util.concurrent.TimeUnit; | 40 | import java.util.concurrent.TimeUnit; |
@@ -122,33 +115,6 @@ class DefaultTbContext implements TbContext { | @@ -122,33 +115,6 @@ class DefaultTbContext implements TbContext { | ||
122 | } | 115 | } |
123 | 116 | ||
124 | @Override | 117 | @Override |
125 | - public void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, FutureCallback<Void> callback) { | ||
126 | - saveAndNotify(entityId, ts, 0L, callback); | ||
127 | - } | ||
128 | - | ||
129 | - @Override | ||
130 | - public void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Void> callback) { | ||
131 | - ListenableFuture<List<Void>> saveFuture = mainCtx.getTsService().save(entityId, ts, ttl); | ||
132 | - Futures.addCallback(saveFuture, new FutureCallback<List<Void>>() { | ||
133 | - @Override | ||
134 | - public void onSuccess(@Nullable List<Void> result) { | ||
135 | - mainCtx.getTsSubService().onLocalTimeseriesUpdate(entityId, ts); | ||
136 | - callback.onSuccess(null); | ||
137 | - } | ||
138 | - | ||
139 | - @Override | ||
140 | - public void onFailure(Throwable t) { | ||
141 | - callback.onFailure(t); | ||
142 | - } | ||
143 | - }, mainCtx.getTsCallBackExecutor()); | ||
144 | - } | ||
145 | - | ||
146 | - @Override | ||
147 | - public void saveAndNotify(EntityId entityId, String scope, Set<AttributeKvEntry> attributes, FutureCallback<Void> callback) { | ||
148 | - | ||
149 | - } | ||
150 | - | ||
151 | - @Override | ||
152 | public ListeningExecutor getJsExecutor() { | 118 | public ListeningExecutor getJsExecutor() { |
153 | return mainCtx.getJsExecutor(); | 119 | return mainCtx.getJsExecutor(); |
154 | } | 120 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | 3 | + * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with 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 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * <p> | 7 | + * |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -89,15 +89,15 @@ import java.util.stream.Collectors; | @@ -89,15 +89,15 @@ import java.util.stream.Collectors; | ||
89 | public class TelemetryController extends BaseController { | 89 | public class TelemetryController extends BaseController { |
90 | 90 | ||
91 | @Autowired | 91 | @Autowired |
92 | - private TelemetrySubscriptionService subscriptionService; | ||
93 | - | ||
94 | - @Autowired | ||
95 | private AttributesService attributesService; | 92 | private AttributesService attributesService; |
96 | 93 | ||
97 | @Autowired | 94 | @Autowired |
98 | private TimeseriesService tsService; | 95 | private TimeseriesService tsService; |
99 | 96 | ||
100 | @Autowired | 97 | @Autowired |
98 | + private TelemetrySubscriptionService tsSubService; | ||
99 | + | ||
100 | + @Autowired | ||
101 | private AccessValidator accessValidator; | 101 | private AccessValidator accessValidator; |
102 | 102 | ||
103 | private ExecutorService executor; | 103 | private ExecutorService executor; |
@@ -312,13 +312,11 @@ public class TelemetryController extends BaseController { | @@ -312,13 +312,11 @@ public class TelemetryController extends BaseController { | ||
312 | } | 312 | } |
313 | SecurityUser user = getCurrentUser(); | 313 | SecurityUser user = getCurrentUser(); |
314 | return accessValidator.validateEntityAndCallback(getCurrentUser(), entityIdSrc, (result, entityId) -> { | 314 | return accessValidator.validateEntityAndCallback(getCurrentUser(), entityIdSrc, (result, entityId) -> { |
315 | - ListenableFuture<List<Void>> future = attributesService.save(entityId, scope, attributes); | ||
316 | - Futures.addCallback(future, new FutureCallback<List<Void>>() { | 315 | + tsSubService.saveAndNotify(entityId, scope, attributes, new FutureCallback<Void>() { |
317 | @Override | 316 | @Override |
318 | - public void onSuccess(@Nullable List<Void> tmp) { | 317 | + public void onSuccess(@Nullable Void tmp) { |
319 | logAttributesUpdated(user, entityId, scope, attributes, null); | 318 | logAttributesUpdated(user, entityId, scope, attributes, null); |
320 | result.setResult(new ResponseEntity(HttpStatus.OK)); | 319 | result.setResult(new ResponseEntity(HttpStatus.OK)); |
321 | - subscriptionService.onAttributesUpdateFromServer(entityId, scope, attributes); | ||
322 | } | 320 | } |
323 | 321 | ||
324 | @Override | 322 | @Override |
@@ -327,7 +325,6 @@ public class TelemetryController extends BaseController { | @@ -327,7 +325,6 @@ public class TelemetryController extends BaseController { | ||
327 | AccessValidator.handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR); | 325 | AccessValidator.handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR); |
328 | } | 326 | } |
329 | }); | 327 | }); |
330 | - result.setResult(new ResponseEntity(HttpStatus.OK)); | ||
331 | }); | 328 | }); |
332 | } else { | 329 | } else { |
333 | return getImmediateDeferredResult("Request is not a JSON object", HttpStatus.BAD_REQUEST); | 330 | return getImmediateDeferredResult("Request is not a JSON object", HttpStatus.BAD_REQUEST); |
@@ -358,12 +355,10 @@ public class TelemetryController extends BaseController { | @@ -358,12 +355,10 @@ public class TelemetryController extends BaseController { | ||
358 | } | 355 | } |
359 | SecurityUser user = getCurrentUser(); | 356 | SecurityUser user = getCurrentUser(); |
360 | return accessValidator.validateEntityAndCallback(getCurrentUser(), entityIdSrc, (result, entityId) -> { | 357 | return accessValidator.validateEntityAndCallback(getCurrentUser(), entityIdSrc, (result, entityId) -> { |
361 | - ListenableFuture<List<Void>> future = tsService.save(entityId, entries, ttl); | ||
362 | - Futures.addCallback(future, new FutureCallback<List<Void>>() { | 358 | + tsSubService.saveAndNotify(entityId, entries, ttl, new FutureCallback<Void>() { |
363 | @Override | 359 | @Override |
364 | - public void onSuccess(@Nullable List<Void> tmp) { | 360 | + public void onSuccess(@Nullable Void tmp) { |
365 | result.setResult(new ResponseEntity(HttpStatus.OK)); | 361 | result.setResult(new ResponseEntity(HttpStatus.OK)); |
366 | - subscriptionService.onTimeseriesUpdateFromServer(entityId, entries); | ||
367 | } | 362 | } |
368 | 363 | ||
369 | @Override | 364 | @Override |
@@ -371,7 +366,6 @@ public class TelemetryController extends BaseController { | @@ -371,7 +366,6 @@ public class TelemetryController extends BaseController { | ||
371 | AccessValidator.handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR); | 366 | AccessValidator.handleError(t, result, HttpStatus.INTERNAL_SERVER_ERROR); |
372 | } | 367 | } |
373 | }); | 368 | }); |
374 | - result.setResult(new ResponseEntity(HttpStatus.OK)); | ||
375 | }); | 369 | }); |
376 | } | 370 | } |
377 | 371 |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | 3 | + * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with 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 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * <p> | 7 | + * |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
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 | + */ | ||
1 | package org.thingsboard.server.service.security; | 16 | package org.thingsboard.server.service.security; |
2 | 17 | ||
3 | import com.google.common.base.Function; | 18 | import com.google.common.base.Function; |
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 | + */ | ||
1 | package org.thingsboard.server.service.security; | 16 | package org.thingsboard.server.service.security; |
2 | 17 | ||
3 | import com.google.common.util.concurrent.FutureCallback; | 18 | import com.google.common.util.concurrent.FutureCallback; |
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
18 | +import com.google.common.util.concurrent.FutureCallback; | ||
19 | +import com.google.common.util.concurrent.Futures; | ||
20 | +import com.google.common.util.concurrent.ListenableFuture; | ||
3 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
4 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
5 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | +import org.springframework.util.StringUtils; | ||
6 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
7 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 26 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
8 | -import org.thingsboard.server.common.data.kv.KvEntry; | 27 | +import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
9 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 28 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
29 | +import org.thingsboard.server.common.msg.cluster.ServerAddress; | ||
30 | +import org.thingsboard.server.dao.attributes.AttributesService; | ||
31 | +import org.thingsboard.server.dao.timeseries.TimeseriesService; | ||
32 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; | ||
10 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.Subscription; | 33 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.Subscription; |
11 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; | 34 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; |
35 | +import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; | ||
36 | +import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; | ||
12 | 37 | ||
38 | +import javax.annotation.Nullable; | ||
39 | +import javax.annotation.PostConstruct; | ||
40 | +import javax.annotation.PreDestroy; | ||
41 | +import java.util.ArrayList; | ||
13 | import java.util.HashMap; | 42 | import java.util.HashMap; |
43 | +import java.util.HashSet; | ||
14 | import java.util.List; | 44 | import java.util.List; |
15 | import java.util.Map; | 45 | import java.util.Map; |
46 | +import java.util.Optional; | ||
16 | import java.util.Set; | 47 | import java.util.Set; |
48 | +import java.util.concurrent.ExecutorService; | ||
49 | +import java.util.concurrent.Executors; | ||
50 | +import java.util.function.Consumer; | ||
51 | +import java.util.function.Function; | ||
52 | +import java.util.function.Predicate; | ||
17 | 53 | ||
18 | /** | 54 | /** |
19 | * Created by ashvayka on 27.03.18. | 55 | * Created by ashvayka on 27.03.18. |
@@ -25,42 +61,275 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio | @@ -25,42 +61,275 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio | ||
25 | @Autowired | 61 | @Autowired |
26 | private TelemetryWebSocketService wsService; | 62 | private TelemetryWebSocketService wsService; |
27 | 63 | ||
64 | + @Autowired | ||
65 | + private AttributesService attrService; | ||
66 | + | ||
67 | + @Autowired | ||
68 | + private TimeseriesService tsService; | ||
69 | + | ||
70 | + @Autowired | ||
71 | + private ClusterRoutingService routingService; | ||
72 | + | ||
73 | + private ExecutorService tsCallBackExecutor; | ||
74 | + private ExecutorService wsCallBackExecutor; | ||
75 | + | ||
76 | + @PostConstruct | ||
77 | + public void initExecutor() { | ||
78 | + tsCallBackExecutor = Executors.newSingleThreadExecutor(); | ||
79 | + wsCallBackExecutor = Executors.newSingleThreadExecutor(); | ||
80 | + } | ||
81 | + | ||
82 | + @PreDestroy | ||
83 | + public void shutdownExecutor() { | ||
84 | + if (tsCallBackExecutor != null) { | ||
85 | + tsCallBackExecutor.shutdownNow(); | ||
86 | + } | ||
87 | + if (wsCallBackExecutor != null) { | ||
88 | + wsCallBackExecutor.shutdownNow(); | ||
89 | + } | ||
90 | + } | ||
91 | + | ||
28 | private final Map<EntityId, Set<Subscription>> subscriptionsByEntityId = new HashMap<>(); | 92 | private final Map<EntityId, Set<Subscription>> subscriptionsByEntityId = new HashMap<>(); |
29 | 93 | ||
30 | private final Map<String, Map<Integer, Subscription>> subscriptionsByWsSessionId = new HashMap<>(); | 94 | private final Map<String, Map<Integer, Subscription>> subscriptionsByWsSessionId = new HashMap<>(); |
31 | 95 | ||
32 | @Override | 96 | @Override |
33 | - public void onAttributesUpdateFromServer(EntityId entityId, String scope, List<AttributeKvEntry> attributes) { | ||
34 | - | 97 | + public void addLocalWsSubscription(String sessionId, EntityId entityId, SubscriptionState sub) { |
98 | + Optional<ServerAddress> server = routingService.resolveById(entityId); | ||
99 | + Subscription subscription; | ||
100 | + if (server.isPresent()) { | ||
101 | + ServerAddress address = server.get(); | ||
102 | + log.trace("[{}] Forwarding subscription [{}] for device [{}] to [{}]", sessionId, sub.getSubscriptionId(), entityId, address); | ||
103 | + subscription = new Subscription(sub, true, address); | ||
104 | +// rpcHandler.onNewSubscription(ctx, address, sessionId, subscription); | ||
105 | + } else { | ||
106 | + log.trace("[{}] Registering local subscription [{}] for device [{}]", sessionId, sub.getSubscriptionId(), entityId); | ||
107 | + subscription = new Subscription(sub, true); | ||
108 | + } | ||
109 | + registerSubscription(sessionId, entityId, subscription); | ||
35 | } | 110 | } |
36 | 111 | ||
37 | @Override | 112 | @Override |
38 | - public void onTimeseriesUpdateFromServer(EntityId entityId, List<TsKvEntry> entries) { | 113 | + public void cleanupLocalWsSessionSubscriptions(TelemetryWebSocketSessionRef sessionRef, String sessionId) { |
114 | + cleanupLocalWsSessionSubscriptions(sessionId); | ||
115 | + } | ||
39 | 116 | ||
117 | + @Override | ||
118 | + public void removeSubscription(String sessionId, int subscriptionId) { | ||
119 | + log.debug("[{}][{}] Going to remove subscription.", sessionId, subscriptionId); | ||
120 | + Map<Integer, Subscription> sessionSubscriptions = subscriptionsByWsSessionId.get(sessionId); | ||
121 | + if (sessionSubscriptions != null) { | ||
122 | + Subscription subscription = sessionSubscriptions.remove(subscriptionId); | ||
123 | + if (subscription != null) { | ||
124 | + processSubscriptionRemoval(sessionId, sessionSubscriptions, subscription); | ||
125 | + } else { | ||
126 | + log.debug("[{}][{}] Subscription not found!", sessionId, subscriptionId); | ||
127 | + } | ||
128 | + } else { | ||
129 | + log.debug("[{}] No session subscriptions found!", sessionId); | ||
130 | + } | ||
40 | } | 131 | } |
41 | 132 | ||
42 | @Override | 133 | @Override |
43 | - public void cleanupLocalWsSessionSubscriptions(TelemetryWebSocketSessionRef sessionRef, String sessionId) { | 134 | + public void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, FutureCallback<Void> callback) { |
135 | + saveAndNotify(entityId, ts, 0L, callback); | ||
136 | + } | ||
44 | 137 | ||
138 | + @Override | ||
139 | + public void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Void> callback) { | ||
140 | + ListenableFuture<List<Void>> saveFuture = tsService.save(entityId, ts, ttl); | ||
141 | + addMainCallback(saveFuture, callback); | ||
142 | + addWsCallback(saveFuture, success -> onTimeseriesUpdate(entityId, ts)); | ||
45 | } | 143 | } |
46 | 144 | ||
47 | @Override | 145 | @Override |
48 | - public void removeSubscription(String sessionId, int cmdId) { | 146 | + public void saveAndNotify(EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback) { |
147 | + ListenableFuture<List<Void>> saveFuture = attrService.save(entityId, scope, attributes); | ||
148 | + addMainCallback(saveFuture, callback); | ||
149 | + addWsCallback(saveFuture, success -> onAttributesUpdate(entityId, scope, attributes)); | ||
150 | + } | ||
49 | 151 | ||
152 | + private void onAttributesUpdate(EntityId entityId, String scope, List<AttributeKvEntry> attributes) { | ||
153 | + Optional<ServerAddress> serverAddress = routingService.resolveById(entityId); | ||
154 | + if (!serverAddress.isPresent()) { | ||
155 | + onLocalAttributesUpdate(entityId, scope, attributes); | ||
156 | + } else { | ||
157 | +// rpcHandler.onAttributesUpdate(ctx, serverAddress.get(), entityId, entries); | ||
158 | + } | ||
50 | } | 159 | } |
51 | 160 | ||
52 | - @Override | ||
53 | - public void addLocalWsSubscription(String sessionId, EntityId entityId, SubscriptionState sub) { | 161 | + private void onTimeseriesUpdate(EntityId entityId, List<TsKvEntry> ts) { |
162 | + Optional<ServerAddress> serverAddress = routingService.resolveById(entityId); | ||
163 | + if (!serverAddress.isPresent()) { | ||
164 | + onLocalTimeseriesUpdate(entityId, ts); | ||
165 | + } else { | ||
166 | +// rpcHandler.onTimeseriesUpdate(ctx, serverAddress.get(), entityId, entries); | ||
167 | + } | ||
168 | + } | ||
54 | 169 | ||
170 | + private void onLocalAttributesUpdate(EntityId entityId, String scope, List<AttributeKvEntry> attributes) { | ||
171 | + onLocalSubUpdate(entityId, s -> TelemetryFeature.ATTRIBUTES == s.getType() && (StringUtils.isEmpty(s.getScope()) || scope.equals(s.getScope())), s -> { | ||
172 | + List<TsKvEntry> subscriptionUpdate = null; | ||
173 | + for (AttributeKvEntry kv : attributes) { | ||
174 | + if (s.isAllKeys() || s.getKeyStates().containsKey(kv.getKey())) { | ||
175 | + if (subscriptionUpdate == null) { | ||
176 | + subscriptionUpdate = new ArrayList<>(); | ||
177 | + } | ||
178 | + subscriptionUpdate.add(new BasicTsKvEntry(kv.getLastUpdateTs(), kv)); | ||
179 | + } | ||
180 | + } | ||
181 | + return subscriptionUpdate; | ||
182 | + }); | ||
55 | } | 183 | } |
56 | 184 | ||
57 | - @Override | ||
58 | - public void onLocalTimeseriesUpdate(EntityId entityId, Map<Long, List<KvEntry>> ts) { | 185 | + private void onLocalTimeseriesUpdate(EntityId entityId, List<TsKvEntry> ts) { |
186 | + onLocalSubUpdate(entityId, s -> TelemetryFeature.TIMESERIES == s.getType(), s -> { | ||
187 | + List<TsKvEntry> subscriptionUpdate = null; | ||
188 | + for (TsKvEntry kv : ts) { | ||
189 | + if (s.isAllKeys() || s.getKeyStates().containsKey((kv.getKey()))) { | ||
190 | + if (subscriptionUpdate == null) { | ||
191 | + subscriptionUpdate = new ArrayList<>(); | ||
192 | + } | ||
193 | + subscriptionUpdate.add(kv); | ||
194 | + } | ||
195 | + } | ||
196 | + return subscriptionUpdate; | ||
197 | + }); | ||
198 | + } | ||
59 | 199 | ||
200 | + private void onLocalSubUpdate(EntityId entityId, Predicate<Subscription> filter, Function<Subscription, List<TsKvEntry>> f) { | ||
201 | + Set<Subscription> deviceSubscriptions = subscriptionsByEntityId.get(entityId); | ||
202 | + if (deviceSubscriptions != null) { | ||
203 | + deviceSubscriptions.stream().filter(filter).forEach(s -> { | ||
204 | + String sessionId = s.getWsSessionId(); | ||
205 | + List<TsKvEntry> subscriptionUpdate = f.apply(s); | ||
206 | + if (subscriptionUpdate == null || !subscriptionUpdate.isEmpty()) { | ||
207 | + SubscriptionUpdate update = new SubscriptionUpdate(s.getSubscriptionId(), subscriptionUpdate); | ||
208 | + if (s.isLocal()) { | ||
209 | + updateSubscriptionState(sessionId, s, update); | ||
210 | + wsService.sendWsMsg(sessionId, update); | ||
211 | + } else { | ||
212 | + //TODO: ashvayka | ||
213 | +// rpcHandler.onSubscriptionUpdate(ctx, s.getServer(), sessionId, update); | ||
214 | + } | ||
215 | + } | ||
216 | + }); | ||
217 | + } else { | ||
218 | + log.debug("[{}] No device subscriptions to process!", entityId); | ||
219 | + } | ||
60 | } | 220 | } |
61 | 221 | ||
62 | - @Override | ||
63 | - public void onLocalAttributesUpdate(EntityId entityId, String scope, Set<AttributeKvEntry> attributes) { | 222 | + private void updateSubscriptionState(String sessionId, Subscription subState, SubscriptionUpdate update) { |
223 | + log.trace("[{}] updating subscription state {} using onUpdate {}", sessionId, subState, update); | ||
224 | + update.getLatestValues().entrySet().forEach(e -> subState.setKeyState(e.getKey(), e.getValue())); | ||
225 | + } | ||
226 | + | ||
227 | + private void registerSubscription(String sessionId, EntityId entityId, Subscription subscription) { | ||
228 | + Set<Subscription> deviceSubscriptions = subscriptionsByEntityId.computeIfAbsent(entityId, k -> new HashSet<>()); | ||
229 | + deviceSubscriptions.add(subscription); | ||
230 | + Map<Integer, Subscription> sessionSubscriptions = subscriptionsByWsSessionId.computeIfAbsent(sessionId, k -> new HashMap<>()); | ||
231 | + sessionSubscriptions.put(subscription.getSubscriptionId(), subscription); | ||
232 | + } | ||
233 | + | ||
234 | + public void cleanupLocalWsSessionSubscriptions(String sessionId) { | ||
235 | + cleanupWsSessionSubscriptions(sessionId, true); | ||
236 | + } | ||
237 | + | ||
238 | + public void cleanupRemoteWsSessionSubscriptions(String sessionId) { | ||
239 | + cleanupWsSessionSubscriptions(sessionId, false); | ||
240 | + } | ||
241 | + | ||
242 | + private void cleanupWsSessionSubscriptions(String sessionId, boolean localSession) { | ||
243 | + log.debug("[{}] Removing all subscriptions for particular session.", sessionId); | ||
244 | + Map<Integer, Subscription> sessionSubscriptions = subscriptionsByWsSessionId.get(sessionId); | ||
245 | + if (sessionSubscriptions != null) { | ||
246 | + int sessionSubscriptionSize = sessionSubscriptions.size(); | ||
247 | + | ||
248 | + for (Subscription subscription : sessionSubscriptions.values()) { | ||
249 | + EntityId entityId = subscription.getEntityId(); | ||
250 | + Set<Subscription> deviceSubscriptions = subscriptionsByEntityId.get(entityId); | ||
251 | + deviceSubscriptions.remove(subscription); | ||
252 | + if (deviceSubscriptions.isEmpty()) { | ||
253 | + subscriptionsByEntityId.remove(entityId); | ||
254 | + } | ||
255 | + } | ||
256 | + subscriptionsByWsSessionId.remove(sessionId); | ||
257 | + log.debug("[{}] Removed {} subscriptions for particular session.", sessionId, sessionSubscriptionSize); | ||
258 | + | ||
259 | + if (localSession) { | ||
260 | + notifyWsSubscriptionClosed(sessionId, sessionSubscriptions); | ||
261 | + } | ||
262 | + } else { | ||
263 | + log.debug("[{}] No subscriptions found!", sessionId); | ||
264 | + } | ||
265 | + } | ||
266 | + | ||
267 | + private void notifyWsSubscriptionClosed(String sessionId, Map<Integer, Subscription> sessionSubscriptions) { | ||
268 | + Set<ServerAddress> affectedServers = new HashSet<>(); | ||
269 | + for (Subscription subscription : sessionSubscriptions.values()) { | ||
270 | + if (subscription.getServer() != null) { | ||
271 | + affectedServers.add(subscription.getServer()); | ||
272 | + } | ||
273 | + } | ||
274 | + for (ServerAddress address : affectedServers) { | ||
275 | + log.debug("[{}] Going to onSubscriptionUpdate [{}] server about session close event", sessionId, address); | ||
276 | +// rpcHandler.onSessionClose(ctx, address, sessionId); | ||
277 | + } | ||
278 | + } | ||
279 | + | ||
280 | + private void processSubscriptionRemoval(String sessionId, Map<Integer, Subscription> sessionSubscriptions, Subscription subscription) { | ||
281 | + EntityId entityId = subscription.getEntityId(); | ||
282 | + if (subscription.isLocal() && subscription.getServer() != null) { | ||
283 | +// rpcHandler.onSubscriptionClose(ctx, subscription.getServer(), sessionId, subscription.getSubscriptionId()); | ||
284 | + } | ||
285 | + if (sessionSubscriptions.isEmpty()) { | ||
286 | + log.debug("[{}] Removed last subscription for particular session.", sessionId); | ||
287 | + subscriptionsByWsSessionId.remove(sessionId); | ||
288 | + } else { | ||
289 | + log.debug("[{}] Removed session subscription.", sessionId); | ||
290 | + } | ||
291 | + Set<Subscription> deviceSubscriptions = subscriptionsByEntityId.get(entityId); | ||
292 | + if (deviceSubscriptions != null) { | ||
293 | + boolean result = deviceSubscriptions.remove(subscription); | ||
294 | + if (result) { | ||
295 | + if (deviceSubscriptions.size() == 0) { | ||
296 | + log.debug("[{}] Removed last subscription for particular device.", sessionId); | ||
297 | + subscriptionsByEntityId.remove(entityId); | ||
298 | + } else { | ||
299 | + log.debug("[{}] Removed device subscription.", sessionId); | ||
300 | + } | ||
301 | + } else { | ||
302 | + log.debug("[{}] Subscription not found!", sessionId); | ||
303 | + } | ||
304 | + } else { | ||
305 | + log.debug("[{}] No device subscriptions found!", sessionId); | ||
306 | + } | ||
307 | + } | ||
308 | + | ||
309 | + private void addMainCallback(ListenableFuture<List<Void>> saveFuture, final FutureCallback<Void> callback) { | ||
310 | + Futures.addCallback(saveFuture, new FutureCallback<List<Void>>() { | ||
311 | + @Override | ||
312 | + public void onSuccess(@Nullable List<Void> result) { | ||
313 | + callback.onSuccess(null); | ||
314 | + } | ||
315 | + | ||
316 | + @Override | ||
317 | + public void onFailure(Throwable t) { | ||
318 | + callback.onFailure(t); | ||
319 | + } | ||
320 | + }, tsCallBackExecutor); | ||
321 | + } | ||
322 | + | ||
323 | + private void addWsCallback(ListenableFuture<List<Void>> saveFuture, Consumer<Void> callback) { | ||
324 | + Futures.addCallback(saveFuture, new FutureCallback<List<Void>>() { | ||
325 | + @Override | ||
326 | + public void onSuccess(@Nullable List<Void> result) { | ||
327 | + callback.accept(null); | ||
328 | + } | ||
64 | 329 | ||
330 | + @Override | ||
331 | + public void onFailure(Throwable t) { | ||
332 | + } | ||
333 | + }, wsCallBackExecutor); | ||
65 | } | 334 | } |
66 | } | 335 | } |
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
3 | import com.fasterxml.jackson.core.JsonProcessingException; | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
@@ -24,6 +39,7 @@ import org.thingsboard.server.common.data.kv.TsKvQuery; | @@ -24,6 +39,7 @@ import org.thingsboard.server.common.data.kv.TsKvQuery; | ||
24 | import org.thingsboard.server.dao.attributes.AttributesService; | 39 | import org.thingsboard.server.dao.attributes.AttributesService; |
25 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 40 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
26 | import org.thingsboard.server.extensions.api.exception.UnauthorizedException; | 41 | import org.thingsboard.server.extensions.api.exception.UnauthorizedException; |
42 | +import org.thingsboard.server.extensions.api.plugins.PluginContext; | ||
27 | import org.thingsboard.server.extensions.api.plugins.ws.SessionEvent; | 43 | import org.thingsboard.server.extensions.api.plugins.ws.SessionEvent; |
28 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.AttributesSubscriptionCmd; | 44 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.AttributesSubscriptionCmd; |
29 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.GetHistoryCmd; | 45 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.GetHistoryCmd; |
@@ -31,9 +47,9 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.SubscriptionC | @@ -31,9 +47,9 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.SubscriptionC | ||
31 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TelemetryPluginCmd; | 47 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TelemetryPluginCmd; |
32 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TelemetryPluginCmdsWrapper; | 48 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TelemetryPluginCmdsWrapper; |
33 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TimeseriesSubscriptionCmd; | 49 | import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TimeseriesSubscriptionCmd; |
50 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; | ||
34 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionErrorCode; | 51 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionErrorCode; |
35 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; | 52 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; |
36 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | ||
37 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; | 53 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; |
38 | import org.thingsboard.server.service.security.AccessValidator; | 54 | import org.thingsboard.server.service.security.AccessValidator; |
39 | 55 | ||
@@ -146,6 +162,14 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -146,6 +162,14 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
146 | } | 162 | } |
147 | } | 163 | } |
148 | 164 | ||
165 | + @Override | ||
166 | + public void sendWsMsg(String sessionId, SubscriptionUpdate update) { | ||
167 | + WsSessionMetaData md = wsSessionsMap.get(sessionId); | ||
168 | + if (md != null) { | ||
169 | + sendWsMsg(md.getSessionRef(), update); | ||
170 | + } | ||
171 | + } | ||
172 | + | ||
149 | private void handleWsAttributesSubscriptionCmd(TelemetryWebSocketSessionRef sessionRef, AttributesSubscriptionCmd cmd) { | 173 | private void handleWsAttributesSubscriptionCmd(TelemetryWebSocketSessionRef sessionRef, AttributesSubscriptionCmd cmd) { |
150 | String sessionId = sessionRef.getSessionId(); | 174 | String sessionId = sessionRef.getSessionId(); |
151 | log.debug("[{}] Processing: {}", sessionId, cmd); | 175 | log.debug("[{}] Processing: {}", sessionId, cmd); |
@@ -180,7 +204,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -180,7 +204,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
180 | keys.forEach(key -> subState.put(key, 0L)); | 204 | keys.forEach(key -> subState.put(key, 0L)); |
181 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 205 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
182 | 206 | ||
183 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.ATTRIBUTES, false, subState, cmd.getScope()); | 207 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.ATTRIBUTES, false, subState, cmd.getScope()); |
184 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); | 208 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); |
185 | } | 209 | } |
186 | 210 | ||
@@ -267,7 +291,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -267,7 +291,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
267 | Map<String, Long> subState = new HashMap<>(attributesData.size()); | 291 | Map<String, Long> subState = new HashMap<>(attributesData.size()); |
268 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 292 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
269 | 293 | ||
270 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.ATTRIBUTES, true, subState, cmd.getScope()); | 294 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.ATTRIBUTES, true, subState, cmd.getScope()); |
271 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); | 295 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); |
272 | } | 296 | } |
273 | 297 | ||
@@ -340,7 +364,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -340,7 +364,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
340 | sendWsMsg(sessionRef, new SubscriptionUpdate(cmd.getCmdId(), data)); | 364 | sendWsMsg(sessionRef, new SubscriptionUpdate(cmd.getCmdId(), data)); |
341 | Map<String, Long> subState = new HashMap<>(data.size()); | 365 | Map<String, Long> subState = new HashMap<>(data.size()); |
342 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); | 366 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); |
343 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.TIMESERIES, true, subState, cmd.getScope()); | 367 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.TIMESERIES, true, subState, cmd.getScope()); |
344 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); | 368 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); |
345 | } | 369 | } |
346 | 370 | ||
@@ -370,7 +394,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -370,7 +394,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
370 | Map<String, Long> subState = new HashMap<>(keys.size()); | 394 | Map<String, Long> subState = new HashMap<>(keys.size()); |
371 | keys.forEach(key -> subState.put(key, startTs)); | 395 | keys.forEach(key -> subState.put(key, startTs)); |
372 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); | 396 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); |
373 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.TIMESERIES, false, subState, cmd.getScope()); | 397 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.TIMESERIES, false, subState, cmd.getScope()); |
374 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); | 398 | subscriptionManager.addLocalWsSubscription(sessionId, entityId, sub); |
375 | } | 399 | } |
376 | 400 |
application/src/main/java/org/thingsboard/server/service/telemetry/TelemetrySubscriptionService.java
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
18 | +import com.google.common.util.concurrent.FutureCallback; | ||
3 | import org.thingsboard.server.common.data.id.EntityId; | 19 | import org.thingsboard.server.common.data.id.EntityId; |
4 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 20 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
5 | import org.thingsboard.server.common.data.kv.KvEntry; | 21 | import org.thingsboard.server.common.data.kv.KvEntry; |
@@ -15,17 +31,15 @@ import java.util.Set; | @@ -15,17 +31,15 @@ import java.util.Set; | ||
15 | */ | 31 | */ |
16 | public interface TelemetrySubscriptionService { | 32 | public interface TelemetrySubscriptionService { |
17 | 33 | ||
18 | - void onAttributesUpdateFromServer(EntityId entityId, String scope, List<AttributeKvEntry> attributes); | ||
19 | - | ||
20 | - void onTimeseriesUpdateFromServer(EntityId entityId, List<TsKvEntry> entries); | 34 | + void addLocalWsSubscription(String sessionId, EntityId entityId, SubscriptionState sub); |
21 | 35 | ||
22 | void cleanupLocalWsSessionSubscriptions(TelemetryWebSocketSessionRef sessionRef, String sessionId); | 36 | void cleanupLocalWsSessionSubscriptions(TelemetryWebSocketSessionRef sessionRef, String sessionId); |
23 | 37 | ||
24 | void removeSubscription(String sessionId, int cmdId); | 38 | void removeSubscription(String sessionId, int cmdId); |
25 | 39 | ||
26 | - void addLocalWsSubscription(String sessionId, EntityId entityId, SubscriptionState sub); | 40 | + void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, FutureCallback<Void> callback); |
27 | 41 | ||
28 | - void onLocalTimeseriesUpdate(EntityId entityId, List<TsKvEntry> ts); | 42 | + void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Void> callback); |
29 | 43 | ||
30 | - void onLocalAttributesUpdate(EntityId entityId, String scope, Set<AttributeKvEntry> attributes); | 44 | + void saveAndNotify(EntityId entityId, String scope, List<AttributeKvEntry> attributes, FutureCallback<Void> callback); |
31 | } | 45 | } |
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
3 | import java.io.IOException; | 18 | import java.io.IOException; |
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
3 | import org.thingsboard.server.extensions.api.plugins.ws.SessionEvent; | 18 | import org.thingsboard.server.extensions.api.plugins.ws.SessionEvent; |
19 | +import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; | ||
4 | 20 | ||
5 | /** | 21 | /** |
6 | * Created by ashvayka on 27.03.18. | 22 | * Created by ashvayka on 27.03.18. |
@@ -10,4 +26,6 @@ public interface TelemetryWebSocketService { | @@ -10,4 +26,6 @@ public interface TelemetryWebSocketService { | ||
10 | void handleWebSocketSessionEvent(TelemetryWebSocketSessionRef sessionRef, SessionEvent sessionEvent); | 26 | void handleWebSocketSessionEvent(TelemetryWebSocketSessionRef sessionRef, SessionEvent sessionEvent); |
11 | 27 | ||
12 | void handleWebSocketMsg(TelemetryWebSocketSessionRef sessionRef, String msg); | 28 | void handleWebSocketMsg(TelemetryWebSocketSessionRef sessionRef, String msg); |
29 | + | ||
30 | + void sendWsMsg(String sessionId, SubscriptionUpdate update); | ||
13 | } | 31 | } |
application/src/main/java/org/thingsboard/server/service/telemetry/TelemetryWebSocketSessionRef.java
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
3 | import lombok.Getter; | 18 | import lombok.Getter; |
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
3 | import lombok.Data; | 18 | import lombok.Data; |
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 | + */ | ||
1 | package org.thingsboard.server.service.telemetry; | 16 | package org.thingsboard.server.service.telemetry; |
2 | 17 | ||
3 | import org.thingsboard.server.extensions.api.plugins.ws.PluginWebsocketSessionRef; | 18 | import org.thingsboard.server.extensions.api.plugins.ws.PluginWebsocketSessionRef; |
@@ -19,20 +19,30 @@ import lombok.Setter; | @@ -19,20 +19,30 @@ import lombok.Setter; | ||
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | import org.springframework.util.StringUtils; | 20 | import org.springframework.util.StringUtils; |
21 | import org.thingsboard.server.common.data.DataConstants; | 21 | import org.thingsboard.server.common.data.DataConstants; |
22 | -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.EntityId; |
24 | -import org.thingsboard.server.common.data.kv.*; | 23 | +import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
24 | +import org.thingsboard.server.common.data.kv.BaseTsKvQuery; | ||
25 | +import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | ||
26 | +import org.thingsboard.server.common.data.kv.TsKvEntry; | ||
27 | +import org.thingsboard.server.common.data.kv.TsKvQuery; | ||
25 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 28 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
26 | import org.thingsboard.server.extensions.api.plugins.PluginCallback; | 29 | import org.thingsboard.server.extensions.api.plugins.PluginCallback; |
27 | import org.thingsboard.server.extensions.api.plugins.PluginContext; | 30 | import org.thingsboard.server.extensions.api.plugins.PluginContext; |
31 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; | ||
28 | import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryRpcMsgHandler; | 32 | import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryRpcMsgHandler; |
29 | import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryWebsocketMsgHandler; | 33 | import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryWebsocketMsgHandler; |
30 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.Subscription; | 34 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.Subscription; |
31 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; | 35 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; |
32 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | ||
33 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; | 36 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; |
34 | 37 | ||
35 | -import java.util.*; | 38 | +import java.util.ArrayList; |
39 | +import java.util.HashMap; | ||
40 | +import java.util.HashSet; | ||
41 | +import java.util.Iterator; | ||
42 | +import java.util.List; | ||
43 | +import java.util.Map; | ||
44 | +import java.util.Optional; | ||
45 | +import java.util.Set; | ||
36 | import java.util.function.Function; | 46 | import java.util.function.Function; |
37 | import java.util.function.Predicate; | 47 | import java.util.function.Predicate; |
38 | 48 | ||
@@ -70,7 +80,7 @@ public class SubscriptionManager { | @@ -70,7 +80,7 @@ public class SubscriptionManager { | ||
70 | EntityId entityId = subscription.getEntityId(); | 80 | EntityId entityId = subscription.getEntityId(); |
71 | log.trace("[{}] Registering remote subscription [{}] for device [{}] to [{}]", sessionId, subscription.getSubscriptionId(), entityId, address); | 81 | log.trace("[{}] Registering remote subscription [{}] for device [{}] to [{}]", sessionId, subscription.getSubscriptionId(), entityId, address); |
72 | registerSubscription(sessionId, entityId, subscription); | 82 | registerSubscription(sessionId, entityId, subscription); |
73 | - if (subscription.getType() == SubscriptionType.ATTRIBUTES) { | 83 | + if (subscription.getType() == TelemetryFeature.ATTRIBUTES) { |
74 | final Map<String, Long> keyStates = subscription.getKeyStates(); | 84 | final Map<String, Long> keyStates = subscription.getKeyStates(); |
75 | ctx.loadAttributes(entityId, DataConstants.CLIENT_SCOPE, keyStates.keySet(), new PluginCallback<List<AttributeKvEntry>>() { | 85 | ctx.loadAttributes(entityId, DataConstants.CLIENT_SCOPE, keyStates.keySet(), new PluginCallback<List<AttributeKvEntry>>() { |
76 | @Override | 86 | @Override |
@@ -91,7 +101,7 @@ public class SubscriptionManager { | @@ -91,7 +101,7 @@ public class SubscriptionManager { | ||
91 | log.error("Failed to fetch missed updates.", e); | 101 | log.error("Failed to fetch missed updates.", e); |
92 | } | 102 | } |
93 | }); | 103 | }); |
94 | - } else if (subscription.getType() == SubscriptionType.TIMESERIES) { | 104 | + } else if (subscription.getType() == TelemetryFeature.TIMESERIES) { |
95 | long curTs = System.currentTimeMillis(); | 105 | long curTs = System.currentTimeMillis(); |
96 | List<TsKvQuery> queries = new ArrayList<>(); | 106 | List<TsKvQuery> queries = new ArrayList<>(); |
97 | subscription.getKeyStates().entrySet().forEach(e -> { | 107 | subscription.getKeyStates().entrySet().forEach(e -> { |
@@ -175,7 +185,7 @@ public class SubscriptionManager { | @@ -175,7 +185,7 @@ public class SubscriptionManager { | ||
175 | } | 185 | } |
176 | } | 186 | } |
177 | 187 | ||
178 | - public void onLocalSubscriptionUpdate(PluginContext ctx, EntityId entityId, SubscriptionType type, Function<Subscription, List<TsKvEntry>> f) { | 188 | + public void onLocalSubscriptionUpdate(PluginContext ctx, EntityId entityId, TelemetryFeature type, Function<Subscription, List<TsKvEntry>> f) { |
179 | onLocalSubscriptionUpdate(ctx, entityId, s -> type == s.getType(), f); | 189 | onLocalSubscriptionUpdate(ctx, entityId, s -> type == s.getType(), f); |
180 | } | 190 | } |
181 | 191 | ||
@@ -212,7 +222,7 @@ public class SubscriptionManager { | @@ -212,7 +222,7 @@ public class SubscriptionManager { | ||
212 | public void onAttributesUpdateFromServer(PluginContext ctx, EntityId entityId, String scope, List<AttributeKvEntry> attributes) { | 222 | public void onAttributesUpdateFromServer(PluginContext ctx, EntityId entityId, String scope, List<AttributeKvEntry> attributes) { |
213 | Optional<ServerAddress> serverAddress = ctx.resolve(entityId); | 223 | Optional<ServerAddress> serverAddress = ctx.resolve(entityId); |
214 | if (!serverAddress.isPresent()) { | 224 | if (!serverAddress.isPresent()) { |
215 | - onLocalSubscriptionUpdate(ctx, entityId, s -> SubscriptionType.ATTRIBUTES == s.getType() && (StringUtils.isEmpty(s.getScope()) || scope.equals(s.getScope())), s -> { | 225 | + onLocalSubscriptionUpdate(ctx, entityId, s -> TelemetryFeature.ATTRIBUTES == s.getType() && (StringUtils.isEmpty(s.getScope()) || scope.equals(s.getScope())), s -> { |
216 | List<TsKvEntry> subscriptionUpdate = new ArrayList<TsKvEntry>(); | 226 | List<TsKvEntry> subscriptionUpdate = new ArrayList<TsKvEntry>(); |
217 | for (AttributeKvEntry kv : attributes) { | 227 | for (AttributeKvEntry kv : attributes) { |
218 | if (s.isAllKeys() || s.getKeyStates().containsKey(kv.getKey())) { | 228 | if (s.isAllKeys() || s.getKeyStates().containsKey(kv.getKey())) { |
@@ -229,7 +239,7 @@ public class SubscriptionManager { | @@ -229,7 +239,7 @@ public class SubscriptionManager { | ||
229 | public void onTimeseriesUpdateFromServer(PluginContext ctx, EntityId entityId, List<TsKvEntry> entries) { | 239 | public void onTimeseriesUpdateFromServer(PluginContext ctx, EntityId entityId, List<TsKvEntry> entries) { |
230 | Optional<ServerAddress> serverAddress = ctx.resolve(entityId); | 240 | Optional<ServerAddress> serverAddress = ctx.resolve(entityId); |
231 | if (!serverAddress.isPresent()) { | 241 | if (!serverAddress.isPresent()) { |
232 | - onLocalSubscriptionUpdate(ctx, entityId, SubscriptionType.TIMESERIES, s -> { | 242 | + onLocalSubscriptionUpdate(ctx, entityId, TelemetryFeature.TIMESERIES, s -> { |
233 | List<TsKvEntry> subscriptionUpdate = new ArrayList<TsKvEntry>(); | 243 | List<TsKvEntry> subscriptionUpdate = new ArrayList<TsKvEntry>(); |
234 | for (TsKvEntry kv : entries) { | 244 | for (TsKvEntry kv : entries) { |
235 | if (s.isAllKeys() || s.getKeyStates().containsKey((kv.getKey()))) { | 245 | if (s.isAllKeys() || s.getKeyStates().containsKey((kv.getKey()))) { |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | package org.thingsboard.server.extensions.core.plugin.telemetry.cmd; | 16 | package org.thingsboard.server.extensions.core.plugin.telemetry.cmd; |
17 | 17 | ||
18 | import lombok.NoArgsConstructor; | 18 | import lombok.NoArgsConstructor; |
19 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | 19 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @author Andrew Shvayka | 22 | * @author Andrew Shvayka |
@@ -25,8 +25,8 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionT | @@ -25,8 +25,8 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionT | ||
25 | public class AttributesSubscriptionCmd extends SubscriptionCmd { | 25 | public class AttributesSubscriptionCmd extends SubscriptionCmd { |
26 | 26 | ||
27 | @Override | 27 | @Override |
28 | - public SubscriptionType getType() { | ||
29 | - return SubscriptionType.ATTRIBUTES; | 28 | + public TelemetryFeature getType() { |
29 | + return TelemetryFeature.ATTRIBUTES; | ||
30 | } | 30 | } |
31 | 31 | ||
32 | } | 32 | } |
@@ -18,7 +18,7 @@ package org.thingsboard.server.extensions.core.plugin.telemetry.cmd; | @@ -18,7 +18,7 @@ package org.thingsboard.server.extensions.core.plugin.telemetry.cmd; | ||
18 | import lombok.AllArgsConstructor; | 18 | import lombok.AllArgsConstructor; |
19 | import lombok.Data; | 19 | import lombok.Data; |
20 | import lombok.NoArgsConstructor; | 20 | import lombok.NoArgsConstructor; |
21 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | 21 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; |
22 | 22 | ||
23 | @NoArgsConstructor | 23 | @NoArgsConstructor |
24 | @AllArgsConstructor | 24 | @AllArgsConstructor |
@@ -32,7 +32,7 @@ public abstract class SubscriptionCmd implements TelemetryPluginCmd { | @@ -32,7 +32,7 @@ public abstract class SubscriptionCmd implements TelemetryPluginCmd { | ||
32 | private String scope; | 32 | private String scope; |
33 | private boolean unsubscribe; | 33 | private boolean unsubscribe; |
34 | 34 | ||
35 | - public abstract SubscriptionType getType(); | 35 | + public abstract TelemetryFeature getType(); |
36 | 36 | ||
37 | @Override | 37 | @Override |
38 | public String toString() { | 38 | public String toString() { |
@@ -18,7 +18,7 @@ package org.thingsboard.server.extensions.core.plugin.telemetry.cmd; | @@ -18,7 +18,7 @@ package org.thingsboard.server.extensions.core.plugin.telemetry.cmd; | ||
18 | import lombok.AllArgsConstructor; | 18 | import lombok.AllArgsConstructor; |
19 | import lombok.Data; | 19 | import lombok.Data; |
20 | import lombok.NoArgsConstructor; | 20 | import lombok.NoArgsConstructor; |
21 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | 21 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * @author Andrew Shvayka | 24 | * @author Andrew Shvayka |
@@ -35,7 +35,7 @@ public class TimeseriesSubscriptionCmd extends SubscriptionCmd { | @@ -35,7 +35,7 @@ public class TimeseriesSubscriptionCmd extends SubscriptionCmd { | ||
35 | private String agg; | 35 | private String agg; |
36 | 36 | ||
37 | @Override | 37 | @Override |
38 | - public SubscriptionType getType() { | ||
39 | - return SubscriptionType.TIMESERIES; | 38 | + public TelemetryFeature getType() { |
39 | + return TelemetryFeature.TIMESERIES; | ||
40 | } | 40 | } |
41 | } | 41 | } |
@@ -114,7 +114,7 @@ public class TelemetryRpcMsgHandler implements RpcMsgHandler { | @@ -114,7 +114,7 @@ public class TelemetryRpcMsgHandler implements RpcMsgHandler { | ||
114 | } | 114 | } |
115 | Map<String, Long> statesMap = proto.getKeyStatesList().stream().collect(Collectors.toMap(SubscriptionKetStateProto::getKey, SubscriptionKetStateProto::getTs)); | 115 | Map<String, Long> statesMap = proto.getKeyStatesList().stream().collect(Collectors.toMap(SubscriptionKetStateProto::getKey, SubscriptionKetStateProto::getTs)); |
116 | Subscription subscription = new Subscription( | 116 | Subscription subscription = new Subscription( |
117 | - new SubscriptionState(proto.getSessionId(), proto.getSubscriptionId(), EntityIdFactory.getByTypeAndId(proto.getEntityType(), proto.getEntityId()), SubscriptionType.valueOf(proto.getType()), proto.getAllKeys(), statesMap, proto.getScope()), | 117 | + new SubscriptionState(proto.getSessionId(), proto.getSubscriptionId(), EntityIdFactory.getByTypeAndId(proto.getEntityType(), proto.getEntityId()), TelemetryFeature.valueOf(proto.getType()), proto.getAllKeys(), statesMap, proto.getScope()), |
118 | false, msg.getServerAddress()); | 118 | false, msg.getServerAddress()); |
119 | subscriptionManager.addRemoteWsSubscription(ctx, msg.getServerAddress(), proto.getSessionId(), subscription); | 119 | subscriptionManager.addRemoteWsSubscription(ctx, msg.getServerAddress(), proto.getSessionId(), subscription); |
120 | } | 120 | } |
@@ -24,7 +24,11 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; | @@ -24,7 +24,11 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; | ||
24 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | 24 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
25 | import org.thingsboard.server.common.data.kv.KvEntry; | 25 | import org.thingsboard.server.common.data.kv.KvEntry; |
26 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 26 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
27 | -import org.thingsboard.server.common.msg.core.*; | 27 | +import org.thingsboard.server.common.msg.core.BasicGetAttributesResponse; |
28 | +import org.thingsboard.server.common.msg.core.BasicStatusCodeResponse; | ||
29 | +import org.thingsboard.server.common.msg.core.GetAttributesRequest; | ||
30 | +import org.thingsboard.server.common.msg.core.TelemetryUploadRequest; | ||
31 | +import org.thingsboard.server.common.msg.core.UpdateAttributesRequest; | ||
28 | import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg; | 32 | import org.thingsboard.server.common.msg.kv.BasicAttributeKVMsg; |
29 | import org.thingsboard.server.extensions.api.plugins.PluginCallback; | 33 | import org.thingsboard.server.extensions.api.plugins.PluginCallback; |
30 | import org.thingsboard.server.extensions.api.plugins.PluginContext; | 34 | import org.thingsboard.server.extensions.api.plugins.PluginContext; |
@@ -35,9 +39,13 @@ import org.thingsboard.server.extensions.api.plugins.msg.TelemetryUploadRequestR | @@ -35,9 +39,13 @@ import org.thingsboard.server.extensions.api.plugins.msg.TelemetryUploadRequestR | ||
35 | import org.thingsboard.server.extensions.api.plugins.msg.UpdateAttributesRequestRuleToPluginMsg; | 39 | import org.thingsboard.server.extensions.api.plugins.msg.UpdateAttributesRequestRuleToPluginMsg; |
36 | import org.thingsboard.server.extensions.core.plugin.telemetry.SubscriptionManager; | 40 | import org.thingsboard.server.extensions.core.plugin.telemetry.SubscriptionManager; |
37 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.Subscription; | 41 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.Subscription; |
38 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | ||
39 | 42 | ||
40 | -import java.util.*; | 43 | +import java.util.ArrayList; |
44 | +import java.util.Collections; | ||
45 | +import java.util.List; | ||
46 | +import java.util.Map; | ||
47 | +import java.util.Optional; | ||
48 | +import java.util.Set; | ||
41 | import java.util.stream.Collectors; | 49 | import java.util.stream.Collectors; |
42 | 50 | ||
43 | @Slf4j | 51 | @Slf4j |
@@ -97,7 +105,7 @@ public class TelemetryRuleMsgHandler extends DefaultRuleMsgHandler { | @@ -97,7 +105,7 @@ public class TelemetryRuleMsgHandler extends DefaultRuleMsgHandler { | ||
97 | @Override | 105 | @Override |
98 | public void onSuccess(PluginContext ctx, Void data) { | 106 | public void onSuccess(PluginContext ctx, Void data) { |
99 | ctx.reply(new ResponsePluginToRuleMsg(msg.getUid(), tenantId, ruleId, BasicStatusCodeResponse.onSuccess(request.getMsgType(), request.getRequestId()))); | 107 | ctx.reply(new ResponsePluginToRuleMsg(msg.getUid(), tenantId, ruleId, BasicStatusCodeResponse.onSuccess(request.getMsgType(), request.getRequestId()))); |
100 | - subscriptionManager.onLocalSubscriptionUpdate(ctx, msg.getDeviceId(), SubscriptionType.TIMESERIES, s -> | 108 | + subscriptionManager.onLocalSubscriptionUpdate(ctx, msg.getDeviceId(), TelemetryFeature.TIMESERIES, s -> |
101 | prepareSubscriptionUpdate(request, s) | 109 | prepareSubscriptionUpdate(request, s) |
102 | ); | 110 | ); |
103 | } | 111 | } |
@@ -131,7 +139,7 @@ public class TelemetryRuleMsgHandler extends DefaultRuleMsgHandler { | @@ -131,7 +139,7 @@ public class TelemetryRuleMsgHandler extends DefaultRuleMsgHandler { | ||
131 | public void onSuccess(PluginContext ctx, Void value) { | 139 | public void onSuccess(PluginContext ctx, Void value) { |
132 | ctx.reply(new ResponsePluginToRuleMsg(msg.getUid(), tenantId, ruleId, BasicStatusCodeResponse.onSuccess(request.getMsgType(), request.getRequestId()))); | 140 | ctx.reply(new ResponsePluginToRuleMsg(msg.getUid(), tenantId, ruleId, BasicStatusCodeResponse.onSuccess(request.getMsgType(), request.getRequestId()))); |
133 | 141 | ||
134 | - subscriptionManager.onLocalSubscriptionUpdate(ctx, msg.getDeviceId(), SubscriptionType.ATTRIBUTES, s -> { | 142 | + subscriptionManager.onLocalSubscriptionUpdate(ctx, msg.getDeviceId(), TelemetryFeature.ATTRIBUTES, s -> { |
135 | List<TsKvEntry> subscriptionUpdate = new ArrayList<>(); | 143 | List<TsKvEntry> subscriptionUpdate = new ArrayList<>(); |
136 | for (AttributeKvEntry kv : request.getAttributes()) { | 144 | for (AttributeKvEntry kv : request.getAttributes()) { |
137 | if (s.isAllKeys() || s.getKeyStates().containsKey(kv.getKey())) { | 145 | if (s.isAllKeys() || s.getKeyStates().containsKey(kv.getKey())) { |
@@ -21,7 +21,12 @@ import org.springframework.util.StringUtils; | @@ -21,7 +21,12 @@ import org.springframework.util.StringUtils; | ||
21 | import org.thingsboard.server.common.data.DataConstants; | 21 | import org.thingsboard.server.common.data.DataConstants; |
22 | import org.thingsboard.server.common.data.id.EntityId; | 22 | import org.thingsboard.server.common.data.id.EntityId; |
23 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 23 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
24 | -import org.thingsboard.server.common.data.kv.*; | 24 | +import org.thingsboard.server.common.data.kv.Aggregation; |
25 | +import org.thingsboard.server.common.data.kv.AttributeKvEntry; | ||
26 | +import org.thingsboard.server.common.data.kv.BaseTsKvQuery; | ||
27 | +import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | ||
28 | +import org.thingsboard.server.common.data.kv.TsKvEntry; | ||
29 | +import org.thingsboard.server.common.data.kv.TsKvQuery; | ||
25 | import org.thingsboard.server.extensions.api.exception.UnauthorizedException; | 30 | import org.thingsboard.server.extensions.api.exception.UnauthorizedException; |
26 | import org.thingsboard.server.extensions.api.plugins.PluginCallback; | 31 | import org.thingsboard.server.extensions.api.plugins.PluginCallback; |
27 | import org.thingsboard.server.extensions.api.plugins.PluginContext; | 32 | import org.thingsboard.server.extensions.api.plugins.PluginContext; |
@@ -32,14 +37,26 @@ import org.thingsboard.server.extensions.api.plugins.ws.msg.BinaryPluginWebSocke | @@ -32,14 +37,26 @@ import org.thingsboard.server.extensions.api.plugins.ws.msg.BinaryPluginWebSocke | ||
32 | import org.thingsboard.server.extensions.api.plugins.ws.msg.PluginWebsocketMsg; | 37 | import org.thingsboard.server.extensions.api.plugins.ws.msg.PluginWebsocketMsg; |
33 | import org.thingsboard.server.extensions.api.plugins.ws.msg.TextPluginWebSocketMsg; | 38 | import org.thingsboard.server.extensions.api.plugins.ws.msg.TextPluginWebSocketMsg; |
34 | import org.thingsboard.server.extensions.core.plugin.telemetry.SubscriptionManager; | 39 | import org.thingsboard.server.extensions.core.plugin.telemetry.SubscriptionManager; |
35 | -import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.*; | 40 | +import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.AttributesSubscriptionCmd; |
41 | +import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.GetHistoryCmd; | ||
42 | +import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.SubscriptionCmd; | ||
43 | +import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TelemetryPluginCmd; | ||
44 | +import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TelemetryPluginCmdsWrapper; | ||
45 | +import org.thingsboard.server.extensions.core.plugin.telemetry.cmd.TimeseriesSubscriptionCmd; | ||
36 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionErrorCode; | 46 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionErrorCode; |
37 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; | 47 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionState; |
38 | -import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionType; | ||
39 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; | 48 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionUpdate; |
40 | 49 | ||
41 | import java.io.IOException; | 50 | import java.io.IOException; |
42 | -import java.util.*; | 51 | +import java.util.ArrayList; |
52 | +import java.util.Arrays; | ||
53 | +import java.util.Collections; | ||
54 | +import java.util.HashMap; | ||
55 | +import java.util.HashSet; | ||
56 | +import java.util.List; | ||
57 | +import java.util.Map; | ||
58 | +import java.util.Optional; | ||
59 | +import java.util.Set; | ||
43 | import java.util.stream.Collectors; | 60 | import java.util.stream.Collectors; |
44 | 61 | ||
45 | /** | 62 | /** |
@@ -131,7 +148,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | @@ -131,7 +148,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | ||
131 | keys.forEach(key -> subState.put(key, 0L)); | 148 | keys.forEach(key -> subState.put(key, 0L)); |
132 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 149 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
133 | 150 | ||
134 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.ATTRIBUTES, false, subState, cmd.getScope()); | 151 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.ATTRIBUTES, false, subState, cmd.getScope()); |
135 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); | 152 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); |
136 | } | 153 | } |
137 | 154 | ||
@@ -168,7 +185,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | @@ -168,7 +185,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | ||
168 | Map<String, Long> subState = new HashMap<>(attributesData.size()); | 185 | Map<String, Long> subState = new HashMap<>(attributesData.size()); |
169 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 186 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
170 | 187 | ||
171 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.ATTRIBUTES, true, subState, cmd.getScope()); | 188 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.ATTRIBUTES, true, subState, cmd.getScope()); |
172 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); | 189 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); |
173 | } | 190 | } |
174 | 191 | ||
@@ -234,7 +251,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | @@ -234,7 +251,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | ||
234 | sendWsMsg(ctx, sessionRef, new SubscriptionUpdate(cmd.getCmdId(), data)); | 251 | sendWsMsg(ctx, sessionRef, new SubscriptionUpdate(cmd.getCmdId(), data)); |
235 | Map<String, Long> subState = new HashMap<>(data.size()); | 252 | Map<String, Long> subState = new HashMap<>(data.size()); |
236 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); | 253 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); |
237 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.TIMESERIES, true, subState, cmd.getScope()); | 254 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.TIMESERIES, true, subState, cmd.getScope()); |
238 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); | 255 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); |
239 | } | 256 | } |
240 | 257 | ||
@@ -262,7 +279,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | @@ -262,7 +279,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | ||
262 | Map<String, Long> subState = new HashMap<>(keys.size()); | 279 | Map<String, Long> subState = new HashMap<>(keys.size()); |
263 | keys.forEach(key -> subState.put(key, startTs)); | 280 | keys.forEach(key -> subState.put(key, startTs)); |
264 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); | 281 | data.forEach(v -> subState.put(v.getKey(), v.getTs())); |
265 | - SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, SubscriptionType.TIMESERIES, false, subState, cmd.getScope()); | 282 | + SubscriptionState sub = new SubscriptionState(sessionId, cmd.getCmdId(), entityId, TelemetryFeature.TIMESERIES, false, subState, cmd.getScope()); |
266 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); | 283 | subscriptionManager.addLocalWsSubscription(ctx, sessionId, entityId, sub); |
267 | } | 284 | } |
268 | 285 |
@@ -20,6 +20,7 @@ import lombok.Data; | @@ -20,6 +20,7 @@ import lombok.Data; | ||
20 | import org.thingsboard.server.common.data.id.DeviceId; | 20 | import org.thingsboard.server.common.data.id.DeviceId; |
21 | import org.thingsboard.server.common.data.id.EntityId; | 21 | import org.thingsboard.server.common.data.id.EntityId; |
22 | import org.thingsboard.server.common.msg.cluster.ServerAddress; | 22 | import org.thingsboard.server.common.msg.cluster.ServerAddress; |
23 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; | ||
23 | 24 | ||
24 | import java.util.Map; | 25 | import java.util.Map; |
25 | 26 | ||
@@ -47,7 +48,7 @@ public class Subscription { | @@ -47,7 +48,7 @@ public class Subscription { | ||
47 | return getSub().getEntityId(); | 48 | return getSub().getEntityId(); |
48 | } | 49 | } |
49 | 50 | ||
50 | - public SubscriptionType getType() { | 51 | + public TelemetryFeature getType() { |
51 | return getSub().getType(); | 52 | return getSub().getType(); |
52 | } | 53 | } |
53 | 54 |
@@ -18,6 +18,7 @@ package org.thingsboard.server.extensions.core.plugin.telemetry.sub; | @@ -18,6 +18,7 @@ package org.thingsboard.server.extensions.core.plugin.telemetry.sub; | ||
18 | import lombok.AllArgsConstructor; | 18 | import lombok.AllArgsConstructor; |
19 | import lombok.Getter; | 19 | import lombok.Getter; |
20 | import org.thingsboard.server.common.data.id.EntityId; | 20 | import org.thingsboard.server.common.data.id.EntityId; |
21 | +import org.thingsboard.server.extensions.core.plugin.telemetry.handlers.TelemetryFeature; | ||
21 | 22 | ||
22 | import java.util.Map; | 23 | import java.util.Map; |
23 | 24 | ||
@@ -30,7 +31,7 @@ public class SubscriptionState { | @@ -30,7 +31,7 @@ public class SubscriptionState { | ||
30 | @Getter private final String wsSessionId; | 31 | @Getter private final String wsSessionId; |
31 | @Getter private final int subscriptionId; | 32 | @Getter private final int subscriptionId; |
32 | @Getter private final EntityId entityId; | 33 | @Getter private final EntityId entityId; |
33 | - @Getter private final SubscriptionType type; | 34 | + @Getter private final TelemetryFeature type; |
34 | @Getter private final boolean allKeys; | 35 | @Getter private final boolean allKeys; |
35 | @Getter private final Map<String, Long> keyStates; | 36 | @Getter private final Map<String, Long> keyStates; |
36 | @Getter private final String scope; | 37 | @Getter private final String scope; |
extensions-core/src/main/java/org/thingsboard/server/extensions/core/plugin/telemetry/sub/SubscriptionType.java
deleted
100644 → 0
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.extensions.core.plugin.telemetry.sub; | ||
17 | - | ||
18 | -/** | ||
19 | - * @author Andrew Shvayka | ||
20 | - */ | ||
21 | -public enum SubscriptionType { | ||
22 | - ATTRIBUTES, TIMESERIES | ||
23 | -} |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * <p> | 3 | + * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with 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 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * <p> | 7 | + * |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -63,12 +63,6 @@ public interface TbContext { | @@ -63,12 +63,6 @@ public interface TbContext { | ||
63 | 63 | ||
64 | void tellError(TbMsg msg, Throwable th); | 64 | void tellError(TbMsg msg, Throwable th); |
65 | 65 | ||
66 | - void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, FutureCallback<Void> callback); | ||
67 | - | ||
68 | - void saveAndNotify(EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Void> callback); | ||
69 | - | ||
70 | - void saveAndNotify(EntityId entityId, String scope, Set<AttributeKvEntry> attributes, FutureCallback<Void> callback); | ||
71 | - | ||
72 | RuleNodeId getSelfId(); | 66 | RuleNodeId getSelfId(); |
73 | 67 | ||
74 | AttributesService getAttributesService(); | 68 | AttributesService getAttributesService(); |
@@ -89,7 +89,7 @@ public class TbTransformMsgNodeTest { | @@ -89,7 +89,7 @@ public class TbTransformMsgNodeTest { | ||
89 | 89 | ||
90 | @Test | 90 | @Test |
91 | public void payloadCanBeUpdated() throws TbNodeException { | 91 | public void payloadCanBeUpdated() throws TbNodeException { |
92 | - initWithScript("return msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine' "); | 92 | + initWithScript("msg.passed = msg.passed * metadata.temp; return msg.bigObj.newProp = 'Ukraine' "); |
93 | TbMsgMetaData metaData = new TbMsgMetaData(); | 93 | TbMsgMetaData metaData = new TbMsgMetaData(); |
94 | metaData.putValue("temp", "7"); | 94 | metaData.putValue("temp", "7"); |
95 | metaData.putValue("humidity", "99"); | 95 | metaData.putValue("humidity", "99"); |