Commit e5a1fb58654cb5c6b03e8007eae34f5422625a7e

Authored by Andrew Shvayka
1 parent 950ec8d6

Refactoring of Gateway API

Showing 30 changed files with 635 additions and 559 deletions
... ... @@ -411,29 +411,6 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso
411 411 }
412 412 }
413 413
414   -// private void processRpcResponses(ActorContext context, DeviceToDeviceActorMsg msg) {
415   -// SessionId sessionId = msg.getSessionId();
416   -// FromDeviceMsg inMsg = msg.getPayload();
417   -// if (inMsg.getMsgType() == SessionMsgType.TO_DEVICE_RPC_RESPONSE) {
418   -// logger.debug("[{}] Processing rpc command response [{}]", deviceId, sessionId);
419   -// ToDeviceRpcResponseMsg responseMsg = (ToDeviceRpcResponseMsg) inMsg;
420   -// ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(responseMsg.getRequestId());
421   -// boolean success = requestMd != null;
422   -// if (success) {
423   -// systemContext.getDeviceRpcService().processRpcResponseFromDevice(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(),
424   -// requestMd.getMsg().getServerAddress(), responseMsg.getData(), null));
425   -// } else {
426   -// logger.debug("[{}] Rpc command response [{}] is stale!", deviceId, responseMsg.getRequestId());
427   -// }
428   -// if (msg.getSessionType() == SessionType.SYNC) {
429   -// BasicCommandAckResponse response = success
430   -// ? BasicCommandAckResponse.onSuccess(SessionMsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId())
431   -// : BasicCommandAckResponse.onError(SessionMsgType.TO_DEVICE_RPC_REQUEST, responseMsg.getRequestId(), new TimeoutException());
432   -// sendMsgToSessionActor(new BasicActorSystemToDeviceSessionActorMsg(response, msg.getSessionId()), msg.getServerAddress());
433   -// }
434   -// }
435   -// }
436   -
437 414 void processClusterEventMsg(ClusterEventMsg msg) {
438 415 // if (!msg.isAdded()) {
439 416 // logger.debug("[{}] Clearing attributes/rpc subscription for server [{}]", deviceId, msg.getServerAddress());
... ...
... ... @@ -16,7 +16,6 @@
16 16 package org.thingsboard.server.actors.shared;
17 17
18 18 import lombok.Data;
19   -import org.thingsboard.server.common.data.id.SessionId;
20 19 import org.thingsboard.server.common.msg.MsgType;
21 20 import org.thingsboard.server.common.msg.TbActorMsg;
22 21
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -24,11 +24,16 @@ import org.springframework.beans.factory.annotation.Autowired;
24 24 import org.springframework.beans.factory.annotation.Value;
25 25 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
26 26 import org.springframework.stereotype.Service;
  27 +import org.thingsboard.server.common.data.Device;
27 28 import org.thingsboard.server.common.data.id.DeviceId;
  29 +import org.thingsboard.server.common.data.relation.EntityRelation;
28 30 import org.thingsboard.server.common.data.security.DeviceCredentials;
29 31 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
30 32 import org.thingsboard.server.dao.device.DeviceCredentialsService;
31 33 import org.thingsboard.server.dao.device.DeviceService;
  34 +import org.thingsboard.server.dao.relation.RelationService;
  35 +import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
  36 +import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg;
32 37 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
33 38 import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg;
34 39 import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg;
... ... @@ -40,8 +45,10 @@ import org.thingsboard.server.kafka.TBKafkaProducerTemplate;
40 45 import org.thingsboard.server.kafka.TbKafkaResponseTemplate;
41 46 import org.thingsboard.server.kafka.TbKafkaSettings;
42 47 import org.thingsboard.server.service.cluster.discovery.DiscoveryService;
  48 +import org.thingsboard.server.service.state.DeviceStateService;
43 49
44 50 import javax.annotation.PostConstruct;
  51 +import java.util.UUID;
45 52 import java.util.concurrent.ExecutorService;
46 53 import java.util.concurrent.Executors;
47 54
... ... @@ -78,8 +85,14 @@ public class RemoteTransportApiService implements TransportApiService {
78 85 private DeviceService deviceService;
79 86
80 87 @Autowired
  88 + private RelationService relationService;
  89 +
  90 + @Autowired
81 91 private DeviceCredentialsService deviceCredentialsService;
82 92
  93 + @Autowired
  94 + private DeviceStateService deviceStateService;
  95 +
83 96 private ExecutorService transportCallbackExecutor;
84 97
85 98 private TbKafkaResponseTemplate<TransportApiRequestMsg, TransportApiResponseMsg> transportApiTemplate;
... ... @@ -123,6 +136,8 @@ public class RemoteTransportApiService implements TransportApiService {
123 136 } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) {
124 137 ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg();
125 138 return validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);
  139 + } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {
  140 + return handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());
126 141 }
127 142 return getEmptyTransportApiResponseFuture();
128 143 }
... ... @@ -137,6 +152,32 @@ public class RemoteTransportApiService implements TransportApiService {
137 152 }
138 153 }
139 154
  155 + private ListenableFuture<TransportApiResponseMsg> handle(GetOrCreateDeviceFromGatewayRequestMsg requestMsg) {
  156 + DeviceId gatewayId = new DeviceId(new UUID(requestMsg.getGatewayIdMSB(), requestMsg.getGatewayIdLSB()));
  157 + ListenableFuture<Device> gatewayFuture = deviceService.findDeviceByIdAsync(gatewayId);
  158 + return Futures.transform(gatewayFuture, gateway -> {
  159 + Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), gateway.getName());
  160 + if (device == null) {
  161 + device = new Device();
  162 + device.setTenantId(gateway.getTenantId());
  163 + device.setName(requestMsg.getDeviceName());
  164 + device.setType(requestMsg.getDeviceType());
  165 + device.setCustomerId(gateway.getCustomerId());
  166 + device = deviceService.saveDevice(device);
  167 + relationService.saveRelationAsync(new EntityRelation(gateway.getId(), device.getId(), "Created"));
  168 + deviceStateService.onDeviceAdded(device);
  169 + }
  170 + try {
  171 + return TransportApiResponseMsg.newBuilder()
  172 + .setGetOrCreateDeviceResponseMsg(GetOrCreateDeviceFromGatewayResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).build()).build();
  173 + } catch (JsonProcessingException e) {
  174 + log.warn("[{}] Failed to lookup device by gateway id and name", gatewayId, requestMsg.getDeviceName(), e);
  175 + throw new RuntimeException(e);
  176 + }
  177 + }, transportCallbackExecutor);
  178 + }
  179 +
  180 +
140 181 private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId) {
141 182 return Futures.transform(deviceService.findDeviceByIdAsync(deviceId), device -> {
142 183 if (device == null) {
... ... @@ -144,17 +185,8 @@ public class RemoteTransportApiService implements TransportApiService {
144 185 return getEmptyTransportApiResponse();
145 186 }
146 187 try {
147   - DeviceInfoProto deviceInfoProto = DeviceInfoProto.newBuilder()
148   - .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
149   - .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits())
150   - .setDeviceIdMSB(device.getId().getId().getMostSignificantBits())
151   - .setDeviceIdLSB(device.getId().getId().getLeastSignificantBits())
152   - .setDeviceName(device.getName())
153   - .setDeviceType(device.getType())
154   - .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()))
155   - .build();
156 188 return TransportApiResponseMsg.newBuilder()
157   - .setValidateTokenResponseMsg(ValidateDeviceCredentialsResponseMsg.newBuilder().setDeviceInfo(deviceInfoProto).build()).build();
  189 + .setValidateTokenResponseMsg(ValidateDeviceCredentialsResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).build()).build();
158 190 } catch (JsonProcessingException e) {
159 191 log.warn("[{}] Failed to lookup device by id", deviceId, e);
160 192 return getEmptyTransportApiResponse();
... ... @@ -162,6 +194,18 @@ public class RemoteTransportApiService implements TransportApiService {
162 194 });
163 195 }
164 196
  197 + private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
  198 + return DeviceInfoProto.newBuilder()
  199 + .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
  200 + .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits())
  201 + .setDeviceIdMSB(device.getId().getId().getMostSignificantBits())
  202 + .setDeviceIdLSB(device.getId().getId().getLeastSignificantBits())
  203 + .setDeviceName(device.getName())
  204 + .setDeviceType(device.getType())
  205 + .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()))
  206 + .build();
  207 + }
  208 +
165 209 private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() {
166 210 return Futures.immediateFuture(getEmptyTransportApiResponse());
167 211 }
... ...
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.common.data.id;
17   -
18   -import java.io.Serializable;
19   -
20   -public interface SessionId extends Serializable {
21   -
22   - String toUidStr();
23   -
24   -}
... ... @@ -15,8 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.common.msg.aware;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19   -
20 18 public interface SessionAwareMsg {
21 19
22 20 SessionId getSessionId();
... ...
... ... @@ -16,11 +16,8 @@
16 16 package org.thingsboard.server.common.msg.core;
17 17
18 18 import lombok.Data;
19   -import org.thingsboard.server.common.data.id.SessionId;
20   -import org.thingsboard.server.common.msg.aware.SessionAwareMsg;
21 19 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
22 20 import org.thingsboard.server.common.msg.session.SessionMsgType;
23   -import org.thingsboard.server.common.msg.session.SessionMsgType;
24 21
25 22 /**
26 23 * @author Andrew Shvayka
... ...
... ... @@ -15,8 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.common.msg.session;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19   -
20 18 public class BasicSessionMsg implements SessionMsg {
21 19
22 20 private final SessionContext ctx;
... ...
... ... @@ -18,7 +18,6 @@ package org.thingsboard.server.common.msg.session;
18 18 import org.thingsboard.server.common.data.Device;
19 19 import org.thingsboard.server.common.data.id.CustomerId;
20 20 import org.thingsboard.server.common.data.id.DeviceId;
21   -import org.thingsboard.server.common.data.id.SessionId;
22 21 import org.thingsboard.server.common.data.id.TenantId;
23 22 import org.thingsboard.server.common.msg.MsgType;
24 23
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -15,21 +15,11 @@
15 15 */
16 16 package org.thingsboard.server.common.msg.session;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19   -import org.thingsboard.server.common.msg.session.ex.SessionException;
  18 +import java.util.UUID;
20 19
21 20 public interface SessionContext {
22 21
23   - SessionId getSessionId();
24   -
25   - SessionType getSessionType();
26   -
27   - void onMsg(SessionActorToAdaptorMsg msg) throws SessionException;
28   -
29   - void onMsg(SessionCtrlMsg msg) throws SessionException;
30   -
31   - boolean isClosed();
32   -
33   - long getTimeout();
  22 + UUID getSessionId();
34 23
  24 + int nextMsgId();
35 25 }
... ...
... ... @@ -15,7 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.common.msg.session.ctrl;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19 18 import org.thingsboard.server.common.msg.MsgType;
20 19 import org.thingsboard.server.common.msg.session.SessionCtrlMsg;
21 20
... ...
... ... @@ -15,19 +15,8 @@
15 15 */
16 16 package org.thingsboard.server.common.transport;
17 17
18   -import org.thingsboard.server.common.msg.session.AdaptorToSessionActorMsg;
19   -import org.thingsboard.server.common.msg.session.SessionMsgType;
20   -import org.thingsboard.server.common.msg.session.SessionActorToAdaptorMsg;
21 18 import org.thingsboard.server.common.msg.session.SessionContext;
22   -import org.thingsboard.server.common.transport.adaptor.AdaptorException;
23   -import org.thingsboard.server.gen.transport.TransportProtos;
24   -
25   -import java.util.Optional;
26 19
27 20 public interface TransportAdaptor<C extends SessionContext, T, V> {
28 21
29   - AdaptorToSessionActorMsg convertToActorMsg(C ctx, SessionMsgType type, T inbound) throws AdaptorException;
30   -
31   - Optional<V> convertToAdaptorMsg(C ctx, SessionActorToAdaptorMsg msg) throws AdaptorException;
32   -
33 22 }
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.common.transport;
17 17
  18 +import org.thingsboard.server.gen.transport.TransportProtos;
18 19 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
19 20 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
20 21 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg;
... ... @@ -39,6 +40,9 @@ public interface TransportService {
39 40 void process(ValidateDeviceX509CertRequestMsg msg,
40 41 TransportServiceCallback<ValidateDeviceCredentialsResponseMsg> callback);
41 42
  43 + void process(TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg msg,
  44 + TransportServiceCallback<TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg> callback);
  45 +
42 46 void process(SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback);
43 47
44 48 void process(SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback);
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -52,7 +52,8 @@ import java.util.stream.Collectors;
52 52 public class JsonConverter {
53 53
54 54 private static final Gson GSON = new Gson();
55   - public static final String CAN_T_PARSE_VALUE = "Can't parse value: ";
  55 + private static final String CAN_T_PARSE_VALUE = "Can't parse value: ";
  56 + private static final String DEVICE_PROPERTY = "device";
56 57
57 58 public static TelemetryUploadRequest convertToTelemetry(JsonElement jsonObject) throws JsonSyntaxException {
58 59 return convertToTelemetry(jsonObject, BasicRequest.DEFAULT_REQUEST_ID);
... ... @@ -318,6 +319,57 @@ public class JsonConverter {
318 319 return result;
319 320 }
320 321
  322 + public static JsonObject getJsonObjectForGateway(TransportProtos.GetAttributeResponseMsg responseMsg) {
  323 + JsonObject result = new JsonObject();
  324 + result.addProperty("id", responseMsg.getRequestId());
  325 + if (responseMsg.getClientAttributeListCount() > 0) {
  326 + addValues(result, responseMsg.getClientAttributeListList());
  327 + }
  328 + if (responseMsg.getSharedAttributeListCount() > 0) {
  329 + addValues(result, responseMsg.getSharedAttributeListList());
  330 + }
  331 + return result;
  332 + }
  333 +
  334 + public static JsonObject getJsonObjectForGateway(String deviceName, AttributeUpdateNotificationMsg notificationMsg) {
  335 + JsonObject result = new JsonObject();
  336 + result.addProperty(DEVICE_PROPERTY, deviceName);
  337 + result.add("data", toJson(notificationMsg));
  338 + return result;
  339 + }
  340 +
  341 + private static void addValues(JsonObject result, List<TransportProtos.TsKvProto> kvList) {
  342 + if (kvList.size() == 1) {
  343 + addValueToJson(result, "value", kvList.get(0).getKv());
  344 + } else {
  345 + JsonObject values;
  346 + if (result.has("values")) {
  347 + values = result.get("values").getAsJsonObject();
  348 + } else {
  349 + values = new JsonObject();
  350 + result.add("values", values);
  351 + }
  352 + kvList.forEach(value -> addValueToJson(values, value.getKv().getKey(), value.getKv()));
  353 + }
  354 + }
  355 +
  356 + private static void addValueToJson(JsonObject json, String name, TransportProtos.KeyValueProto entry) {
  357 + switch (entry.getType()) {
  358 + case BOOLEAN_V:
  359 + json.addProperty(name, entry.getBoolV());
  360 + break;
  361 + case STRING_V:
  362 + json.addProperty(name, entry.getStringV());
  363 + break;
  364 + case DOUBLE_V:
  365 + json.addProperty(name, entry.getDoubleV());
  366 + break;
  367 + case LONG_V:
  368 + json.addProperty(name, entry.getLongV());
  369 + break;
  370 + }
  371 + }
  372 +
321 373 private static Consumer<AttributeKey> addToObject(JsonArray result) {
322 374 return key -> result.add(key.getAttributeKey());
323 375 }
... ...
... ... @@ -31,16 +31,9 @@ public abstract class DeviceAwareSessionContext implements SessionContext {
31 31
32 32 @Getter
33 33 private volatile DeviceId deviceId;
  34 + @Getter
34 35 private volatile DeviceInfoProto deviceInfo;
35 36
36   - public long getDeviceIdMSB() {
37   - return deviceInfo.getDeviceIdMSB();
38   - }
39   -
40   - public long getDeviceIdLSB() {
41   - return deviceInfo.getDeviceIdLSB();
42   - }
43   -
44 37 public DeviceId getDeviceId() {
45 38 return deviceId;
46 39 }
... ...
... ... @@ -125,6 +125,17 @@ message ValidateDeviceCredentialsResponseMsg {
125 125 DeviceInfoProto deviceInfo = 1;
126 126 }
127 127
  128 +message GetOrCreateDeviceFromGatewayRequestMsg {
  129 + int64 gatewayIdMSB = 1;
  130 + int64 gatewayIdLSB = 2;
  131 + string deviceName = 3;
  132 + string deviceType = 4;
  133 +}
  134 +
  135 +message GetOrCreateDeviceFromGatewayResponseMsg {
  136 + DeviceInfoProto deviceInfo = 1;
  137 +}
  138 +
128 139 message SessionCloseNotificationProto {
129 140 string message = 1;
130 141 }
... ... @@ -196,8 +207,10 @@ message ToTransportMsg {
196 207 message TransportApiRequestMsg {
197 208 ValidateDeviceTokenRequestMsg validateTokenRequestMsg = 1;
198 209 ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2;
  210 + GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3;
199 211 }
200 212
201 213 message TransportApiResponseMsg {
202 214 ValidateDeviceCredentialsResponseMsg validateTokenResponseMsg = 1;
  215 + GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2;
203 216 }
\ No newline at end of file
... ...
... ... @@ -27,7 +27,6 @@ import org.eclipse.californium.core.network.Exchange;
27 27 import org.eclipse.californium.core.network.ExchangeObserver;
28 28 import org.eclipse.californium.core.server.resources.CoapExchange;
29 29 import org.eclipse.californium.core.server.resources.Resource;
30   -import org.thingsboard.server.common.data.id.SessionId;
31 30 import org.thingsboard.server.common.data.security.DeviceCredentialsFilter;
32 31 import org.thingsboard.server.common.data.security.DeviceTokenCredentials;
33 32 import org.thingsboard.server.common.msg.session.*;
... ...
... ... @@ -20,20 +20,16 @@ import org.eclipse.californium.core.coap.CoAP.ResponseCode;
20 20 import org.eclipse.californium.core.coap.Request;
21 21 import org.eclipse.californium.core.coap.Response;
22 22 import org.eclipse.californium.core.server.resources.CoapExchange;
23   -import org.thingsboard.server.common.data.id.SessionId;
24 23 import org.thingsboard.server.common.msg.session.SessionActorToAdaptorMsg;
25 24 import org.thingsboard.server.common.msg.session.SessionCtrlMsg;
26 25 import org.thingsboard.server.common.msg.session.SessionType;
27 26 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
28   -import org.thingsboard.server.common.msg.session.ex.SessionAuthException;
29 27 import org.thingsboard.server.common.msg.session.ex.SessionException;
30 28 import org.thingsboard.server.common.transport.SessionMsgProcessor;
31 29 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
32 30 import org.thingsboard.server.common.transport.auth.DeviceAuthService;
33 31 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
34 32 import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor;
35   -import org.slf4j.Logger;
36   -import org.slf4j.LoggerFactory;
37 33
38 34 import java.util.concurrent.atomic.AtomicInteger;
39 35
... ...
... ... @@ -15,8 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.transport.coap.session;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19   -
20 18 public final class CoapSessionId implements SessionId {
21 19
22 20 private final String clientAddress;
... ...
... ... @@ -20,7 +20,6 @@ import lombok.extern.slf4j.Slf4j;
20 20 import org.springframework.http.HttpStatus;
21 21 import org.springframework.http.ResponseEntity;
22 22 import org.springframework.web.context.request.async.DeferredResult;
23   -import org.thingsboard.server.common.data.id.SessionId;
24 23 import org.thingsboard.server.common.msg.core.*;
25 24 import org.thingsboard.server.common.msg.session.*;
26 25 import org.thingsboard.server.common.msg.session.ex.SessionException;
... ...
... ... @@ -15,8 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.transport.http.session;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19   -
20 18 import java.util.UUID;
21 19
22 20 /**
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.mqtt;
18 18 import com.fasterxml.jackson.databind.ObjectMapper;
19 19 import io.netty.handler.ssl.SslHandler;
20 20 import lombok.Data;
  21 +import lombok.Getter;
21 22 import lombok.extern.slf4j.Slf4j;
22 23 import org.apache.commons.lang3.RandomStringUtils;
23 24 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -30,8 +31,11 @@ import org.thingsboard.server.common.transport.quota.host.HostRequestsQuotaServi
30 31 import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
31 32
32 33 import javax.annotation.PostConstruct;
  34 +import javax.annotation.PreDestroy;
33 35 import java.net.InetAddress;
34 36 import java.net.UnknownHostException;
  37 +import java.util.concurrent.ExecutorService;
  38 +import java.util.concurrent.Executors;
35 39
36 40 /**
37 41 * Created by ashvayka on 04.10.18.
... ... @@ -64,6 +68,9 @@ public class MqttTransportContext {
64 68
65 69 private SslHandler sslHandler;
66 70
  71 + @Getter
  72 + private ExecutorService executor;
  73 +
67 74 @PostConstruct
68 75 public void init() {
69 76 if (StringUtils.isEmpty(nodeId)) {
... ... @@ -74,6 +81,14 @@ public class MqttTransportContext {
74 81 }
75 82 }
76 83 log.info("Current NodeId: {}", nodeId);
  84 + executor = Executors.newCachedThreadPool();
  85 + }
  86 +
  87 + @PreDestroy
  88 + public void stop() {
  89 + if (executor != null) {
  90 + executor.shutdownNow();
  91 + }
77 92 }
78 93
79 94 }
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -108,7 +108,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
108 108 this.quotaService = context.getQuotaService();
109 109 this.sslHandler = context.getSslHandler();
110 110 this.mqttQoSMap = new ConcurrentHashMap<>();
111   - this.deviceSessionCtx = new DeviceSessionCtx(mqttQoSMap);
  111 + this.deviceSessionCtx = new DeviceSessionCtx(sessionId, mqttQoSMap);
112 112 }
113 113
114 114 @Override
... ... @@ -176,42 +176,40 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
176 176
177 177 if (topicName.startsWith(MqttTopics.BASE_GATEWAY_API_TOPIC)) {
178 178 if (gatewaySessionCtx != null) {
179   - gatewaySessionCtx.setChannel(ctx);
180   -// handleMqttPublishMsg(topicName, msgId, mqttMsg);
  179 + handleGatewayPublishMsg(topicName, msgId, mqttMsg);
181 180 }
182 181 } else {
183 182 processDevicePublish(ctx, mqttMsg, topicName, msgId);
184 183 }
185 184 }
186 185
187   - //
188   -// private void handleMqttPublishMsg(String topicName, int msgId, MqttPublishMessage mqttMsg) {
189   -// try {
190   -// switch (topicName) {
191   -// case GATEWAY_TELEMETRY_TOPIC:
192   -// gatewaySessionCtx.onDeviceTelemetry(mqttMsg);
193   -// break;
194   -// case GATEWAY_ATTRIBUTES_TOPIC:
195   -// gatewaySessionCtx.onDeviceAttributes(mqttMsg);
196   -// break;
197   -// case GATEWAY_ATTRIBUTES_REQUEST_TOPIC:
198   -// gatewaySessionCtx.onDeviceAttributesRequest(mqttMsg);
199   -// break;
200   -// case GATEWAY_RPC_TOPIC:
201   -// gatewaySessionCtx.onDeviceRpcResponse(mqttMsg);
202   -// break;
203   -// case GATEWAY_CONNECT_TOPIC:
204   -// gatewaySessionCtx.onDeviceConnect(mqttMsg);
205   -// break;
206   -// case GATEWAY_DISCONNECT_TOPIC:
207   -// gatewaySessionCtx.onDeviceDisconnect(mqttMsg);
208   -// break;
209   -// }
210   -// } catch (RuntimeException | AdaptorException e) {
211   -// log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
212   -// }
213   -// }
214   -//
  186 + private void handleGatewayPublishMsg(String topicName, int msgId, MqttPublishMessage mqttMsg) {
  187 + try {
  188 + switch (topicName) {
  189 + case MqttTopics.GATEWAY_TELEMETRY_TOPIC:
  190 + gatewaySessionCtx.onDeviceTelemetry(mqttMsg);
  191 + break;
  192 + case MqttTopics.GATEWAY_ATTRIBUTES_TOPIC:
  193 + gatewaySessionCtx.onDeviceAttributes(mqttMsg);
  194 + break;
  195 + case MqttTopics.GATEWAY_ATTRIBUTES_REQUEST_TOPIC:
  196 + gatewaySessionCtx.onDeviceAttributesRequest(mqttMsg);
  197 + break;
  198 + case MqttTopics.GATEWAY_RPC_TOPIC:
  199 + gatewaySessionCtx.onDeviceRpcResponse(mqttMsg);
  200 + break;
  201 + case MqttTopics.GATEWAY_CONNECT_TOPIC:
  202 + gatewaySessionCtx.onDeviceConnect(mqttMsg);
  203 + break;
  204 + case MqttTopics.GATEWAY_DISCONNECT_TOPIC:
  205 + gatewaySessionCtx.onDeviceDisconnect(mqttMsg);
  206 + break;
  207 + }
  208 + } catch (RuntimeException | AdaptorException e) {
  209 + log.warn("[{}] Failed to process publish msg [{}][{}]", sessionId, topicName, msgId, e);
  210 + }
  211 + }
  212 +
215 213 private void processDevicePublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, String topicName, int msgId) {
216 214 try {
217 215 if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_TOPIC)) {
... ... @@ -223,10 +221,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
223 221 } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) {
224 222 TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg);
225 223 transportService.process(sessionInfo, getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
226   - } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC)){
  224 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC)) {
227 225 TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = adaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg);
228 226 transportService.process(sessionInfo, rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
229   - } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)){
  227 + } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)) {
230 228 TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = adaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg);
231 229 transportService.process(sessionInfo, rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
232 230 }
... ... @@ -469,7 +467,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
469 467 if (infoNode != null) {
470 468 JsonNode gatewayNode = infoNode.get("gateway");
471 469 if (gatewayNode != null && gatewayNode.asBoolean()) {
472   - gatewaySessionCtx = new GatewaySessionCtx(deviceSessionCtx);
  470 + gatewaySessionCtx = new GatewaySessionCtx(context, deviceSessionCtx, sessionId);
473 471 }
474 472 }
475 473 } catch (IOException e) {
... ... @@ -477,7 +475,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
477 475 }
478 476 }
479 477
480   - private SessionEventMsg getSessionEventMsg(SessionEvent event) {
  478 + public static SessionEventMsg getSessionEventMsg(SessionEvent event) {
481 479 return SessionEventMsg.newBuilder()
482 480 .setSessionType(TransportProtos.SessionType.ASYNC)
483 481 .setEvent(event).build();
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.mqtt.adaptors;
17 17
18 18 import com.google.gson.Gson;
19 19 import com.google.gson.JsonElement;
  20 +import com.google.gson.JsonObject;
20 21 import com.google.gson.JsonParser;
21 22 import com.google.gson.JsonSyntaxException;
22 23 import io.netty.buffer.ByteBuf;
... ... @@ -26,7 +27,8 @@ import io.netty.handler.codec.mqtt.*;
26 27 import lombok.extern.slf4j.Slf4j;
27 28 import org.springframework.stereotype.Component;
28 29 import org.springframework.util.StringUtils;
29   -import org.thingsboard.server.common.data.id.SessionId;
  30 +import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  31 +import org.thingsboard.server.common.data.kv.KvEntry;
30 32 import org.thingsboard.server.common.msg.core.*;
31 33 import org.thingsboard.server.common.msg.kv.AttributesKVMsg;
32 34 import org.thingsboard.server.common.msg.session.*;
... ... @@ -36,12 +38,15 @@ import org.thingsboard.server.gen.transport.TransportProtos;
36 38 import org.thingsboard.server.transport.mqtt.MqttTopics;
37 39 import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx;
38 40 import org.thingsboard.server.transport.mqtt.MqttTransportHandler;
  41 +import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext;
39 42
40 43 import java.nio.charset.Charset;
41 44 import java.util.Arrays;
42 45 import java.util.HashSet;
  46 +import java.util.List;
43 47 import java.util.Optional;
44 48 import java.util.Set;
  49 +import java.util.UUID;
45 50
46 51 /**
47 52 * @author Andrew Shvayka
... ... @@ -55,7 +60,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
55 60 private static final ByteBufAllocator ALLOCATOR = new UnpooledByteBufAllocator(false);
56 61
57 62 @Override
58   - public TransportProtos.PostTelemetryMsg convertToPostTelemetry(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  63 + public TransportProtos.PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
59 64 String payload = validatePayload(ctx.getSessionId(), inbound.payload());
60 65 try {
61 66 return JsonConverter.convertToTelemetryProto(new JsonParser().parse(payload));
... ... @@ -65,7 +70,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
65 70 }
66 71
67 72 @Override
68   - public TransportProtos.PostAttributeMsg convertToPostAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  73 + public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
69 74 String payload = validatePayload(ctx.getSessionId(), inbound.payload());
70 75 try {
71 76 return JsonConverter.convertToAttributesProto(new JsonParser().parse(payload));
... ... @@ -75,7 +80,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
75 80 }
76 81
77 82 @Override
78   - public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  83 + public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
79 84 String topicName = inbound.variableHeader().topicName();
80 85 try {
81 86 TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder();
... ... @@ -98,7 +103,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
98 103 }
99 104
100 105 @Override
101   - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  106 + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
102 107 String topicName = inbound.variableHeader().topicName();
103 108 try {
104 109 Integer requestId = Integer.valueOf(topicName.substring(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC.length()));
... ... @@ -111,7 +116,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
111 116 }
112 117
113 118 @Override
114   - public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  119 + public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
115 120 String topicName = inbound.variableHeader().topicName();
116 121 String payload = validatePayload(ctx.getSessionId(), inbound.payload());
117 122 try {
... ... @@ -123,7 +128,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
123 128 }
124 129
125 130 @Override
126   - public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
  131 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
127 132 if (!StringUtils.isEmpty(responseMsg.getError())) {
128 133 throw new AdaptorException(responseMsg.getError());
129 134 } else {
... ... @@ -138,99 +143,37 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
138 143 }
139 144
140 145 @Override
141   - public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException {
142   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_ATTRIBUTES_TOPIC, JsonConverter.toJson(notificationMsg)));
  146 + public Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException {
  147 + if (!StringUtils.isEmpty(responseMsg.getError())) {
  148 + throw new AdaptorException(responseMsg.getError());
  149 + } else {
  150 + JsonObject result = JsonConverter.getJsonObjectForGateway(responseMsg);
  151 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC, result));
  152 + }
143 153 }
144 154
145 155 @Override
146   - public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException {
147   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), JsonConverter.toJson(rpcRequest, false)));
  156 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException {
  157 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_ATTRIBUTES_TOPIC, JsonConverter.toJson(notificationMsg)));
148 158 }
149 159
150 160 @Override
151   - public Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse) {
152   - return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(), JsonConverter.toJson(rpcResponse)));
  161 + public Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException {
  162 + JsonObject result = JsonConverter.getJsonObjectForGateway(deviceName, notificationMsg);
  163 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.GATEWAY_ATTRIBUTES_TOPIC, result));
153 164 }
154 165
155 166 @Override
156   - public AdaptorToSessionActorMsg convertToActorMsg(DeviceSessionCtx ctx, SessionMsgType type, MqttMessage inbound) throws AdaptorException {
157   - FromDeviceMsg msg;
158   - switch (type) {
159   - case POST_TELEMETRY_REQUEST:
160   - msg = convertToTelemetryUploadRequest(ctx, (MqttPublishMessage) inbound);
161   - break;
162   - case POST_ATTRIBUTES_REQUEST:
163   - msg = convertToUpdateAttributesRequest(ctx, (MqttPublishMessage) inbound);
164   - break;
165   - case SUBSCRIBE_ATTRIBUTES_REQUEST:
166   - msg = new AttributesSubscribeMsg();
167   - break;
168   - case UNSUBSCRIBE_ATTRIBUTES_REQUEST:
169   - msg = new AttributesUnsubscribeMsg();
170   - break;
171   - case SUBSCRIBE_RPC_COMMANDS_REQUEST:
172   - msg = new RpcSubscribeMsg();
173   - break;
174   - case UNSUBSCRIBE_RPC_COMMANDS_REQUEST:
175   - msg = new RpcUnsubscribeMsg();
176   - break;
177   - case GET_ATTRIBUTES_REQUEST:
178   - msg = convertToGetAttributesRequest(ctx, (MqttPublishMessage) inbound);
179   - break;
180   - case TO_DEVICE_RPC_RESPONSE:
181   - msg = convertToRpcCommandResponse(ctx, (MqttPublishMessage) inbound);
182   - break;
183   - case TO_SERVER_RPC_REQUEST:
184   - msg = null;//convertToServerRpcRequest(ctx, (MqttPublishMessage) inbound);
185   - break;
186   - default:
187   - log.warn("[{}] Unsupported msg type: {}!", ctx.getSessionId(), type);
188   - throw new AdaptorException(new IllegalArgumentException("Unsupported msg type: " + type + "!"));
189   - }
190   - return new BasicAdaptorToSessionActorMsg(ctx, msg);
  167 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException {
  168 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), JsonConverter.toJson(rpcRequest, false)));
191 169 }
192 170
193 171 @Override
194   - public Optional<MqttMessage> convertToAdaptorMsg(DeviceSessionCtx ctx, SessionActorToAdaptorMsg sessionMsg) throws AdaptorException {
195   - MqttMessage result = null;
196   - ToDeviceMsg msg = sessionMsg.getMsg();
197   - switch (msg.getSessionMsgType()) {
198   - case STATUS_CODE_RESPONSE:
199   - case GET_ATTRIBUTES_RESPONSE:
200   - ResponseMsg<?> responseMsg = (ResponseMsg) msg;
201   - Optional<Exception> responseError = responseMsg.getError();
202   - if (responseMsg.isSuccess()) {
203   - result = convertResponseMsg(ctx, msg, responseMsg, responseError);
204   - } else {
205   - if (responseError.isPresent()) {
206   - throw new AdaptorException(responseError.get());
207   - }
208   - }
209   - break;
210   - case ATTRIBUTES_UPDATE_NOTIFICATION:
211   - AttributesUpdateNotification notification = (AttributesUpdateNotification) msg;
212   - result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_ATTRIBUTES_TOPIC, notification.getData(), false);
213   - break;
214   - case TO_DEVICE_RPC_REQUEST:
215   - ToDeviceRpcRequestMsg rpcRequest = (ToDeviceRpcRequestMsg) msg;
216   - result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC + rpcRequest.getRequestId(), rpcRequest);
217   - break;
218   - case TO_SERVER_RPC_RESPONSE:
219   -// ToServerRpcResponseMsg rpcResponse = (ToServerRpcResponseMsg) msg;
220   -// result = createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(),
221   -// rpcResponse);
222   - break;
223   - case RULE_ENGINE_ERROR:
224   - RuleEngineErrorMsg errorMsg = (RuleEngineErrorMsg) msg;
225   - result = createMqttPublishMsg(ctx, "errors", JsonConverter.toErrorJson(errorMsg.getErrorMsg()));
226   - break;
227   - default:
228   - break;
229   - }
230   - return Optional.ofNullable(result);
  172 + public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse) {
  173 + return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_RPC_RESPONSE_TOPIC + rpcResponse.getRequestId(), JsonConverter.toJson(rpcResponse)));
231 174 }
232 175
233   - private MqttMessage convertResponseMsg(DeviceSessionCtx ctx, ToDeviceMsg msg,
  176 + private MqttMessage convertResponseMsg(MqttDeviceAwareSessionContext ctx, ToDeviceMsg msg,
234 177 ResponseMsg<?> responseMsg, Optional<Exception> responseError) throws AdaptorException {
235 178 MqttMessage result = null;
236 179 SessionMsgType requestMsgType = responseMsg.getRequestMsgType();
... ... @@ -255,19 +198,19 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
255 198 return result;
256 199 }
257 200
258   - private MqttPublishMessage createMqttPublishMsg(DeviceSessionCtx ctx, String topic, AttributesKVMsg msg, boolean asMap) {
  201 + private MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, AttributesKVMsg msg, boolean asMap) {
259 202 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg, asMap));
260 203 }
261 204
262   - private MqttPublishMessage createMqttPublishMsg(DeviceSessionCtx ctx, String topic, ToDeviceRpcRequestMsg msg) {
  205 + private MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, ToDeviceRpcRequestMsg msg) {
263 206 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg, false));
264 207 }
265 208
266   - private MqttPublishMessage createMqttPublishMsg(DeviceSessionCtx ctx, String topic, TransportProtos.ToServerRpcResponseMsg msg) {
  209 + private MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, TransportProtos.ToServerRpcResponseMsg msg) {
267 210 return createMqttPublishMsg(ctx, topic, JsonConverter.toJson(msg));
268 211 }
269 212
270   - private MqttPublishMessage createMqttPublishMsg(DeviceSessionCtx ctx, String topic, JsonElement json) {
  213 + private MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, JsonElement json) {
271 214 MqttFixedHeader mqttFixedHeader =
272 215 new MqttFixedHeader(MqttMessageType.PUBLISH, false, ctx.getQoSForTopic(topic), false, 0);
273 216 MqttPublishVariableHeader header = new MqttPublishVariableHeader(topic, ctx.nextMsgId());
... ... @@ -276,7 +219,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
276 219 return new MqttPublishMessage(mqttFixedHeader, header, payload);
277 220 }
278 221
279   - private FromDeviceMsg convertToGetAttributesRequest(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  222 + private FromDeviceMsg convertToGetAttributesRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
280 223 String topicName = inbound.variableHeader().topicName();
281 224 try {
282 225 Integer requestId = Integer.valueOf(topicName.substring(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX.length()));
... ... @@ -295,7 +238,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
295 238 }
296 239 }
297 240
298   - private FromDeviceMsg convertToRpcCommandResponse(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException {
  241 + private FromDeviceMsg convertToRpcCommandResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
299 242 String topicName = inbound.variableHeader().topicName();
300 243 try {
301 244 Integer requestId = Integer.valueOf(topicName.substring(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC.length()));
... ... @@ -336,7 +279,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
336 279 }
337 280 }
338 281
339   - public static JsonElement validateJsonPayload(SessionId sessionId, ByteBuf payloadData) throws AdaptorException {
  282 + public static JsonElement validateJsonPayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException {
340 283 String payload = validatePayload(sessionId, payloadData);
341 284 try {
342 285 return new JsonParser().parse(payload);
... ... @@ -345,11 +288,11 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
345 288 }
346 289 }
347 290
348   - public static String validatePayload(SessionId sessionId, ByteBuf payloadData) throws AdaptorException {
  291 + public static String validatePayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException {
349 292 try {
350 293 String payload = payloadData.toString(UTF8);
351 294 if (payload == null) {
352   - log.warn("[{}] Payload is empty!", sessionId.toUidStr());
  295 + log.warn("[{}] Payload is empty!", sessionId);
353 296 throw new AdaptorException(new IllegalArgumentException("Payload is empty!"));
354 297 }
355 298 return payload;
... ...
... ... @@ -17,41 +17,44 @@ package org.thingsboard.server.transport.mqtt.adaptors;
17 17
18 18 import io.netty.handler.codec.mqtt.MqttMessage;
19 19 import io.netty.handler.codec.mqtt.MqttPublishMessage;
20   -import org.thingsboard.server.common.transport.TransportAdaptor;
21 20 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
22   -import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
23   -import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
24   -import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
25 21 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
26 22 import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
27 23 import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
28 24 import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
29 25 import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
30 26 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
31   -import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx;
  27 +import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
  28 +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
  29 +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
  30 +import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext;
32 31
33 32 import java.util.Optional;
34 33
35 34 /**
36 35 * @author Andrew Shvayka
37 36 */
38   -public interface MqttTransportAdaptor extends TransportAdaptor<DeviceSessionCtx, MqttMessage, MqttMessage> {
  37 +public interface MqttTransportAdaptor {
  38 +
  39 + PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
  40 +
  41 + PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
39 42
40   - PostTelemetryMsg convertToPostTelemetry(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException;
  43 + GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
41 44
42   - PostAttributeMsg convertToPostAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException;
  45 + ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
43 46
44   - GetAttributeRequestMsg convertToGetAttributes(DeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException;
  47 + ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
45 48
46   - ToDeviceRpcResponseMsg convertToDeviceRpcResponse(DeviceSessionCtx ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
  49 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, GetAttributeResponseMsg responseMsg) throws AdaptorException;
47 50
48   - ToServerRpcRequestMsg convertToServerRpcRequest(DeviceSessionCtx ctx, MqttPublishMessage mqttMsg) throws AdaptorException;
  51 + Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, GetAttributeResponseMsg responseMsg) throws AdaptorException;
49 52
50   - Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, GetAttributeResponseMsg responseMsg) throws AdaptorException;
  53 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
51 54
52   - Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
  55 + Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
53 56
54   - Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException;
  57 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException;
55 58
56   - Optional<MqttMessage> convertToPublish(DeviceSessionCtx ctx, ToServerRpcResponseMsg rpcResponse);
  59 + Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToServerRpcResponseMsg rpcResponse) throws AdaptorException;
57 60 }
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -19,19 +19,14 @@ import io.netty.channel.ChannelHandlerContext;
19 19 import io.netty.handler.codec.mqtt.*;
20 20 import lombok.Getter;
21 21 import lombok.extern.slf4j.Slf4j;
22   -import org.thingsboard.server.common.data.id.SessionId;
23 22 import org.thingsboard.server.common.msg.session.SessionActorToAdaptorMsg;
24 23 import org.thingsboard.server.common.msg.session.SessionCtrlMsg;
25 24 import org.thingsboard.server.common.msg.session.SessionType;
26 25 import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
27 26 import org.thingsboard.server.common.msg.session.ex.SessionException;
28   -import org.thingsboard.server.common.transport.SessionMsgProcessor;
29 27 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
30   -import org.thingsboard.server.common.transport.auth.DeviceAuthService;
31   -import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
32   -import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
33 28
34   -import java.util.Map;
  29 +import java.util.UUID;
35 30 import java.util.concurrent.ConcurrentMap;
36 31 import java.util.concurrent.atomic.AtomicInteger;
37 32
... ... @@ -41,14 +36,14 @@ import java.util.concurrent.atomic.AtomicInteger;
41 36 @Slf4j
42 37 public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
43 38
44   - private final MqttSessionId sessionId;
  39 + private final UUID sessionId;
45 40 @Getter
46 41 private ChannelHandlerContext channel;
47 42 private AtomicInteger msgIdSeq = new AtomicInteger(0);
48 43
49   - public DeviceSessionCtx(ConcurrentMap<String, Integer> mqttQoSMap) {
  44 + public DeviceSessionCtx(UUID sessionId, ConcurrentMap<String, Integer> mqttQoSMap) {
50 45 super(null, null, mqttQoSMap);
51   - this.sessionId = new MqttSessionId();
  46 + this.sessionId = sessionId;
52 47 }
53 48
54 49 @Override
... ... @@ -94,7 +89,7 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
94 89 }
95 90
96 91 @Override
97   - public SessionId getSessionId() {
  92 + public UUID getSessionId() {
98 93 return sessionId;
99 94 }
100 95
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -16,70 +16,80 @@
16 16 package org.thingsboard.server.transport.mqtt.session;
17 17
18 18 import com.google.gson.Gson;
19   -import com.google.gson.JsonArray;
20 19 import com.google.gson.JsonElement;
21 20 import com.google.gson.JsonObject;
  21 +import com.sun.xml.internal.bind.v2.TODO;
22 22 import io.netty.buffer.ByteBuf;
23 23 import io.netty.buffer.ByteBufAllocator;
24 24 import io.netty.buffer.UnpooledByteBufAllocator;
25   -import io.netty.handler.codec.mqtt.*;
26   -import org.thingsboard.server.common.data.Device;
27   -import org.thingsboard.server.common.data.id.SessionId;
  25 +import io.netty.handler.codec.mqtt.MqttFixedHeader;
  26 +import io.netty.handler.codec.mqtt.MqttMessage;
  27 +import io.netty.handler.codec.mqtt.MqttMessageType;
  28 +import io.netty.handler.codec.mqtt.MqttPublishMessage;
  29 +import io.netty.handler.codec.mqtt.MqttPublishVariableHeader;
  30 +import lombok.extern.slf4j.Slf4j;
28 31 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
29 32 import org.thingsboard.server.common.data.kv.KvEntry;
30   -import org.thingsboard.server.common.msg.core.*;
  33 +import org.thingsboard.server.common.msg.core.AttributesUpdateNotification;
  34 +import org.thingsboard.server.common.msg.core.GetAttributesResponse;
  35 +import org.thingsboard.server.common.msg.core.ResponseMsg;
  36 +import org.thingsboard.server.common.msg.core.ToDeviceRpcRequestMsg;
31 37 import org.thingsboard.server.common.msg.kv.AttributesKVMsg;
32   -import org.thingsboard.server.common.msg.session.*;
33   -import org.thingsboard.server.common.msg.session.ex.SessionException;
  38 +import org.thingsboard.server.common.msg.session.SessionActorToAdaptorMsg;
  39 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  40 +import org.thingsboard.server.common.msg.session.ToDeviceMsg;
  41 +import org.thingsboard.server.common.transport.SessionMsgListener;
34 42 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
35   -import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
  43 +import org.thingsboard.server.gen.transport.TransportProtos;
  44 +import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
  45 +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
36 46 import org.thingsboard.server.transport.mqtt.MqttTopics;
37 47 import org.thingsboard.server.transport.mqtt.MqttTransportHandler;
38 48
39 49 import java.nio.charset.Charset;
40 50 import java.util.List;
41   -import java.util.Map;
42 51 import java.util.Optional;
  52 +import java.util.UUID;
43 53 import java.util.concurrent.ConcurrentMap;
44 54 import java.util.concurrent.atomic.AtomicInteger;
45 55
46 56 /**
47 57 * Created by ashvayka on 19.01.17.
48 58 */
49   -public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext {
  59 +@Slf4j
  60 +public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext implements SessionMsgListener {
50 61
51 62 private static final Gson GSON = new Gson();
52 63 private static final Charset UTF8 = Charset.forName("UTF-8");
53 64 private static final ByteBufAllocator ALLOCATOR = new UnpooledByteBufAllocator(false);
54   - public static final String DEVICE_PROPERTY = "device";
55 65
56   - private GatewaySessionCtx parent;
57   - private final MqttSessionId sessionId;
  66 + private final GatewaySessionCtx parent;
  67 + private final UUID sessionId;
  68 + private final SessionInfoProto sessionInfo;
58 69 private volatile boolean closed;
59 70 private AtomicInteger msgIdSeq = new AtomicInteger(0);
60 71
61   - public GatewayDeviceSessionCtx(GatewaySessionCtx parent, Device device, ConcurrentMap<String, Integer> mqttQoSMap) {
62   - super(parent.getProcessor(), parent.getAuthService(), device, mqttQoSMap);
  72 + public GatewayDeviceSessionCtx(GatewaySessionCtx parent, DeviceInfoProto deviceInfo, ConcurrentMap<String, Integer> mqttQoSMap) {
  73 + super(mqttQoSMap);
63 74 this.parent = parent;
64   - this.sessionId = new MqttSessionId();
  75 + this.sessionId = UUID.randomUUID();
  76 + this.sessionInfo = SessionInfoProto.newBuilder()
  77 + .setNodeId(parent.getNodeId())
  78 + .setSessionIdMSB(sessionId.getMostSignificantBits())
  79 + .setSessionIdLSB(sessionId.getLeastSignificantBits())
  80 + .setDeviceIdMSB(deviceInfo.getDeviceIdMSB())
  81 + .setDeviceIdLSB(deviceInfo.getDeviceIdLSB())
  82 + .setTenantIdMSB(deviceInfo.getTenantIdMSB())
  83 + .setTenantIdLSB(deviceInfo.getTenantIdLSB())
  84 + .build();
  85 + setDeviceInfo(deviceInfo);
65 86 }
66 87
67 88 @Override
68   - public SessionId getSessionId() {
  89 + public UUID getSessionId() {
69 90 return sessionId;
70 91 }
71 92
72   - @Override
73   - public SessionType getSessionType() {
74   - return SessionType.ASYNC;
75   - }
76   -
77   - @Override
78   - public void onMsg(SessionActorToAdaptorMsg sessionMsg) throws SessionException {
79   - Optional<MqttMessage> message = getToDeviceMsg(sessionMsg);
80   - message.ifPresent(parent::writeAndFlush);
81   - }
82   -
83 93 private Optional<MqttMessage> getToDeviceMsg(SessionActorToAdaptorMsg sessionMsg) {
84 94 ToDeviceMsg msg = sessionMsg.getMsg();
85 95 switch (msg.getSessionMsgType()) {
... ... @@ -113,25 +123,6 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext {
113 123 return Optional.empty();
114 124 }
115 125
116   - @Override
117   - public void onMsg(SessionCtrlMsg msg) throws SessionException {
118   - //Do nothing
119   - }
120   -
121   - @Override
122   - public boolean isClosed() {
123   - return closed;
124   - }
125   -
126   - public void setClosed(boolean closed) {
127   - this.closed = closed;
128   - }
129   -
130   - @Override
131   - public long getTimeout() {
132   - return 0;
133   - }
134   -
135 126 private MqttMessage createMqttPublishMsg(String topic, GetAttributesResponse response) {
136 127 JsonObject result = new JsonObject();
137 128 result.addProperty("id", response.getRequestId());
... ... @@ -204,4 +195,40 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext {
204 195 return new MqttPublishMessage(mqttFixedHeader, header, payload);
205 196 }
206 197
  198 + SessionInfoProto getSessionInfo() {
  199 + return sessionInfo;
  200 + }
  201 +
  202 + @Override
  203 + public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg response) {
  204 + try {
  205 + parent.getAdaptor().convertToGatewayPublish(this, response).ifPresent(parent::writeAndFlush);
  206 + } catch (Exception e) {
  207 + log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e);
  208 + }
  209 + }
  210 +
  211 + @Override
  212 + public void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg notification) {
  213 + try {
  214 + parent.getAdaptor().convertToGatewayPublish(this, getDeviceInfo().getDeviceName(), notification).ifPresent(parent::writeAndFlush);
  215 + } catch (Exception e) {
  216 + log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e);
  217 + }
  218 + }
  219 +
  220 + @Override
  221 + public void onRemoteSessionCloseCommand(TransportProtos.SessionCloseNotificationProto sessionCloseNotification) {
  222 + parent.deregisterSession(getDeviceInfo().getDeviceName());
  223 + }
  224 +
  225 + @Override
  226 + public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest) {
  227 +
  228 + }
  229 +
  230 + @Override
  231 + public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg toServerResponse) {
  232 + TODO
  233 + }
207 234 }
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -15,6 +15,11 @@
15 15 */
16 16 package org.thingsboard.server.transport.mqtt.session;
17 17
  18 +
  19 +import com.google.common.util.concurrent.FutureCallback;
  20 +import com.google.common.util.concurrent.Futures;
  21 +import com.google.common.util.concurrent.ListenableFuture;
  22 +import com.google.common.util.concurrent.SettableFuture;
18 23 import com.google.gson.JsonArray;
19 24 import com.google.gson.JsonElement;
20 25 import com.google.gson.JsonNull;
... ... @@ -25,28 +30,28 @@ import io.netty.handler.codec.mqtt.MqttMessage;
25 30 import io.netty.handler.codec.mqtt.MqttPublishMessage;
26 31 import lombok.extern.slf4j.Slf4j;
27 32 import org.springframework.util.StringUtils;
28   -import org.thingsboard.server.common.data.Device;
29   -import org.thingsboard.server.common.data.id.SessionId;
30   -import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
31   -import org.thingsboard.server.common.data.relation.EntityRelation;
32   -import org.thingsboard.server.common.msg.core.*;
33   -import org.thingsboard.server.common.msg.session.BasicAdaptorToSessionActorMsg;
34   -import org.thingsboard.server.common.msg.session.BasicTransportToDeviceSessionActorMsg;
35   -import org.thingsboard.server.common.msg.session.ctrl.SessionCloseMsg;
36   -import org.thingsboard.server.common.transport.SessionMsgProcessor;
  33 +import org.thingsboard.server.common.transport.TransportService;
  34 +import org.thingsboard.server.common.transport.TransportServiceCallback;
37 35 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
38 36 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
39   -import org.thingsboard.server.common.transport.auth.DeviceAuthService;
40   -import org.thingsboard.server.dao.device.DeviceService;
41   -import org.thingsboard.server.dao.relation.RelationService;
  37 +import org.thingsboard.server.gen.transport.TransportProtos;
  38 +import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
  39 +import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
  40 +import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg;
  41 +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
  42 +import org.thingsboard.server.transport.mqtt.MqttTransportContext;
42 43 import org.thingsboard.server.transport.mqtt.MqttTransportHandler;
43 44 import org.thingsboard.server.transport.mqtt.adaptors.JsonMqttAdaptor;
  45 +import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
44 46
45   -import java.util.*;
  47 +import javax.annotation.Nullable;
  48 +import java.util.Collections;
  49 +import java.util.HashSet;
  50 +import java.util.Map;
  51 +import java.util.Set;
  52 +import java.util.UUID;
  53 +import java.util.concurrent.ConcurrentHashMap;
46 54 import java.util.concurrent.ConcurrentMap;
47   -import java.util.stream.Collectors;
48   -
49   -import static org.thingsboard.server.transport.mqtt.adaptors.JsonMqttAdaptor.validateJsonPayload;
50 55
51 56 /**
52 57 * Created by ashvayka on 19.01.17.
... ... @@ -55,184 +60,235 @@ import static org.thingsboard.server.transport.mqtt.adaptors.JsonMqttAdaptor.val
55 60 public class GatewaySessionCtx {
56 61
57 62 private static final String DEFAULT_DEVICE_TYPE = "default";
58   - public static final String CAN_T_PARSE_VALUE = "Can't parse value: ";
59   - public static final String DEVICE_PROPERTY = "device";
60   -// private final Device gateway;
61   -// private final SessionId gatewaySessionId;
62   -// private final SessionMsgProcessor processor;
63   -// private final DeviceService deviceService;
64   -// private final DeviceAuthService authService;
65   -// private final RelationService relationService;
66   -// private final Map<String, GatewayDeviceSessionCtx> devices;
67   -// private final ConcurrentMap<String, Integer> mqttQoSMap;
68   - private ChannelHandlerContext channel;
69   -
70   -// public GatewaySessionCtx(SessionMsgProcessor processor, DeviceService deviceService, DeviceAuthService authService, RelationService relationService, DeviceSessionCtx gatewaySessionCtx) {
71   -// this.processor = processor;
72   -// this.deviceService = deviceService;
73   -// this.authService = authService;
74   -// this.relationService = relationService;
75   -// this.gateway = gatewaySessionCtx.getDevice();
76   -// this.gatewaySessionId = gatewaySessionCtx.getSessionId();
77   -// this.devices = new HashMap<>();
78   -// this.mqttQoSMap = gatewaySessionCtx.getMqttQoSMap();
79   -// }
80   -
81   - public GatewaySessionCtx(DeviceSessionCtx deviceSessionCtx) {
  63 + private static final String CAN_T_PARSE_VALUE = "Can't parse value: ";
  64 + private static final String DEVICE_PROPERTY = "device";
  65 +
  66 + private final MqttTransportContext context;
  67 + private final TransportService transportService;
  68 + private final DeviceInfoProto gateway;
  69 + private final UUID sessionId;
  70 + private final Map<String, GatewayDeviceSessionCtx> devices;
  71 + private final ConcurrentMap<String, Integer> mqttQoSMap;
  72 + private final ChannelHandlerContext channel;
82 73
  74 + public GatewaySessionCtx(MqttTransportContext context, DeviceSessionCtx deviceSessionCtx, UUID sessionId) {
  75 + this.context = context;
  76 + this.transportService = context.getTransportService();
  77 + this.gateway = deviceSessionCtx.getDeviceInfo();
  78 + this.sessionId = sessionId;
  79 + this.devices = new ConcurrentHashMap<>();
  80 + this.mqttQoSMap = deviceSessionCtx.getMqttQoSMap();
  81 + this.channel = deviceSessionCtx.getChannel();
83 82 }
84 83
85 84 public void onDeviceConnect(MqttPublishMessage msg) throws AdaptorException {
86 85 JsonElement json = getJson(msg);
87 86 String deviceName = checkDeviceName(getDeviceName(json));
88 87 String deviceType = getDeviceType(json);
89   - onDeviceConnect(deviceName, deviceType);
90   - ack(msg);
  88 + Futures.addCallback(onDeviceConnect(deviceName, deviceType), new FutureCallback<GatewayDeviceSessionCtx>() {
  89 + @Override
  90 + public void onSuccess(@Nullable GatewayDeviceSessionCtx result) {
  91 + ack(msg);
  92 + }
  93 +
  94 + @Override
  95 + public void onFailure(Throwable t) {
  96 + log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, t);
  97 +
  98 + }
  99 + }, context.getExecutor());
91 100 }
92 101
93   - private void onDeviceConnect(String deviceName, String deviceType) {
94   -// if (!devices.containsKey(deviceName)) {
95   -// Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), deviceName);
96   -// if (device == null) {
97   -// device = new Device();
98   -// device.setTenantId(gateway.getTenantId());
99   -// device.setName(deviceName);
100   -// device.setType(deviceType);
101   -// device.setCustomerId(gateway.getCustomerId());
102   -// device = deviceService.saveDevice(device);
103   -// relationService.saveRelationAsync(new EntityRelation(gateway.getId(), device.getId(), "Created"));
104   -// processor.onDeviceAdded(device);
105   -// }
106   -// GatewayDeviceSessionCtx ctx = new GatewayDeviceSessionCtx(this, device, mqttQoSMap);
107   -// devices.put(deviceName, ctx);
108   -// log.debug("[{}] Added device [{}] to the gateway session", gatewaySessionId, deviceName);
109   -// processor.process(new BasicTransportToDeviceSessionActorMsg(device, new BasicAdaptorToSessionActorMsg(ctx, new AttributesSubscribeMsg())));
110   -// processor.process(new BasicTransportToDeviceSessionActorMsg(device, new BasicAdaptorToSessionActorMsg(ctx, new RpcSubscribeMsg())));
111   -// }
  102 + private ListenableFuture<GatewayDeviceSessionCtx> onDeviceConnect(String deviceName, String deviceType) {
  103 + SettableFuture<GatewayDeviceSessionCtx> future = SettableFuture.create();
  104 + GatewayDeviceSessionCtx result = devices.get(deviceName);
  105 + if (result == null) {
  106 + transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder()
  107 + .setDeviceName(deviceName)
  108 + .setDeviceType(deviceType)
  109 + .setGatewayIdMSB(gateway.getDeviceIdMSB())
  110 + .setGatewayIdLSB(gateway.getDeviceIdLSB()).build(),
  111 + new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg>() {
  112 + @Override
  113 + public void onSuccess(GetOrCreateDeviceFromGatewayResponseMsg msg) {
  114 + GatewayDeviceSessionCtx deviceSessionCtx = new GatewayDeviceSessionCtx(GatewaySessionCtx.this, msg.getDeviceInfo(), mqttQoSMap);
  115 + if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) {
  116 + SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo();
  117 + transportService.process(deviceSessionInfo, MqttTransportHandler.getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null);
  118 + transportService.registerSession(deviceSessionInfo, deviceSessionCtx);
  119 + }
  120 + future.set(devices.get(deviceName));
  121 + }
  122 +
  123 + @Override
  124 + public void onError(Throwable e) {
  125 + log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e);
  126 + future.setException(e);
  127 + }
  128 + });
  129 + } else {
  130 + future.set(result);
  131 + }
  132 + return future;
112 133 }
113 134
114 135 public void onDeviceDisconnect(MqttPublishMessage msg) throws AdaptorException {
115   -// String deviceName = checkDeviceName(getDeviceName(getJson(msg)));
116   -// GatewayDeviceSessionCtx deviceSessionCtx = devices.remove(deviceName);
117   -// if (deviceSessionCtx != null) {
118   -// processor.process(SessionCloseMsg.onDisconnect(deviceSessionCtx.getSessionId()));
119   -// deviceSessionCtx.setClosed(true);
120   -// log.debug("[{}] Removed device [{}] from the gateway session", gatewaySessionId, deviceName);
121   -// } else {
122   -// log.debug("[{}] Device [{}] was already removed from the gateway session", gatewaySessionId, deviceName);
123   -// }
124   -// ack(msg);
  136 + String deviceName = checkDeviceName(getDeviceName(getJson(msg)));
  137 + deregisterSession(deviceName);
  138 + ack(msg);
  139 + }
  140 +
  141 + void deregisterSession(String deviceName) {
  142 + GatewayDeviceSessionCtx deviceSessionCtx = devices.remove(deviceName);
  143 + if (deviceSessionCtx != null) {
  144 + deregisterSession(deviceName, deviceSessionCtx);
  145 + } else {
  146 + log.debug("[{}] Device [{}] was already removed from the gateway session", sessionId, deviceName);
  147 + }
125 148 }
126 149
127 150 public void onGatewayDisconnect() {
128   -// devices.forEach((k, v) -> {
129   -// processor.process(SessionCloseMsg.onDisconnect(v.getSessionId()));
130   -// });
  151 + devices.forEach(this::deregisterSession);
131 152 }
132 153
133 154 public void onDeviceTelemetry(MqttPublishMessage mqttMsg) throws AdaptorException {
134   -// JsonElement json = validateJsonPayload(gatewaySessionId, mqttMsg.payload());
135   -// int requestId = mqttMsg.variableHeader().messageId();
136   -// if (json.isJsonObject()) {
137   -// JsonObject jsonObj = json.getAsJsonObject();
138   -// for (Map.Entry<String, JsonElement> deviceEntry : jsonObj.entrySet()) {
139   -// String deviceName = checkDeviceConnected(deviceEntry.getKey());
140   -// if (!deviceEntry.getValue().isJsonArray()) {
141   -// throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
142   -// }
143   -// BasicTelemetryUploadRequest request = new BasicTelemetryUploadRequest(requestId);
144   -// JsonArray deviceData = deviceEntry.getValue().getAsJsonArray();
145   -// for (JsonElement element : deviceData) {
146   -// JsonConverter.parseWithTs(request, element.getAsJsonObject());
147   -// }
148   -// GatewayDeviceSessionCtx deviceSessionCtx = devices.get(deviceName);
149   -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(),
150   -// new BasicAdaptorToSessionActorMsg(deviceSessionCtx, request)));
151   -// }
152   -// } else {
153   -// throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
154   -// }
155   - }
  155 + JsonElement json = JsonMqttAdaptor.validateJsonPayload(sessionId, mqttMsg.payload());
  156 + int msgId = mqttMsg.variableHeader().packetId();
  157 + if (json.isJsonObject()) {
  158 + JsonObject jsonObj = json.getAsJsonObject();
  159 + for (Map.Entry<String, JsonElement> deviceEntry : jsonObj.entrySet()) {
  160 + String deviceName = deviceEntry.getKey();
  161 + Futures.addCallback(checkDeviceConnected(deviceName),
  162 + new FutureCallback<GatewayDeviceSessionCtx>() {
  163 + @Override
  164 + public void onSuccess(@Nullable GatewayDeviceSessionCtx deviceCtx) {
  165 + if (!deviceEntry.getValue().isJsonArray()) {
  166 + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
  167 + }
  168 + TransportProtos.PostTelemetryMsg postTelemetryMsg = JsonConverter.convertToTelemetryProto(deviceEntry.getValue().getAsJsonArray());
  169 + transportService.process(deviceCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(channel, deviceName, msgId, postTelemetryMsg));
  170 + }
156 171
157   - public void onDeviceRpcResponse(MqttPublishMessage mqttMsg) throws AdaptorException {
158   -// JsonElement json = validateJsonPayload(gatewaySessionId, mqttMsg.payload());
159   -// if (json.isJsonObject()) {
160   -// JsonObject jsonObj = json.getAsJsonObject();
161   -// String deviceName = checkDeviceConnected(jsonObj.get(DEVICE_PROPERTY).getAsString());
162   -// Integer requestId = jsonObj.get("id").getAsInt();
163   -// String data = jsonObj.get("data").toString();
164   -// GatewayDeviceSessionCtx deviceSessionCtx = devices.get(deviceName);
165   -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(),
166   -// new BasicAdaptorToSessionActorMsg(deviceSessionCtx, new ToDeviceRpcResponseMsg(requestId, data))));
167   -// ack(mqttMsg);
168   -// } else {
169   -// throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
170   -// }
  172 + @Override
  173 + public void onFailure(Throwable t) {
  174 + log.debug("[{}] Failed to process device teleemtry command: {}", sessionId, deviceName, t);
  175 + }
  176 + }, context.getExecutor());
  177 + }
  178 + } else {
  179 + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
  180 + }
171 181 }
172 182
173 183 public void onDeviceAttributes(MqttPublishMessage mqttMsg) throws AdaptorException {
174   -// JsonElement json = validateJsonPayload(gatewaySessionId, mqttMsg.payload());
175   -// int requestId = mqttMsg.variableHeader().messageId();
176   -// if (json.isJsonObject()) {
177   -// JsonObject jsonObj = json.getAsJsonObject();
178   -// for (Map.Entry<String, JsonElement> deviceEntry : jsonObj.entrySet()) {
179   -// String deviceName = checkDeviceConnected(deviceEntry.getKey());
180   -// if (!deviceEntry.getValue().isJsonObject()) {
181   -// throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
182   -// }
183   -// long ts = System.currentTimeMillis();
184   -// BasicAttributesUpdateRequest request = new BasicAttributesUpdateRequest(requestId);
185   -// JsonObject deviceData = deviceEntry.getValue().getAsJsonObject();
186   -// request.add(JsonConverter.parseValues(deviceData).stream().map(kv -> new BaseAttributeKvEntry(kv, ts)).collect(Collectors.toList()));
187   -// GatewayDeviceSessionCtx deviceSessionCtx = devices.get(deviceName);
188   -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(),
189   -// new BasicAdaptorToSessionActorMsg(deviceSessionCtx, request)));
190   -// }
191   -// } else {
192   -// throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
193   -// }
  184 + JsonElement json = JsonMqttAdaptor.validateJsonPayload(sessionId, mqttMsg.payload());
  185 + int msgId = mqttMsg.variableHeader().packetId();
  186 + if (json.isJsonObject()) {
  187 + JsonObject jsonObj = json.getAsJsonObject();
  188 + for (Map.Entry<String, JsonElement> deviceEntry : jsonObj.entrySet()) {
  189 + String deviceName = deviceEntry.getKey();
  190 + Futures.addCallback(checkDeviceConnected(deviceName),
  191 + new FutureCallback<GatewayDeviceSessionCtx>() {
  192 + @Override
  193 + public void onSuccess(@Nullable GatewayDeviceSessionCtx deviceCtx) {
  194 + if (!deviceEntry.getValue().isJsonObject()) {
  195 + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
  196 + }
  197 + TransportProtos.PostAttributeMsg postAttributeMsg = JsonConverter.convertToAttributesProto(deviceEntry.getValue().getAsJsonObject());
  198 + transportService.process(deviceCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(channel, deviceName, msgId, postAttributeMsg));
  199 + }
  200 +
  201 + @Override
  202 + public void onFailure(Throwable t) {
  203 + log.debug("[{}] Failed to process device teleemtry command: {}", sessionId, deviceName, t);
  204 + }
  205 + }, context.getExecutor());
  206 + }
  207 + } else {
  208 + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
  209 + }
  210 + }
  211 +
  212 + public void onDeviceRpcResponse(MqttPublishMessage mqttMsg) throws AdaptorException {
  213 + JsonElement json = JsonMqttAdaptor.validateJsonPayload(sessionId, mqttMsg.payload());
  214 + int msgId = mqttMsg.variableHeader().packetId();
  215 + if (json.isJsonObject()) {
  216 + JsonObject jsonObj = json.getAsJsonObject();
  217 + String deviceName = jsonObj.get(DEVICE_PROPERTY).getAsString();
  218 + Futures.addCallback(checkDeviceConnected(deviceName),
  219 + new FutureCallback<GatewayDeviceSessionCtx>() {
  220 + @Override
  221 + public void onSuccess(@Nullable GatewayDeviceSessionCtx deviceCtx) {
  222 + Integer requestId = jsonObj.get("id").getAsInt();
  223 + String data = jsonObj.get("data").toString();
  224 + TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
  225 + .setRequestId(requestId).setPayload(data).build();
  226 + transportService.process(deviceCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(channel, deviceName, msgId, rpcResponseMsg));
  227 + }
  228 +
  229 + @Override
  230 + public void onFailure(Throwable t) {
  231 + log.debug("[{}] Failed to process device teleemtry command: {}", sessionId, deviceName, t);
  232 + }
  233 + }, context.getExecutor());
  234 + } else {
  235 + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
  236 + }
194 237 }
195 238
196 239 public void onDeviceAttributesRequest(MqttPublishMessage msg) throws AdaptorException {
197   -// JsonElement json = validateJsonPayload(gatewaySessionId, msg.payload());
198   -// if (json.isJsonObject()) {
199   -// JsonObject jsonObj = json.getAsJsonObject();
200   -// int requestId = jsonObj.get("id").getAsInt();
201   -// String deviceName = jsonObj.get(DEVICE_PROPERTY).getAsString();
202   -// boolean clientScope = jsonObj.get("client").getAsBoolean();
203   -// Set<String> keys;
204   -// if (jsonObj.has("key")) {
205   -// keys = Collections.singleton(jsonObj.get("key").getAsString());
206   -// } else {
207   -// JsonArray keysArray = jsonObj.get("keys").getAsJsonArray();
208   -// keys = new HashSet<>();
209   -// for (JsonElement keyObj : keysArray) {
210   -// keys.add(keyObj.getAsString());
211   -// }
212   -// }
213   -//
214   -// BasicGetAttributesRequest request;
215   -// if (clientScope) {
216   -// request = new BasicGetAttributesRequest(requestId, keys, null);
217   -// } else {
218   -// request = new BasicGetAttributesRequest(requestId, null, keys);
219   -// }
220   -// GatewayDeviceSessionCtx deviceSessionCtx = devices.get(deviceName);
221   -// processor.process(new BasicTransportToDeviceSessionActorMsg(deviceSessionCtx.getDevice(),
222   -// new BasicAdaptorToSessionActorMsg(deviceSessionCtx, request)));
223   -// ack(msg);
224   -// } else {
225   -// throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
226   -// }
  240 + JsonElement json = JsonMqttAdaptor.validateJsonPayload(sessionId, msg.payload());
  241 + if (json.isJsonObject()) {
  242 + JsonObject jsonObj = json.getAsJsonObject();
  243 + int requestId = jsonObj.get("id").getAsInt();
  244 + String deviceName = jsonObj.get(DEVICE_PROPERTY).getAsString();
  245 + boolean clientScope = jsonObj.get("client").getAsBoolean();
  246 + Set<String> keys;
  247 + if (jsonObj.has("key")) {
  248 + keys = Collections.singleton(jsonObj.get("key").getAsString());
  249 + } else {
  250 + JsonArray keysArray = jsonObj.get("keys").getAsJsonArray();
  251 + keys = new HashSet<>();
  252 + for (JsonElement keyObj : keysArray) {
  253 + keys.add(keyObj.getAsString());
  254 + }
  255 + }
  256 + TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder();
  257 + result.setRequestId(requestId);
  258 +
  259 + if (clientScope) {
  260 + result.addAllClientAttributeNames(keys);
  261 + } else {
  262 + result.addAllSharedAttributeNames(keys);
  263 + }
  264 + int msgId = msg.variableHeader().packetId();
  265 + TransportProtos.GetAttributeRequestMsg requestMsg = result.build();
  266 + Futures.addCallback(checkDeviceConnected(deviceName),
  267 + new FutureCallback<GatewayDeviceSessionCtx>() {
  268 + @Override
  269 + public void onSuccess(@Nullable GatewayDeviceSessionCtx deviceCtx) {
  270 + transportService.process(deviceCtx.getSessionInfo(), requestMsg, getPubAckCallback(channel, deviceName, msgId, requestMsg));
  271 + }
  272 +
  273 + @Override
  274 + public void onFailure(Throwable t) {
  275 + log.debug("[{}] Failed to process device teleemtry command: {}", sessionId, deviceName, t);
  276 + }
  277 + }, context.getExecutor());
  278 + ack(msg);
  279 + } else {
  280 + throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
  281 + }
227 282 }
228 283
229   - private String checkDeviceConnected(String deviceName) {
230   -// if (!devices.containsKey(deviceName)) {
231   -// log.debug("[{}] Missing device [{}] for the gateway session", gatewaySessionId, deviceName);
232   -// onDeviceConnect(deviceName, DEFAULT_DEVICE_TYPE);
233   -// }
234   -// return deviceName;
235   - return null;
  284 + private ListenableFuture<GatewayDeviceSessionCtx> checkDeviceConnected(String deviceName) {
  285 + GatewayDeviceSessionCtx ctx = devices.get(deviceName);
  286 + if (ctx == null) {
  287 + log.debug("[{}] Missing device [{}] for the gateway session", sessionId, deviceName);
  288 + return onDeviceConnect(deviceName, DEFAULT_DEVICE_TYPE);
  289 + } else {
  290 + return Futures.immediateFuture(ctx);
  291 + }
236 292 }
237 293
238 294 private String checkDeviceName(String deviceName) {
... ... @@ -253,32 +309,52 @@ public class GatewaySessionCtx {
253 309 }
254 310
255 311 private JsonElement getJson(MqttPublishMessage mqttMsg) throws AdaptorException {
256   -// return JsonMqttAdaptor.validateJsonPayload(gatewaySessionId, mqttMsg.payload());
257   - return null;
  312 + return JsonMqttAdaptor.validateJsonPayload(sessionId, mqttMsg.payload());
  313 + }
  314 +
  315 + private void ack(MqttPublishMessage msg) {
  316 + if (msg.variableHeader().packetId() > 0) {
  317 + writeAndFlush(MqttTransportHandler.createMqttPubAckMsg(msg.variableHeader().packetId()));
  318 + }
258 319 }
259 320
260   - protected SessionMsgProcessor getProcessor() {
261   -// return processor;
262   - return null;
  321 + void writeAndFlush(MqttMessage mqttMessage) {
  322 + channel.writeAndFlush(mqttMessage);
263 323 }
264 324
265   - DeviceAuthService getAuthService() {
266   -// return authService;
267   - return null;
  325 + public String getNodeId() {
  326 + return context.getNodeId();
268 327 }
269 328
270   - public void setChannel(ChannelHandlerContext channel) {
271   - this.channel = channel;
  329 + private void deregisterSession(String deviceName, GatewayDeviceSessionCtx deviceSessionCtx) {
  330 + transportService.deregisterSession(deviceSessionCtx.getSessionInfo());
  331 + transportService.process(deviceSessionCtx.getSessionInfo(), MqttTransportHandler.getSessionEventMsg(TransportProtos.SessionEvent.CLOSED), null);
  332 + log.debug("[{}] Removed device [{}] from the gateway session", sessionId, deviceName);
272 333 }
273 334
274   - private void ack(MqttPublishMessage msg) {
275   - if (msg.variableHeader().messageId() > 0) {
276   - writeAndFlush(MqttTransportHandler.createMqttPubAckMsg(msg.variableHeader().messageId()));
277   - }
  335 + private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final String deviceName, final int msgId, final T msg) {
  336 + return new TransportServiceCallback<Void>() {
  337 + @Override
  338 + public void onSuccess(Void dummy) {
  339 + log.trace("[{}][{}] Published msg: {}", sessionId, deviceName, msg);
  340 + if (msgId > 0) {
  341 + ctx.writeAndFlush(MqttTransportHandler.createMqttPubAckMsg(msgId));
  342 + }
  343 + }
  344 +
  345 + @Override
  346 + public void onError(Throwable e) {
  347 + log.trace("[{}] Failed to publish msg: {}", sessionId, deviceName, msg, e);
  348 + ctx.close();
  349 + }
  350 + };
278 351 }
279 352
280   - void writeAndFlush(MqttMessage mqttMessage) {
281   - channel.writeAndFlush(mqttMessage);
  353 + public MqttTransportContext getContext() {
  354 + return context;
282 355 }
283 356
  357 + public MqttTransportAdaptor getAdaptor() {
  358 + return context.getAdaptor();
  359 + }
284 360 }
... ...
... ... @@ -31,12 +31,7 @@ public abstract class MqttDeviceAwareSessionContext extends DeviceAwareSessionCo
31 31
32 32 private final ConcurrentMap<String, Integer> mqttQoSMap;
33 33
34   - public MqttDeviceAwareSessionContext(SessionMsgProcessor processor, DeviceAuthService authService, ConcurrentMap<String, Integer> mqttQoSMap) {
35   - super();
36   - this.mqttQoSMap = mqttQoSMap;
37   - }
38   -
39   - public MqttDeviceAwareSessionContext(SessionMsgProcessor processor, DeviceAuthService authService, Device device, ConcurrentMap<String, Integer> mqttQoSMap) {
  34 + public MqttDeviceAwareSessionContext(ConcurrentMap<String, Integer> mqttQoSMap) {
40 35 super();
41 36 this.mqttQoSMap = mqttQoSMap;
42 37 }
... ...
... ... @@ -15,9 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.transport.mqtt.session;
17 17
18   -import org.thingsboard.server.common.data.id.SessionId;
19   -
20   -import java.util.UUID;
21 18 import java.util.concurrent.atomic.AtomicLong;
22 19
23 20 /**
... ...
1 1 /**
2 2 * Copyright © 2016-2018 The Thingsboard Authors
3   - *
  3 + * <p>
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
  7 + * <p>
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + * <p>
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
12 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
... ... @@ -25,7 +25,9 @@ import org.springframework.stereotype.Service;
25 25 import org.thingsboard.server.common.transport.SessionMsgListener;
26 26 import org.thingsboard.server.common.transport.TransportService;
27 27 import org.thingsboard.server.common.transport.TransportServiceCallback;
28   -import org.thingsboard.server.gen.transport.TransportProtos;
  28 +import org.thingsboard.server.gen.transport.TransportProtos.*;
  29 +import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
  30 +import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg;
29 31 import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
30 32 import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
31 33 import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg;
... ... @@ -153,7 +155,7 @@ public class MqttTransportService implements TransportService {
153 155 try {
154 156 ToTransportMsg toTransportMsg = mainConsumer.decode(record);
155 157 if (toTransportMsg.hasToDeviceSessionMsg()) {
156   - TransportProtos.DeviceActorToTransportMsg toSessionMsg = toTransportMsg.getToDeviceSessionMsg();
  158 + DeviceActorToTransportMsg toSessionMsg = toTransportMsg.getToDeviceSessionMsg();
157 159 UUID sessionId = new UUID(toSessionMsg.getSessionIdMSB(), toSessionMsg.getSessionIdLSB());
158 160 SessionMsgListener listener = sessions.get(sessionId);
159 161 if (listener != null) {
... ... @@ -228,9 +230,16 @@ public class MqttTransportService implements TransportService {
228 230 }
229 231
230 232 @Override
  233 + public void process(GetOrCreateDeviceFromGatewayRequestMsg msg, TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg> callback) {
  234 + AsyncCallbackTemplate.withCallback(transportApiTemplate.post(msg.getTenantIdMSB() + msg.getTenantIdLSB() + msg.getDeviceName(),
  235 + TransportApiRequestMsg.newBuilder().setGetOrCreateDeviceRequestMsg(msg).build()),
  236 + response -> callback.onSuccess(response.getGetOrCreateDeviceResponseMsg()), callback::onError, transportCallbackExecutor);
  237 + }
  238 +
  239 + @Override
231 240 public void process(SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback) {
232 241 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
233   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  242 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
234 243 .setSessionEvent(msg).build()
235 244 ).build();
236 245 send(sessionInfo, toRuleEngineMsg, callback);
... ... @@ -239,7 +248,7 @@ public class MqttTransportService implements TransportService {
239 248 @Override
240 249 public void process(SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback) {
241 250 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
242   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  251 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
243 252 .setPostTelemetry(msg).build()
244 253 ).build();
245 254 send(sessionInfo, toRuleEngineMsg, callback);
... ... @@ -248,52 +257,52 @@ public class MqttTransportService implements TransportService {
248 257 @Override
249 258 public void process(SessionInfoProto sessionInfo, PostAttributeMsg msg, TransportServiceCallback<Void> callback) {
250 259 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
251   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  260 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
252 261 .setPostAttributes(msg).build()
253 262 ).build();
254 263 send(sessionInfo, toRuleEngineMsg, callback);
255 264 }
256 265
257 266 @Override
258   - public void process(SessionInfoProto sessionInfo, TransportProtos.GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback) {
  267 + public void process(SessionInfoProto sessionInfo, GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback) {
259 268 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
260   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  269 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
261 270 .setGetAttributes(msg).build()
262 271 ).build();
263 272 send(sessionInfo, toRuleEngineMsg, callback);
264 273 }
265 274
266 275 @Override
267   - public void process(SessionInfoProto sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback) {
  276 + public void process(SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback) {
268 277 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
269   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  278 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
270 279 .setSubscribeToAttributes(msg).build()
271 280 ).build();
272 281 send(sessionInfo, toRuleEngineMsg, callback);
273 282 }
274 283
275 284 @Override
276   - public void process(SessionInfoProto sessionInfo, TransportProtos.SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback) {
  285 + public void process(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback) {
277 286 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
278   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  287 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
279 288 .setSubscribeToRPC(msg).build()
280 289 ).build();
281 290 send(sessionInfo, toRuleEngineMsg, callback);
282 291 }
283 292
284 293 @Override
285   - public void process(SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback) {
  294 + public void process(SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback) {
286 295 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
287   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  296 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
288 297 .setToDeviceRPCCallResponse(msg).build()
289 298 ).build();
290 299 send(sessionInfo, toRuleEngineMsg, callback);
291 300 }
292 301
293 302 @Override
294   - public void process(SessionInfoProto sessionInfo, TransportProtos.ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback) {
  303 + public void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback) {
295 304 ToRuleEngineMsg toRuleEngineMsg = ToRuleEngineMsg.newBuilder().setToDeviceActorMsg(
296   - TransportProtos.TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
  305 + TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)
297 306 .setToServerRPCCallRequest(msg).build()
298 307 ).build();
299 308 send(sessionInfo, toRuleEngineMsg, callback);
... ...