Commit ccd4f4b09692c7b1f673e28238007f19182f744a

Authored by Andrew Shvayka
1 parent 15f442fb

Improvements

... ... @@ -18,6 +18,8 @@ package org.thingsboard.server.common.msg.core;
18 18 import lombok.ToString;
19 19 import org.thingsboard.server.common.msg.session.MsgType;
20 20
  21 +import java.util.Collections;
  22 +import java.util.Optional;
21 23 import java.util.Set;
22 24
23 25 @ToString
... ... @@ -28,6 +30,10 @@ public class BasicGetAttributesRequest extends BasicRequest implements GetAttrib
28 30 private final Set<String> clientKeys;
29 31 private final Set<String> sharedKeys;
30 32
  33 + public BasicGetAttributesRequest(Integer requestId) {
  34 + this(requestId, Collections.emptySet(), Collections.emptySet());
  35 + }
  36 +
31 37 public BasicGetAttributesRequest(Integer requestId, Set<String> clientKeys, Set<String> sharedKeys) {
32 38 super(requestId);
33 39 this.clientKeys = clientKeys;
... ... @@ -40,13 +46,13 @@ public class BasicGetAttributesRequest extends BasicRequest implements GetAttrib
40 46 }
41 47
42 48 @Override
43   - public Set<String> getClientAttributeNames() {
44   - return clientKeys;
  49 + public Optional<Set<String>> getClientAttributeNames() {
  50 + return Optional.of(clientKeys);
45 51 }
46 52
47 53 @Override
48   - public Set<String> getSharedAttributeNames() {
49   - return sharedKeys;
  54 + public Optional<Set<String>> getSharedAttributeNames() {
  55 + return Optional.ofNullable(sharedKeys);
50 56 }
51 57
52 58 }
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.common.msg.core;
17 17
  18 +import java.util.Optional;
18 19 import java.util.Set;
19 20
20 21 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
... ... @@ -22,7 +23,7 @@ import org.thingsboard.server.common.msg.session.FromDeviceRequestMsg;
22 23
23 24 public interface GetAttributesRequest extends FromDeviceRequestMsg {
24 25
25   - Set<String> getClientAttributeNames();
26   - Set<String> getSharedAttributeNames();
  26 + Optional<Set<String>> getClientAttributeNames();
  27 + Optional<Set<String>> getSharedAttributeNames();
27 28
28 29 }
... ...
... ... @@ -24,10 +24,6 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.sub.SubscriptionT
24 24 @NoArgsConstructor
25 25 public class AttributesSubscriptionCmd extends SubscriptionCmd {
26 26
27   - public AttributesSubscriptionCmd(int cmdId, String deviceId, String keys, boolean unsubscribe) {
28   - super(cmdId, deviceId, keys, unsubscribe);
29   - }
30   -
31 27 @Override
32 28 public SubscriptionType getType() {
33 29 return SubscriptionType.ATTRIBUTES;
... ...
... ... @@ -26,6 +26,7 @@ public abstract class SubscriptionCmd implements TelemetryPluginCmd {
26 26 private int cmdId;
27 27 private String deviceId;
28 28 private String keys;
  29 + private String scope;
29 30 private boolean unsubscribe;
30 31
31 32 public abstract SubscriptionType getType();
... ... @@ -62,6 +63,14 @@ public abstract class SubscriptionCmd implements TelemetryPluginCmd {
62 63 this.unsubscribe = unsubscribe;
63 64 }
64 65
  66 + public String getScope() {
  67 + return scope;
  68 + }
  69 +
  70 + public void setKeys(String keys) {
  71 + this.keys = keys;
  72 + }
  73 +
65 74 @Override
66 75 public String toString() {
67 76 return "SubscriptionCmd [deviceId=" + deviceId + ", tags=" + keys + ", unsubscribe=" + unsubscribe + "]";
... ...
... ... @@ -26,11 +26,6 @@ public class TimeseriesSubscriptionCmd extends SubscriptionCmd {
26 26
27 27 private long timeWindow;
28 28
29   - public TimeseriesSubscriptionCmd(int cmdId, String deviceId, String keys, boolean unsubscribe, long timeWindow) {
30   - super(cmdId, deviceId, keys, unsubscribe);
31   - this.timeWindow = timeWindow;
32   - }
33   -
34 29 public long getTimeWindow() {
35 30 return timeWindow;
36 31 }
... ...
... ... @@ -58,10 +58,14 @@ public class TelemetryRuleMsgHandler extends DefaultRuleMsgHandler {
58 58 ctx.reply(new ResponsePluginToRuleMsg(msg.getUid(), tenantId, ruleId, response));
59 59 }
60 60
61   - private List<AttributeKvEntry> getAttributeKvEntries(PluginContext ctx, DeviceId deviceId, String scope, Set<String> names) {
  61 + private List<AttributeKvEntry> getAttributeKvEntries(PluginContext ctx, DeviceId deviceId, String scope, Optional<Set<String>> names) {
62 62 List<AttributeKvEntry> attributes;
63   - if (!names.isEmpty()) {
64   - attributes = ctx.loadAttributes(deviceId, scope, new ArrayList<>(names));
  63 + if (names.isPresent()) {
  64 + if (!names.get().isEmpty()) {
  65 + attributes = ctx.loadAttributes(deviceId, scope, new ArrayList<>(names.get()));
  66 + } else {
  67 + attributes = ctx.loadAttributes(deviceId, scope);
  68 + }
65 69 } else {
66 70 attributes = Collections.emptyList();
67 71 }
... ...
... ... @@ -105,7 +105,12 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler {
105 105 if (keysOptional.isPresent()) {
106 106 List<String> keys = new ArrayList<>(keysOptional.get());
107 107 List<AttributeKvEntry> data = new ArrayList<>();
108   - Arrays.stream(DataConstants.ALL_SCOPES).forEach(s -> data.addAll(ctx.loadAttributes(deviceId, s, keys)));
  108 + if (StringUtils.isEmpty(cmd.getScope())) {
  109 + Arrays.stream(DataConstants.ALL_SCOPES).forEach(s -> data.addAll(ctx.loadAttributes(deviceId, s, keys)));
  110 + } else {
  111 + data.addAll(ctx.loadAttributes(deviceId, cmd.getScope(), keys));
  112 + }
  113 +
109 114 List<TsKvEntry> attributesData = data.stream().map(d -> new BasicTsKvEntry(d.getLastUpdateTs(), d)).collect(Collectors.toList());
110 115 sendWsMsg(ctx, sessionRef, new SubscriptionUpdate(cmd.getCmdId(), attributesData));
111 116
... ... @@ -116,7 +121,11 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler {
116 121 sub = new SubscriptionState(sessionId, cmd.getCmdId(), deviceId, SubscriptionType.ATTRIBUTES, false, subState);
117 122 } else {
118 123 List<AttributeKvEntry> data = new ArrayList<>();
119   - Arrays.stream(DataConstants.ALL_SCOPES).forEach(s -> data.addAll(ctx.loadAttributes(deviceId, s)));
  124 + if (StringUtils.isEmpty(cmd.getScope())) {
  125 + Arrays.stream(DataConstants.ALL_SCOPES).forEach(s -> data.addAll(ctx.loadAttributes(deviceId, s)));
  126 + } else {
  127 + data.addAll(ctx.loadAttributes(deviceId, cmd.getScope()));
  128 + }
120 129 List<TsKvEntry> attributesData = data.stream().map(d -> new BasicTsKvEntry(d.getLastUpdateTs(), d)).collect(Collectors.toList());
121 130 sendWsMsg(ctx, sessionRef, new SubscriptionUpdate(cmd.getCmdId(), attributesData));
122 131
... ...
... ... @@ -167,17 +167,13 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
167 167
168 168 private FromDeviceMsg convertToGetAttributesRequest(SessionContext ctx, Request inbound) throws AdaptorException {
169 169 List<String> queryElements = inbound.getOptions().getUriQuery();
170   - if (queryElements == null || queryElements.size() == 0) {
171   - log.warn("[{}] Query is empty!", ctx.getSessionId());
172   - throw new AdaptorException(new IllegalArgumentException("Query is empty!"));
173   - }
174   -
175   - Set<String> clientKeys = toKeys(ctx, queryElements, "clientKeys");
176   - Set<String> sharedKeys = toKeys(ctx, queryElements, "sharedKeys");
177   - if (clientKeys.isEmpty() && sharedKeys.isEmpty()) {
178   - throw new AdaptorException("No clientKeys and serverKeys parameters!");
  170 + if (queryElements != null || queryElements.size() > 0) {
  171 + Set<String> clientKeys = toKeys(ctx, queryElements, "clientKeys");
  172 + Set<String> sharedKeys = toKeys(ctx, queryElements, "sharedKeys");
  173 + return new BasicGetAttributesRequest(0, clientKeys, sharedKeys);
  174 + } else {
  175 + return new BasicGetAttributesRequest(0);
179 176 }
180   - return new BasicGetAttributesRequest(0, clientKeys, sharedKeys);
181 177 }
182 178
183 179 private Set<String> toKeys(SessionContext ctx, List<String> queryElements, String attributeName) throws AdaptorException {
... ... @@ -191,7 +187,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
191 187 if (!StringUtils.isEmpty(keys)) {
192 188 return new HashSet<>(Arrays.asList(keys.split(",")));
193 189 } else {
194   - return Collections.emptySet();
  190 + return null;
195 191 }
196 192 }
197 193
... ...
... ... @@ -182,7 +182,7 @@ public class CoapServerTest {
182 182 public void testNoKeysAttributesGetRequest() {
183 183 CoapClient client = new CoapClient(getBaseTestUrl() + DEVICE1_TOKEN + "/" + FeatureType.ATTRIBUTES.name().toLowerCase() + "?data=key1,key2");
184 184 CoapResponse response = client.setTimeout(6000).get();
185   - Assert.assertEquals(ResponseCode.BAD_REQUEST, response.getCode());
  185 + Assert.assertEquals(ResponseCode.CONTENT, response.getCode());
186 186 }
187 187
188 188 @Test
... ...
... ... @@ -38,6 +38,7 @@ import org.thingsboard.server.common.transport.auth.DeviceAuthService;
38 38 import org.thingsboard.server.transport.http.session.HttpSessionCtx;
39 39
40 40 import java.util.Arrays;
  41 +import java.util.Collections;
41 42 import java.util.HashSet;
42 43 import java.util.Set;
43 44
... ... @@ -60,20 +61,22 @@ public class DeviceApiController {
60 61
61 62 @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = "application/json")
62 63 public DeferredResult<ResponseEntity> getDeviceAttributes(@PathVariable("deviceToken") String deviceToken,
63   - @RequestParam(value = "clientKeys", required = false) String clientKeys,
64   - @RequestParam(value = "sharedKeys", required = false) String sharedKeys) {
  64 + @RequestParam(value = "clientKeys", required = false, defaultValue = "") String clientKeys,
  65 + @RequestParam(value = "sharedKeys", required = false, defaultValue = "") String sharedKeys) {
65 66 DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
66   - if (StringUtils.isEmpty(clientKeys) && StringUtils.isEmpty(sharedKeys)) {
67   - responseWriter.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
68   - } else {
69   - HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
70   - if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
71   - Set<String> clientKeySet = new HashSet<>(Arrays.asList(clientKeys.split(",")));
72   - Set<String> sharedKeySet = new HashSet<>(Arrays.asList(clientKeys.split(",")));
73   - process(ctx, new BasicGetAttributesRequest(0, clientKeySet, sharedKeySet));
  67 + HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
  68 + if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
  69 + GetAttributesRequest request;
  70 + if (StringUtils.isEmpty(clientKeys) && StringUtils.isEmpty(sharedKeys)) {
  71 + request = new BasicGetAttributesRequest(0);
74 72 } else {
75   - responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
  73 + Set<String> clientKeySet = !StringUtils.isEmpty(clientKeys) ? new HashSet<>(Arrays.asList(clientKeys.split(","))) : null;
  74 + Set<String> sharedKeySet = !StringUtils.isEmpty(sharedKeys) ? new HashSet<>(Arrays.asList(sharedKeys.split(","))) : null;
  75 + request = new BasicGetAttributesRequest(0, clientKeySet, sharedKeySet);
76 76 }
  77 + process(ctx, request);
  78 + } else {
  79 + responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
77 80 }
78 81
79 82 return responseWriter;
... ...
... ... @@ -162,8 +162,13 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
162 162 Integer requestId = Integer.valueOf(topicName.substring(MqttTransportHandler.ATTRIBUTES_REQUEST_TOPIC_PREFIX.length()));
163 163 String payload = inbound.payload().toString(UTF8);
164 164 JsonElement requestBody = new JsonParser().parse(payload);
165   - return new BasicGetAttributesRequest(requestId,
166   - toStringSet(requestBody, "clientKeys"), toStringSet(requestBody, "sharedKeys"));
  165 + Set<String> clientKeys = toStringSet(requestBody, "clientKeys");
  166 + Set<String> sharedKeys = toStringSet(requestBody, "sharedKeys");
  167 + if (clientKeys == null && sharedKeys == null) {
  168 + return new BasicGetAttributesRequest(requestId);
  169 + } else {
  170 + return new BasicGetAttributesRequest(requestId, clientKeys, sharedKeys);
  171 + }
167 172 } catch (RuntimeException e) {
168 173 log.warn("Failed to decode get attributes request", e);
169 174 throw new AdaptorException(e);
... ... @@ -189,7 +194,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
189 194 if (element != null) {
190 195 return new HashSet<>(Arrays.asList(element.getAsString().split(",")));
191 196 } else {
192   - return Collections.emptySet();
  197 + return null;
193 198 }
194 199 }
195 200
... ...
... ... @@ -293,7 +293,8 @@ function DeviceService($http, $q, $filter, telemetryWebsocketService, types) {
293 293 var deviceAttributesSubscription = deviceAttributesSubscriptionMap[subscriptionId];
294 294 if (!deviceAttributesSubscription) {
295 295 var subscriptionCommand = {
296   - deviceId: deviceId
  296 + deviceId: deviceId,
  297 + scope: attributeScope
297 298 };
298 299
299 300 var type = attributeScope === types.latestTelemetry.value ?
... ...