Commit 6d8cb480e9fed0527613ae3bf41bd933ab2adbb1

Authored by Andrew Shvayka
1 parent 5e2667d3

Fixed compilation issues

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
  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 }
  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;
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");